Just wait until it's done. It will be a really great HTTP library.
For example, last week as a learning exercise I implemented an OAuth client, which involves adding a bunch of stuff to the "Authorization" header of an HTTP request, none of which was ever mentioned in the original HTTP RFCs, let alone specified. Likewise, the HTTP RFCs have a fixed and rather small set of verbs, but things like DAV add a bunch more.
How can you balance the reliability of strict typing with all the HTTP extensions that expect anyone can stick arbitrary strings anywhere?
Taking your example of the Authorization header: that uses the `credentials` type, defined in RFC 2617 (https://tools.ietf.org/html/rfc2617), which ends up thus:
auth-scheme = token
auth-param = token "=" ( token | quoted-string )
credentials = auth-scheme #auth-param
That could be supported something like this: struct Credentials {
scheme: ~str,
parameters: ~[(~str, ~str)],
}
But then, Basic and Digest come into the mix, and they've got data that should be treated as data rather than text. I'll probably end up with renaming the struct above to ExtensionCredentials (oh no! it doesn't have a proper name!) and using an enum: enum Credentials {
BasicCredentials(BasicCredentials), // A new struct
DigestCredentials(DigestCredentials), // Ditto
ExtensionCredentials(ExtensionCredentials),
}
I've been playing in my mind with having traits to convert such things as custom credentials in some way without you needing to maintain it yourself in your own place, but it's not an easy problem however you dice it.In the end, it is all about balance, as you say, and I'm not sure precisely where the balance falls, yet. But I know it uses the type system a whole lot more than almost all of the code that's out there.
That follows through to many other aspects of e.g. web frameworks; there's a lot there where string typing is used. When rust-http is stable enough, I'll be getting on to my dream framework which will be astonishingly safe and bamboozlingly quick (to start and to run, if not quite to compile), incorporating and extending various ideas at present only present in Haskell frameworks and a couple of other similar language-frameworks (e.g. Ur/Web). It'll be fun!
I've been mostly a Python developer hitherto, but I'd never have tried something like this in Python—it simply wouldn't work. You need a type system like Rust's before it can work, but then it really works.
In this case (HTTP), it's easier (and more correct) to just leave them as stings. The general principle with network protocols is to be strict in what you send, and forgiving in what you receive.
I agree with you that the parse behaviour for HTTP headers is poorly defined. That's something I'll be wrestling with all the time.
Supported headers will be in one place and uncommon extension headers in another. Such, alas, is life. But really, the only time when I would expect this to cause any trouble at all is when new headers are added. Compare it with things like the CGI standard and how it handles headers and you'll realise it's not such a bad system.
I should make it quite clear that the specs are (unfortunately) only a starting point for rust-http. Where there are deviations, more leniency may be added. But it'll be added thoroughly and properly.
For example, https://github.com/spray/spray/blob/master/spray-http/src/ma...
My own header definitions are pretty clumsy at present; I'm just about up to the stage of improving that with macros now. (I didn't do that to start with so that I could write a few and get a feel for what it would need to be like.)
As I get further along, I intend to use the data from the Common Crawl, which fortuitously includes response headers, to see how my validation goes. Of course, that's only a small set of the real-world headers (cache ones in particular will be scarcely stressed by that at all). Validating request headers will be harder; I've still got to figure out what to do about that.
In the end, though, I'm determined that it will work and work well. Servo using it (and thus demanding robust HTTP support) will help with that goal.
Something I discovered a few hours ago, reading the specs: I believe this header should be valid, with the value being interpreted as the weak entity tag ``Super Encoding™``. I wonder how many clients or servers would support it? No idea yet.
etag: w/"=?US-ASCII?B?U3VwZXIg?= =?UTF-8?Q?Encoding=E2=84=A2?="Arbitrary string headers are essential. Conversion between the typed header and strings is part of the design (though only partially implemented at present). As for other extension-headers (as they are designated in RFC 2616), that's the header enum variant ExtensionHeader(~str, ~str).
It's been so long since I've played with netcat and HTTP that I can't remember if 'get' vs 'GET' "used to" work or not...
Still, might be something that should be possible to toggle with a flag (case insensitive parsing on/off or something like that).
Might also be useful to keep in mind that there are very real differences between HTTP/1.0 and HTTP/1.1. For browser-facing stuff, 1.1 should be fine these days(?) -- for apis etc, I don't know if "proper" 1.0 support makes sense or not.