<div dir="ltr">Alex,<div><br></div><div>Great discussion points! I just churned out some quick types that could be used, there's some types that I think are pretty unambiguous like HTTPMethod, but something like headers gets more complex very quickly. </div><div><br></div><div>Historically swift frameworks have tried tons of iterations of HTTPHeaders, but at the end of the day, every single one of them created significantly more problems than they solved. They were either unbearably slow, or so confusing to end users that every day was spent explaining them. URLRequest in Foundation has also opted for what amounts to [String: String] as well. In practice, it's probably something closer to [caseInsensitive: [String?]?] I believe. At vapor we have [HeaderKey: String] with some literal convertibles which has been pretty easy to interact with.<br><br>The reason for the header model was a consideration of how HTTPHeaders are parsed. We could debate about usefulness to end user and best model for that, but instead let's leave that up to frameworks. Let's not focus on that. </div><div><br></div><div>Since this is a parser, I'd opt for something more general like `[String: String?]` (would need to check on the optional there), because that's how the parser will likely receive it, ie:<br><br>Key: Value\r\n<br>Other-Key: OtherValue\r\n<br><br>Then inside the initializer, the model would modify it, create arrays or custom headers models as they see fit. This allows the server side apis to opt out out of taking too many opinions and lets frameworks decide what's best for them. Many want simple [String: String], at Vapor we use [HeaderKey: String] for case insensitivity, some might want something that's considered more "correct" as [CaseInsensitive: [String?]?] or something.</div><div><br></div><div>All of these are arguably valid, so I think taking the approach of Parser's perspective and how things are received would be a good paradigm to strive towards.</div><div><br></div><div>The one thing missing in my example is order, which perhaps `[(String, String?)]` would be better if there are significant implications for order here to an end model. </div><div><br></div><div>- Logan</div></div><br><div class="gmail_quote"><div dir="ltr">On Thu, Mar 23, 2017 at 11:00 AM Alex Blewitt <<a href="mailto:alblue@apple.com">alblue@apple.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><br class="gmail_msg">
> On 23 Mar 2017, at 09:51, Logan Wright via swift-server-dev <<a href="mailto:swift-server-dev@swift.org" class="gmail_msg" target="_blank">swift-server-dev@swift.org</a>> wrote:<br class="gmail_msg">
><br class="gmail_msg">
> Here's an example of a protocol required to parse a request<br class="gmail_msg">
<br class="gmail_msg">
I agree in principle, thinking in protocols is a good way of defining what an API should look like and how it should interact.<br class="gmail_msg">
<br class="gmail_msg">
> ```<br class="gmail_msg">
> protocol HTTPMessage {<br class="gmail_msg">
> init(status: String, version: String, method: String, headers: [String: String], etc...<br class="gmail_msg">
> }<br class="gmail_msg">
> ```<br class="gmail_msg">
<br class="gmail_msg">
This is a good example, in that it brings up a number of other questions. For example: the 'status' is a String here. Why not an enum or an int?<br class="gmail_msg">
<br class="gmail_msg">
In addition, the headers are a dictionary of [String:String]. However, HTTP headers can be repeated and it's possible to get the first or a list of values for the repeated header, so using a dictionary isn't sufficient. In addition the headers dictionary has an implicit assumption about the fact they're stored as values (for example). You'd need to have a separate protocol for representing the headers in order to permit multiple implementations.<br class="gmail_msg">
<br class="gmail_msg">
Discussing the protocols helps understand the problems from two perspectives; from an end user's view of the software, and from a framework implementor's view of the software.<br class="gmail_msg">
<br class="gmail_msg">
> It doesn't need to be anything particularly complex, and we could include easily the inverse as well for the serializer. This could be a distinct protocol even for use cases we might not consider.<br class="gmail_msg">
><br class="gmail_msg">
> I'd like to just put up a quick reminder that we're not building a framework here, we're building core apis that are intended to be flexible and useful for framework developers. With something like this, we could easily conform foundation's URLRequest or NSURLRequest by default so basic users could use those built in without much effort, but framework developers wouldn't be stuck constantly dealing with non-native objects or doing unnecessary conversions.<br class="gmail_msg">
><br class="gmail_msg">
> This doesn't take away from anything that has been proposed so far, and creates additional capabilities and flexibilities for a system that is intended to be just that ... flexible. In general, I think it's important for us to remind ourselves what we're building and that creating the most flexible possible code will make the library more lasting and allow users to create unique and interesting interactions that we might not have even considered in our narrow scope. We want to support and encourage this creativity, not stifle it, wherever possible. Looking forward to working through more of this.<br class="gmail_msg">
<br class="gmail_msg">
<br class="gmail_msg">
Alex<br class="gmail_msg">
</blockquote></div>