[swift-server-dev] Proposal: Strictly-typed HTTPHeader values
Amir Abbas Mousavian
a.mosavian at gmail.com
Sun Nov 19 16:35:43 CST 2017
I strongly believe we should implement typed header here. Real
frameworks which would be placed atop of this framework must focus on
things like "what is appropriate response (header and body) for this
request" or "how to implement authentication" or "validating
input/output" rather than basic things like "parsing headers" or
"(de)compressing data" or "decrypting/encrypting".
I think this PR falls into "Provide low level HTTP parsing" category
listed in https://github.com/swift-server/work-group#current-focus-areas
These are common headers and every "real framework" have to implement
this independently! It will parse raw strings into meaningful
Foundation or Swift types and allows cleaner code (using switch case)
and much less unintended and undetectable bugs which means secure
codes. These accessors would decrease code lines significantly and
would encourage developers to focus on "logic" instead of "handworks"
We are not changing that underlying `[(String:String)]` architecture
and these accessors are lazy-loaded thus won't impose performance
overhead on loading. Strict typed storage will hit performance
significantly and will restrict users to have custom header values.
> Date: Sun, 19 Nov 2017 17:07:59 +0100
> From: Helge Heß <me at helgehess.eu>
> as I already wrote in the issue:
> I think we already discussed this kind of stuff and decided not to do typed headers at this level of the framework. It would be part of a real framework on top of this driver.
> If we really go the route of typed headers (which I personally kinda like for efficiency), we should actually do that in the storage itself, not just wrapping the String key/value. I wrote some email on that in the list.
> Since `[(String:String)]` seems to be what people decided to use (we discussed that a few times, too), I think this stuff should just live in a separate package (which higher level frameworks can use or not). It far exceeds the minimalist route this thing was trying to go.
>> On 17. Nov 2017, at 17:39, Amir Abbas Mousavian via swift-server-dev <swift-server-dev at swift.org> wrote:
>> HTTP headers are simply defined as a pair of strings. But for many of headers there is a set of defined values or a structured value. Current implementation is prone to typo and human errors which will raise hard-to-debug errors. So I propose to have strictly-typed getters/setters for frequent ones.
>> I implemented my proposal draft in https://github.com/swift-server/http/pull/104
>> 📝 Please note:
>> - `Cookie`, `Set-Cookie` and ` Authorization` accessors are not implemented yet and marked as TODO in source code. Also test cases are not implemented yet. I will implement them in this or another PR.
>> - I believe raw string should be accessible by developer thus better to implement as HTTPHeaders properties rather than typing storage object. This design allows lazy parsing.
>> - Some setters are not necessary for a server (marked as Request headers). I implemented them but we can discuss to remove or having them in portfolio.
>> - Getter accessors of headers such as Accept-Encoding returns sorted values according to `q` parameter, thus developer would not need to know exact value of q parameter imo.
>> - Validating input values is out of scope. It imposes overhead with little benefit, e.g. EntryTag.wildcard is not a valid value for eTag, but it won't be checked by setter. Same situation for contentCache.
>> - ContentType struct doesn't embed parameters such as charset. I’ve implemented charset as a separate property `contentCharset` which manipulates underlying Content-Type. We may revise this design and implementing a struct which holds other parameters too.
More information about the swift-server-dev