<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div><blockquote type="cite" class=""><div class="">On Mar 27, 2017, at 6:23 PM, Helge Heß via swift-server-dev &lt;<a href="mailto:swift-server-dev@swift.org" class="">swift-server-dev@swift.org</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><div class=""><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;" class="">I've got a PR for one of those, as well as for non-`inout` argument passing: &lt;<a href="https://github.com/tanner0101/request-types/pull/2" class="">https://github.com/tanner0101/request-types/pull/2</a>&gt;<br class=""></blockquote><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">"A HybridRequest is a struct with a private nested class”</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">That way you have the overhead of ARC *and* a struct :-) Well if your struct is just the pointer, so why not use the class in the first place? Just to get copy behavior which I don’t think played a huge role in the discussion</span></div></div></blockquote><div><br class=""></div><div>Ideally, the *only* consideration should be whether we want value semantics (each portion of the system has a separate copy of the request; mutating one doesn't affect the others) or we want reference semantics (all portions share the same copy; mutating one affects the others; you probably need to synchronize access somehow, which could be tricky). The point of the hybrid design is that, if a design using reference semantics would be faster but we'd prefer value semantics instead, hybrid ought to give us the speed benefits of both.</div><br class=""><blockquote type="cite" class=""><div class=""><div class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">(well, someone even claimed non-copy behavior actually reduces bugs ;-)</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""></div></div></blockquote><div><br class=""></div><div>I saw that claim, but to tell the truth, I find it so astonishing that I don't think I can believe it without hearing what kinds of bugs were happening due to copying. The person making that claim has been asked to clarify and hasn't yet, so...I simply don't believe it right now.</div><br class=""><blockquote type="cite" class=""><div class=""><div class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">I was thinking more along the lines of using UnsafePointer with an own (unprotected) retain count. Not sure whether that is even possible in Swift. (the idea being that the RC of a request isn’t modified by multiple threads ever).</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""></div></div></blockquote><div><br class=""></div><div>It's not possible to maintain your own reference count because you can't detect when a struct is copied. (Swift does not have anything equivalent to a C++ copy constructor.)</div><br class=""><blockquote type="cite" class=""><div class=""><div class=""><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;" class="">Is the use of `inout` here purely a performance hack, or is it semantically significant?<br class=""></blockquote><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">That depends on the higher level framework. Some store values (like a restored session) in the request, others may use secondary objects for that.</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""></div></div></blockquote><div><blockquote type="cite" class=""><br class=""></blockquote></div><blockquote type="cite" class=""><div class=""><div class=""><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;" class="">That is, are you *supposed* to write into the request in ways that middlewares above you will see?<br class=""></blockquote><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">You mean below in the sequence? Yes. This is what Node does. E.g. middleware could parse Basic Auth and store a REMOTE_USER variable into the request. Or parse a session cookie, retrieve that and then attach the session to the request.</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""></div></div></blockquote><div><br class=""></div><div><div>Well, but if you added something to the session, you wouldn't want it to be visible to middleware *earlier* in the chain, right?</div><div><br class=""></div><div>To illustrate what I mean, suppose your request type has a `userInfo` dictionary that middlewares are supposed to use to attach additional information to a request. Let's further suppose—for the sake of simplicity—that your middleware stack is synchronous (the same considerations apply if it's not, just a little bit differently):</div><div><br class=""></div><div><span class="Apple-tab-span" style="white-space: pre;">        </span>protocol WebResponder: class {</div><div><span class="Apple-tab-span" style="white-space: pre;">                </span>func respond(to request: WebRequest) -&gt; WebResponse</div><div><span class="Apple-tab-span" style="white-space: pre;">                </span>var next: WebResponder?</div><div><span class="Apple-tab-span" style="white-space: pre;">        </span>}</div><div><br class=""></div><div>Then a session middleware would look something like this:</div><div><br class=""></div><div><span class="Apple-tab-span" style="white-space: pre;">        </span>class Session {</div><div><span class="Apple-tab-span" style="white-space: pre;">                </span>private&nbsp;static&nbsp;let key = "SessionMiddleware.Session"</div><div><span class="Apple-tab-span" style="white-space:pre">                </span></div><div><span class="Apple-tab-span" style="white-space: pre;">                </span>init(from request: WebRequest) { … }</div><div><span class="Apple-tab-span" style="white-space: pre;">                </span>func write(to response: inout WebResponse) { … }</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">                </span></div><div><span class="Apple-tab-span" style="white-space: pre;">                </span>private var storage: [String: Any]</div><div><span class="Apple-tab-span" style="white-space: pre;">                </span>…</div><div><span class="Apple-tab-span" style="white-space: pre;">        </span>}</div><div><span class="Apple-tab-span" style="white-space: pre;">        </span></div><div><span class="Apple-tab-span" style="white-space: pre;">        </span>class SessionMiddleware: WebResponder {</div><div><span class="Apple-tab-span" style="white-space: pre;">                </span>func respond(to request: WebRequest) -&gt; WebResponse {</div><div><span class="Apple-tab-span" style="white-space: pre;">                        </span>let session = Session(from: request)</div><div><span class="Apple-tab-span" style="white-space: pre;">                        </span>var requestWithSession = request</div><div><span class="Apple-tab-span" style="white-space: pre;">                        </span>requestWithSession.userInfo[Session.key] = session</div><div><span class="Apple-tab-span" style="white-space: pre;">                        </span></div><div><span class="Apple-tab-span" style="white-space: pre;">                        </span>var response =&nbsp;next!.respond(to: requestWithSession)</div><div><span class="Apple-tab-span" style="white-space: pre;">                        </span></div><div><span class="Apple-tab-span" style="white-space: pre;">                        </span>session.write(to: &amp;response)</div><div><span class="Apple-tab-span" style="white-space: pre;">                        </span>return response</div><div><span class="Apple-tab-span" style="white-space: pre;">                </span>}</div><div><span class="Apple-tab-span" style="white-space: pre;">        </span>}</div><div><span class="Apple-tab-span" style="white-space: pre;">                </span></div><div>If `WebRequest` is a value type, then this is invisible to the middleware that comes before SessionMiddleware and all the previous ones (except for whatever headers `session.write(to:)` might have added to the response). If `WebRequest` is a reference type, then this is *visible* to those middlewares, all the way up to the original web server. I don't think that would really make sense—`request` ought to reflect the request they processed, not whatever rewriting or modification subsequent middlewares might have done.</div><div><br class=""></div><div>Now, having said all that, `WebRequest` would probably be a type from whatever framework provided `WebResponder`, not the low-level HTTP parsing type. If the intent is for this type to be used *only* for the HTTP parser to communicate with its direct user, and *especially* if we only need to create the type or we only need to create and read it (not mutate it), then the choice of value or reference semantics doesn't matter very much.</div><div><br class=""></div><div>But honestly, I hope we're planning to be a little more ambitious than that. I know it's not in scope at this point, but in the long term, I think we would benefit from a common web server interface and middleware stack. My model here is Ruby's Rack, which has been a *huge* boon for web development on Ruby: it lets you mix-and-match servers and frameworks, and it also means that a lot of basic functionality (like parameter and cookie parsing, logfile generation, error pages, static file serving, even routing if you want) can be shared between multiple frameworks as common middleware. Rack makes it really easy to get a web framework off the ground in Ruby; in the long run, I think Swift would benefit from something similar.</div><div><br class=""></div></div><blockquote type="cite" class=""><div class=""><div class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">It is questionable whether this is actually a good design, but this is what Node does and people are accustomed to. Hence some implement it that way.</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;" class="">If so, I question whether that's a good idea—it seems to me that communication back up the stack should be through the response, not the request.<br class=""></blockquote><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">Something a web framework needs to decide. Personally I prefer the WebObjects setup where the request is just the request and the response is just the response, and all framework state is attached to a separate context.</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""></div></div></blockquote></div><div class=""><br class=""></div><div class="">That certainly might make sense. It's sensible to think of the method/path/headers as one of many pieces of data comprising a "request"; if so, the main question is simply which of the two things gets the name "Request" and what the other one gets called.</div><div class=""><br class=""></div><div class="">(But if that's the approach we're going to take—you're expected to make this type a property in your Context/Environment/RequestResponseCycle/Whatever type—then I still think this either needs to be a value type, or a reference type that's designed to be compatible with COW wrappers. You can always box a value-semantics type to give it reference semantics, but some reference-semantics designs can be pretty difficult to give value semantics to.)</div><br class=""><div class="">
<span class="Apple-style-span" style="border-collapse: separate; font-variant-ligatures: normal; font-variant-position: normal; font-variant-numeric: normal; font-variant-alternates: normal; font-variant-east-asian: normal; line-height: normal; border-spacing: 0px;"><div class=""><div style="font-size: 12px; " class="">--&nbsp;</div><div style="font-size: 12px; " class="">Brent Royal-Gordon</div><div style="font-size: 12px; " class="">Architechies</div></div></span>

</div>
<br class=""></body></html>