<div dir="ltr">I guess we need two storages after all.. but instead of lowercasing in the dictionary storage we could keep Field.<div><br></div><div>public struct HTTPHeaders {</div><div> public var original: [(String, String)]</div><div> public var headers: [Field: [String]]</div><div>}</div><div><br></div><div>This way we have:</div><div><br></div><div><div style="font-size:12.800000190734863px">- We don't have to do lowercase on all headers even if they're not needed later.</div><div style="font-size:12.800000190734863px">- The case insensitive comparison from Field is done when the user actually needs the header.</div><div style="font-size:12.800000190734863px">- We maintain the original order of the http message in cases of proxying by providing original.</div><div style="font-size:12.800000190734863px">- Retrieval is done in O(1) from headers.</div><div style="font-size:12.800000190734863px"><br></div><div style="font-size:12.800000190734863px">But we don't have single source of truth.. which might not be that bad and we also might get a penalty by adding to both storages.</div><div class="gmail_extra"><br><div class="gmail_quote">On 30 May 2017 at 11:41, Paulo Faria <span dir="ltr"><<a href="mailto:paulo@zewo.io" target="_blank">paulo@zewo.io</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir="ltr">oh.. scratch that.. the ordered dict won't help with proxying at all.. ouch.</div><div class="gmail-HOEnZb"><div class="gmail-h5"><div class="gmail_extra"><br><div class="gmail_quote">On 30 May 2017 at 11:40, Paulo Faria <span dir="ltr"><<a href="mailto:paulo@zewo.io" target="_blank">paulo@zewo.io</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir="ltr">Hi, Johannes!<div><br></div><div>You're right. It helps performance by not having to go through all the headers and lowercase then when they might not be needed during request handling. This worked well in my own code because I used a dictionary as a backing storage, having O(1) retrieval. Ideally the best backing storage would be:</div><div><br></div><div>OrderedDictionary<Field, [String]></div><div><br></div><div>- This way we have a single source of truth (another problem with the two storages approach)</div><div>- We don't have to do lowercase on all headers even if they're not needed later.</div><div>- The case insensitive comparison from Field is done when the user actually needs the header.</div><div>- We maintain the original order of the http message in cases of proxying.</div><div>- Retrieval is done in O(1) </div><div><br></div><div>Cheers,</div><div>Paulo</div></div><div class="gmail-m_7926215604433893904HOEnZb"><div class="gmail-m_7926215604433893904h5"><div class="gmail_extra"><br><div class="gmail_quote">On 30 May 2017 at 11:29, Johannes Weiss <span dir="ltr"><<a href="mailto:johannesweiss@apple.com" target="_blank">johannesweiss@apple.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex">Hi,<br>
<span><br>
> On 27 May 2017, at 2:18 pm, Paulo Faria via swift-server-dev <<a href="mailto:swift-server-dev@swift.org" target="_blank">swift-server-dev@swift.org</a>> wrote:<br>
><br>
> Michael, I narrowed the scope of the proposal and focused the rationale. I answered your comments about switch for HTTPMethod and HTTPStatus. Basically, we can switch on them because I implemented the pattern matching operator ~=. I also removed the HTTPMessage as it is not *needed* and users can define it and make HTTPRequest and HTTPResponse conform to it in extensions in their own module.<br>
><br>
> <a href="https://github.com/paulofaria/http-api-proposal#rationale" rel="noreferrer" target="_blank">https://github.com/paulofaria/<wbr>http-api-proposal#rationale</a><br>
><br>
> Carl, Helge, Chris and Rien what do you think about the code? This is pretty close to what Carl suggested.<br>
><br>
> The main differences are..<br>
><br>
> HTTPVersion as a struct.<br>
> HTTPHeaders backed by a single array storage and case insensitive checking is done with the Field type to improve performance.<br>
<br>
</span>not opposed to having a 'Field', but how does that improve performance? It reduces memory usage but having a single list makes the lookup of a certain header field with .filter O(n) instead of O(1).<br>
<span><br>
<br>
> HTTPMethod as a struct instead of enum with pattern matching added allowing switch cases. (pointed by Helge)<br>
> HTTPStatus as a struct instead of enum with pattern matching added allowing switch cases. (pointed by Helge)<br>
<br>
</span>happy with those. Except the proposed hashing functions<br>
<br>
return method.hashValue ^ uri.hashValue ^ version.hashValue ^ headers.hashValue<br>
<br>
is really not appropriate but I guess it's more a proof of concept.<br>
<span class="gmail-m_7926215604433893904m_-4072416666985949624HOEnZb"><font color="#888888"><br>
-- Johannes<br>
</font></span><span class="gmail-m_7926215604433893904m_-4072416666985949624im gmail-m_7926215604433893904m_-4072416666985949624HOEnZb"><br>
<br>
> Apart from that there's only naming differences. I added some tests to showcase what I mentioned.<br>
><br>
> <a href="https://github.com/paulofaria/http-api-proposal/blob/master/Tests/HTTPTests/HTTPTests.swift" rel="noreferrer" target="_blank">https://github.com/paulofaria/<wbr>http-api-proposal/blob/master/<wbr>Tests/HTTPTests/HTTPTests.swif<wbr>t</a><br>
><br>
> On 27 May 2017 at 08:41, Michael Chiu <<a href="mailto:hatsuneyuji@icloud.com" target="_blank">hatsuneyuji@icloud.com</a>> wrote:<br>
> The thing is, as I have mentioned before if we move on that route we have to have a well defined structure before hand, for example, there’s no such protocol “Message” in what Johannes proposed.<br>
><br>
> As Chris and Carl mentioned before, this is only a prototype of the discussed API, so at least we have something to test, experiment and branchmark on.<br>
><br>
> Also things like WebApp in Johannes’ proposal can easily remove without huge changes, since WebApp is simply a typealias. I really don’t think that’s a big issue, every other parts of the prototype is in fact pretty http-specific.<br>
><br>
> Yes the prototype might dependent on some other frameworks like blue socket, but that’s how we can at least test and branchmark.<br>
><br>
> Sincerely<br>
> Michael<br>
><br>
><br>
>> On May 27, 2017, at 4:06 AM, Paulo Faria <<a href="mailto:paulo@zewo.io" target="_blank">paulo@zewo.io</a>> wrote:<br>
>><br>
>> Sorry if I'm being annoying, but I really feel what we lack is process. There's no formal proposal and proposal review. I really think we should move incrementally with well defined scopes and deadlines for every round. We didn't have that so far. Carl and others said that my suggestion is counter productive. I think the opposite, of course, as what I'm proposing is a well defined process where when we settle on a design for a particular set of base APIs then we move on to a higher absctraction. This way we won't be discussing the same things over and over again. I'll repeat, if we can't agree on the base types how can we move on? I'm saying let's first *settle* on Version, Headers, Message, Request and Response. Really *define* the API so then we move on, incrementally, from lower abstraction to higher abstraction.<br>
>><br>
>><br>
>><br>
>> On May 27, 2017 07:53, "Paulo Faria" <<a href="mailto:paulo@zewo.io" target="_blank">paulo@zewo.io</a>> wrote:<br>
>> I'm just proposing we move the code incrementally. The "most consentual" list I sent yesterday isn't radically different from the code Johannes proposed. I really don't want to discuss this over and over, ad infinitum. The most important in the messages I sent before is that we need a well defined process. We don't have it. Just taking the first implementation, with a lot of things that admitedly don't fit the scope, and adding that so we can rework doesn't feel right to me. I'm actually confused about the scope this project is taking. The code there explicitly mentions a WebApp, which is a higher responsibility than HTTP. When we started this project the scope as very clear. Crypto/TLS, Socket, HTTP. A well designed HTTP module shouldn't depend *at all* on the socket implementation. Providing an implementation would be just a matter of injecting a dependency. Moving that code as is to the org really doesn't feel right to me. All I'm saying is that we definitely should start having code on the org. But I say we move first Version, Headers, Message, Request, Response. And again, the "least controversial" I sent yesterday isn't radically strange. It's an evolution of Johaness original proposal, plus Carl's, plus Helge's suggestions, plus my suggestions. The only thing I added that wasn't discussed before is HTTPHeader.Field which does a case insensitive comparison in its equatable implementation, and the Message protocol which holds the properties common to request and response (version and headers). If we can't agree on that, which is the sum of everything that was discussed about these particular types. How can we agree on that full implementation?<br>
>><br>
>> On May 27, 2017 05:13, "Michael Chiu" <<a href="mailto:hatsuneyuji@icloud.com" target="_blank">hatsuneyuji@icloud.com</a>> wrote:<br>
>> Hi Carl<br>
>><br>
>><br>
>> > This email thread isn’t about an API proposal. It’s about a prototype implementation of an API that was already proposed and discussed a month and a half ago. The prototype isn't a full-featured framework like Vapor or Kitura, but it does actually work and it even has XCTests with decent (>75%) code coverage.<br>
>><br>
>> I see, I was confused by the email contents instead of reading the subject and thought we are finally implementing some code. TBH, I don’t see any reason why this should not move to swift-server on github, It sounds a good start to me.<br>
>> Thank you guys’ hard work for building it.<br>
>><br>
>> > Also, please note that I didn’t play any part in proposing this API back in March/April - it’s not “Carl’s proposal.” I just took the existing API that the group had previously discussed and implemented enough of it so that we could measure the utility and performance of the API as proposed and so that we could have better informed discussions about potential alternatives.<br>
>><br>
>> You’re right. it was Johannes’ proposal, I’m so sorry for that.<br>
>><br>
>> Michael.<br>
>><br>
>><br>
><br>
><br>
</span><div class="gmail-m_7926215604433893904m_-4072416666985949624HOEnZb"><div class="gmail-m_7926215604433893904m_-4072416666985949624h5">> ______________________________<wbr>_________________<br>
> swift-server-dev mailing list<br>
> <a href="mailto:swift-server-dev@swift.org" target="_blank">swift-server-dev@swift.org</a><br>
> <a href="https://lists.swift.org/mailman/listinfo/swift-server-dev" rel="noreferrer" target="_blank">https://lists.swift.org/mailma<wbr>n/listinfo/swift-server-dev</a><br>
<br>
<br>
</div></div></blockquote></div><br></div>
</div></div></blockquote></div><br></div>
</div></div></blockquote></div><br></div></div></div>