<div dir="ltr">Hi George,<div><br></div><div>This seems interesting, but is it necessary for getting off the ground? Unless I&#39;m missing something (it&#39;s been known to happen!) a protocol based approach could be implemented purely additively, on top of the concrete design Johannes has proposed, at a later date. </div><div><br></div><div>The advantage I see in waiting is that we can get more feedback from real users of the API, such as what extension points they want and need, where their performance concerns are, etc. We would also be able to make sure it integrates well with what the community has been doing around higher level libraries, middleware, etc.</div><div><br></div><div>-C<br><br><div class="gmail_quote"><div dir="ltr">On Sun, Apr 9, 2017 at 9:23 PM George Leontiev via swift-server-dev &lt;<a href="mailto:swift-server-dev@swift.org">swift-server-dev@swift.org</a>&gt; wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word" class="gmail_msg"><div class="gmail_msg">I’ve fleshed out my earlier suggestion.</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">For responses coming back from a server or requests going to a server I like what Helge referred to as a “parser delegate” (naming suggestions welcome) because it allows us to parse the request or response exactly as it comes of the wire, and make no assumptions about how the user wants that data. Also, this API can be used with both an async API (built on top of dispatch) but could also be leveraged to create a synchronous API. </div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">In terms of utility, I like that clients can provide their own HTTPResponseDecoders which can decode to the specific type they are expecting from that endpoint. Servers, on the other hand, can perform their routing logic while processing that path and use the results of that to more appropriately decode the rest of the request. </div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">As I and Helge mentioned, there is overhead to using a protocol cross-module, but the benefit is that we no longer have to have a catch-all type to represent a decoded request or response; this allows users who care about performance to encode their concrete types as efficiently as they can. We can also have a catch-all type provided by the standard library which leaves all the fields as strings (indeed, it can be backed by the actual request data and just point to ranges) and would benefit from full-module optimization. Even better, we can make an opinionated concrete implementation (which can use enums for stata and headers and enforce things like the ContentType header value should always be a MediaType, etc.) but allow specialized applications which need more exotic semantics to fall back to implementing their own type (instead of having `.custom(…)` enum cases)</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">Note: I specifically omitted the body implementation and we may need something like Johannes’  *Writer API to support sending chunked things.</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">- George</div><div class="gmail_msg"><br class="gmail_msg"></div>Code:<div class="gmail_msg"><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">// MARK: - Stubs</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"></span><br class="gmail_msg"></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(186,45,162)" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">public</span><span style="font-variant-ligatures:no-common-ligatures;color:#000000" class="gmail_msg"> </span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">protocol</span><span style="font-variant-ligatures:no-common-ligatures;color:#000000" class="gmail_msg"> HTTPBody {</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures;color:#000000" class="gmail_msg">    </span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">// API omitted.</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures;color:#000000" class="gmail_msg">    </span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">// There are decisions about how to handle streaming bodies which are outside the scope of this example.</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">}</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"></span><br class="gmail_msg"></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">// Definition omitted</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">public</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> </span><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">typealias</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> HTTPHeader = </span><span style="font-variant-ligatures:no-common-ligatures;color:#703daa" class="gmail_msg">Void</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"></span><br class="gmail_msg"></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">public</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> </span><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">struct</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> PathIterator: </span><span style="font-variant-ligatures:no-common-ligatures;color:#703daa" class="gmail_msg">IteratorProtocol</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> {</span></div><p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">    </span><br class="m_8872408226744841416webkit-block-placeholder gmail_msg"></p><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">    </span><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">func</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> next() -&gt; </span><span style="font-variant-ligatures:no-common-ligatures;color:#703daa" class="gmail_msg">String</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> {</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">        </span><span style="font-variant-ligatures:no-common-ligatures;color:#3e1e81" class="gmail_msg">fatalError</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">()</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">    }</span></div><p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">    </span><br class="m_8872408226744841416webkit-block-placeholder gmail_msg"></p><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">}</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"></span><br class="gmail_msg"></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">// MARK: - Body Decoder</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"></span><br class="gmail_msg"></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">public</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> </span><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">protocol</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> HTTPBodyDecoder {</span></div><p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">    </span><br class="m_8872408226744841416webkit-block-placeholder gmail_msg"></p><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">    </span><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">mutating</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> </span><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">func</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> decodeTrailingHeader(</span><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">_</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> key: </span><span style="font-variant-ligatures:no-common-ligatures;color:#703daa" class="gmail_msg">String</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">, value: </span><span style="font-variant-ligatures:no-common-ligatures;color:#703daa" class="gmail_msg">String</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">) </span><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">throws</span></div><p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">    </span><br class="m_8872408226744841416webkit-block-placeholder gmail_msg"></p><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">    </span><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">mutating</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> </span><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">func</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> decodeBodyChunk(</span><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">_</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> data: </span><span style="font-variant-ligatures:no-common-ligatures;color:#703daa" class="gmail_msg">Data</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">) </span><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">throws</span></div><p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">    </span><br class="m_8872408226744841416webkit-block-placeholder gmail_msg"></p><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">}</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"></span><br class="gmail_msg"></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">// MARK: - Server API</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"></span><br class="gmail_msg"></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">// A type which can be created from an HTTP Request as it is coming off the wire. Suggestions on naming are welcome!</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">public</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> </span><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">protocol</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> HTTPRequestDecoder: </span><span style="font-variant-ligatures:no-common-ligatures;color:#4f8187" class="gmail_msg">HTTPBodyDecoder</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> {</span></div><p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">    </span><br class="m_8872408226744841416webkit-block-placeholder gmail_msg"></p><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(186,45,162)" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures;color:#000000" class="gmail_msg">    </span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">associatedtype</span><span style="font-variant-ligatures:no-common-ligatures;color:#000000" class="gmail_msg"> Request</span></div><p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">    </span><br class="m_8872408226744841416webkit-block-placeholder gmail_msg"></p><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures;color:#000000" class="gmail_msg">    </span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">// Thrown exceptions terminate decoding</span></div><p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">    </span><br class="m_8872408226744841416webkit-block-placeholder gmail_msg"></p><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures;color:#000000" class="gmail_msg">    </span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">// Called before any other methods</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">    </span><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">mutating</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> </span><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">func</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> decodeMethod(</span><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">_</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> value: </span><span style="font-variant-ligatures:no-common-ligatures;color:#703daa" class="gmail_msg">String</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">) </span><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">throws</span></div><p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">    </span><br class="m_8872408226744841416webkit-block-placeholder gmail_msg"></p><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures;color:#000000" class="gmail_msg">    </span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">// Called after `decodeMethod` and before any other methods. Types conforming to `HTTPRequestDecoder` can use this method to walk the requested path and prepare to handle the rest of the request appropriately. Implementation does not need to exhaust the iterator.</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">    </span><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">mutating</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> </span><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">func</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> decodePath(</span><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">_</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> iterator: </span><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">inout</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> </span><span style="font-variant-ligatures:no-common-ligatures;color:#4f8187" class="gmail_msg">PathIterator</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">) </span><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">throws</span></div><p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">    </span><br class="m_8872408226744841416webkit-block-placeholder gmail_msg"></p><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures;color:#000000" class="gmail_msg">    </span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">// Called after all of the above methods, and before any methods below.</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">    </span><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">mutating</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> </span><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">func</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> decodeVersion(</span><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">_</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> value: </span><span style="font-variant-ligatures:no-common-ligatures;color:#703daa" class="gmail_msg">String</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">) </span><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">throws</span></div><p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">    </span><br class="m_8872408226744841416webkit-block-placeholder gmail_msg"></p><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures;color:#000000" class="gmail_msg">    </span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">// Called after all of the above methods and before any methods below. May be called multiple times</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">    </span><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">mutating</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> </span><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">func</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> decodeHeader(</span><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">_</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> key: </span><span style="font-variant-ligatures:no-common-ligatures;color:#703daa" class="gmail_msg">String</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">, value: </span><span style="font-variant-ligatures:no-common-ligatures;color:#703daa" class="gmail_msg">String</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">) </span><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">throws</span></div><p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">    </span><br class="m_8872408226744841416webkit-block-placeholder gmail_msg"></p><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures;color:#000000" class="gmail_msg">    </span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">// HTTPBodyDecoder methods conceptually appear here</span></div><p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">    </span><br class="m_8872408226744841416webkit-block-placeholder gmail_msg"></p><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures;color:#000000" class="gmail_msg">    </span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">// Returns an object to be used to represent the request</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">    </span><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">func</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> decoded() </span><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">throws</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> -&gt; Request</span></div><p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">    </span><br class="m_8872408226744841416webkit-block-placeholder gmail_msg"></p><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">}</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"></span><br class="gmail_msg"></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(79,129,135)" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">public</span><span style="font-variant-ligatures:no-common-ligatures;color:#000000" class="gmail_msg"> </span><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">extension</span><span style="font-variant-ligatures:no-common-ligatures;color:#000000" class="gmail_msg"> </span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">HTTPRequestDecoder</span><span style="font-variant-ligatures:no-common-ligatures;color:#000000" class="gmail_msg"> {</span></div><p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">    </span><br class="m_8872408226744841416webkit-block-placeholder gmail_msg"></p><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">    </span><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">mutating</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> </span><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">func</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> decodeVersion(</span><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">_</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> value: </span><span style="font-variant-ligatures:no-common-ligatures;color:#703daa" class="gmail_msg">String</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">) </span><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">throws</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> {</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures;color:#000000" class="gmail_msg">        </span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">// Implementing decodeVersion is not necessary</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">    }</span></div><p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">    </span><br class="m_8872408226744841416webkit-block-placeholder gmail_msg"></p><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">}</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"></span><br class="gmail_msg"></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">/**</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> A type which can be represented as an HTTP Response</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> */</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">public</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> </span><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">protocol</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> HTTPResponse {</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">    </span><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">var</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> statusCode: </span><span style="font-variant-ligatures:no-common-ligatures;color:#703daa" class="gmail_msg">UInt</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> { </span><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">get</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> }</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">    </span><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">var</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> headers: [</span><span style="font-variant-ligatures:no-common-ligatures;color:#4f8187" class="gmail_msg">HTTPHeader</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">] { </span><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">get</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> }</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">    </span><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">var</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> body: </span><span style="font-variant-ligatures:no-common-ligatures;color:#4f8187" class="gmail_msg">HTTPBody</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> { </span><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">get</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> }</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">}</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"></span><br class="gmail_msg"></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">// MARK: - Client API</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"></span><br class="gmail_msg"></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">/**</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> A type which can be represented as an HTTP Request</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> */</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">public</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> </span><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">protocol</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> HTTPRequest {</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">    </span><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">var</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> method: </span><span style="font-variant-ligatures:no-common-ligatures;color:#703daa" class="gmail_msg">String</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> { </span><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">get</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> }</span></div><p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">    </span><br class="m_8872408226744841416webkit-block-placeholder gmail_msg"></p><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures;color:#000000" class="gmail_msg">    </span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">// Note that the target host a part of an HTTPRequest</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">    </span><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">var</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> path: </span><span style="font-variant-ligatures:no-common-ligatures;color:#703daa" class="gmail_msg">String</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> { </span><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">get</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> }</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">    </span><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">var</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> headers: [</span><span style="font-variant-ligatures:no-common-ligatures;color:#4f8187" class="gmail_msg">HTTPHeader</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">] { </span><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">get</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> }</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">    </span><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">var</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> body: </span><span style="font-variant-ligatures:no-common-ligatures;color:#4f8187" class="gmail_msg">HTTPBody</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> { </span><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">get</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> }</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">}</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"></span><br class="gmail_msg"></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">public</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> </span><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">protocol</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> HTTPResponseDecoder: </span><span style="font-variant-ligatures:no-common-ligatures;color:#4f8187" class="gmail_msg">HTTPBodyDecoder</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> {</span></div><p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">    </span><br class="m_8872408226744841416webkit-block-placeholder gmail_msg"></p><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(186,45,162)" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures;color:#000000" class="gmail_msg">    </span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">associatedtype</span><span style="font-variant-ligatures:no-common-ligatures;color:#000000" class="gmail_msg"> Response</span></div><p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">    </span><br class="m_8872408226744841416webkit-block-placeholder gmail_msg"></p><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures;color:#000000" class="gmail_msg">    </span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">// Thrown exceptions terminate decoding</span></div><p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">    </span><br class="m_8872408226744841416webkit-block-placeholder gmail_msg"></p><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures;color:#000000" class="gmail_msg">    </span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">// Called before any other methods</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">    </span><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">mutating</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> </span><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">func</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> decodeVersion(</span><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">_</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> value: </span><span style="font-variant-ligatures:no-common-ligatures;color:#703daa" class="gmail_msg">String</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">) </span><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">throws</span></div><p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">    </span><br class="m_8872408226744841416webkit-block-placeholder gmail_msg"></p><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures;color:#000000" class="gmail_msg">    </span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">// Called after `decodeVersion` and before any other methods</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">    </span><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">mutating</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> </span><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">func</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> decodeStatus(</span><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">_</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> value: </span><span style="font-variant-ligatures:no-common-ligatures;color:#703daa" class="gmail_msg">UInt</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">) </span><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">throws</span></div><p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">    </span><br class="m_8872408226744841416webkit-block-placeholder gmail_msg"></p><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures;color:#000000" class="gmail_msg">    </span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">// Called after `decodeVersion` and before any methods below</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">    </span><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">mutating</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> </span><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">func</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> decodeStatusText(</span><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">_</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> value: </span><span style="font-variant-ligatures:no-common-ligatures;color:#703daa" class="gmail_msg">String</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">) </span><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">throws</span></div><p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">    </span><br class="m_8872408226744841416webkit-block-placeholder gmail_msg"></p><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures;color:#000000" class="gmail_msg">    </span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">// Called after all of the above methods and before any methods below. May be called multiple times</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">    </span><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">mutating</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> </span><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">func</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> decodeHeader(</span><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">_</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> key: </span><span style="font-variant-ligatures:no-common-ligatures;color:#703daa" class="gmail_msg">String</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">, value: </span><span style="font-variant-ligatures:no-common-ligatures;color:#703daa" class="gmail_msg">String</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">) </span><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">throws</span></div><p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">    </span><br class="m_8872408226744841416webkit-block-placeholder gmail_msg"></p><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures;color:#000000" class="gmail_msg">    </span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">// HTTPBodyDecoder methods conceptually appear here</span></div><p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">    </span><br class="m_8872408226744841416webkit-block-placeholder gmail_msg"></p><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures;color:#000000" class="gmail_msg">    </span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">// Returns an object to be used to represent the response</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">    </span><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">func</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> decoded() </span><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">throws</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> -&gt; Response</span></div><p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">    </span><br class="m_8872408226744841416webkit-block-placeholder gmail_msg"></p><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">}</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"></span><br class="gmail_msg"></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">// MARK: - Implementing concrete types.</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"></span><br class="gmail_msg"></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">// We can provide come concrete implementations to handle *most* cases. For instance, a concrete type could only support IANA registered stata (as an enum) while a separate concrete type can allow for custom stata.</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"></span><br class="gmail_msg"></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">// Here is an example for a very simple server</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"></span><br class="gmail_msg"></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">public</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> </span><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">enum</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> GeorgeMethod: </span><span style="font-variant-ligatures:no-common-ligatures;color:#703daa" class="gmail_msg">String</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> {</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">    </span><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">case</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> get, post</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">}</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"></span><br class="gmail_msg"></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">public</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> </span><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">struct</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> GeorgeHTTPRequest {</span></div><p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">    </span><br class="m_8872408226744841416webkit-block-placeholder gmail_msg"></p><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">    </span><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">let</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> status: </span><span style="font-variant-ligatures:no-common-ligatures;color:#703daa" class="gmail_msg">GeorgeStatus</span></div><p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">    </span><br class="m_8872408226744841416webkit-block-placeholder gmail_msg"></p><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures;color:#000000" class="gmail_msg">    </span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">// Implementation omitted</span></div><p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">    </span><br class="m_8872408226744841416webkit-block-placeholder gmail_msg"></p><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">}</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"></span><br class="gmail_msg"></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">// We can provide convenience types/protocols for generating decoders from types like my simple enum type above</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">public</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> </span><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">struct</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> GeorgeHTTPRequestDecoder: </span><span style="font-variant-ligatures:no-common-ligatures;color:#4f8187" class="gmail_msg">HTTPRequestDecoder</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> {</span></div><p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">    </span><br class="m_8872408226744841416webkit-block-placeholder gmail_msg"></p><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures;color:#000000" class="gmail_msg">    </span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">// Implementation omitted</span></div><p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">    </span><br class="m_8872408226744841416webkit-block-placeholder gmail_msg"></p><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">    </span><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">func</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> decode() </span><span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2" class="gmail_msg">throws</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> -&gt; </span><span style="font-variant-ligatures:no-common-ligatures;color:#4f8187" class="gmail_msg">GeorgeHTTPRequest</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"> {</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">        </span><span style="font-variant-ligatures:no-common-ligatures;color:#3e1e81" class="gmail_msg">fatalError</span><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">()</span></div></div></div><div style="word-wrap:break-word" class="gmail_msg"><div class="gmail_msg"><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">    }</span></div><p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">    </span><br class="m_8872408226744841416webkit-block-placeholder gmail_msg"></p><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo" class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg">}</span></div><div class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"><br class="gmail_msg"></span></div><div class="gmail_msg"><span style="font-variant-ligatures:no-common-ligatures" class="gmail_msg"><br class="gmail_msg"></span></div><div class="gmail_msg"><blockquote type="cite" class="gmail_msg"><div class="gmail_msg">On Apr 9, 2017, at 4:50 AM, Helge Heß via swift-server-dev &lt;<a href="mailto:swift-server-dev@swift.org" class="gmail_msg" target="_blank">swift-server-dev@swift.org</a>&gt; wrote:</div><br class="m_8872408226744841416Apple-interchange-newline gmail_msg"><div class="gmail_msg"><div class="gmail_msg">Hi,<br class="gmail_msg"><br class="gmail_msg">On 9. Apr 2017, at 04:12, George Leontiev via swift-server-dev &lt;<a href="mailto:swift-server-dev@swift.org" class="gmail_msg" target="_blank">swift-server-dev@swift.org</a>&gt; wrote:<br class="gmail_msg"><blockquote type="cite" class="gmail_msg">Earlier in this thread, I think someone dismissed protocols/generics because “at some point, we need to implement a concrete type”.<br class="gmail_msg"></blockquote><br class="gmail_msg">I don’t think anything was ‘dismissed’. The sole meaning was that there will be a Swift Server module and that this should/will come with a concrete type (so that people can have a minimal running http server out of the box by just using that module). You can still have protocols or whatever you chose.<br class="gmail_msg"><br class="gmail_msg"><br class="gmail_msg"><blockquote type="cite" class="gmail_msg">I think we can leverage the Swift type system to have something much better.<br class="gmail_msg"><br class="gmail_msg">I recommend having protocols for HTTP{Request,Response}{Encodable,Decoder} types<br class="gmail_msg"></blockquote><br class="gmail_msg">&lt;snip&gt; protocols &lt;snip&gt;<br class="gmail_msg"><br class="gmail_msg">Your `HTTPRequestEncodable` is in a way the reverse of Johannes’ HTTPResponseWriter. The advantage of the latter is that it also doesn’t enforce a specific response type and neither requires a type at all. W/ your approach there always has to be a type implementing the protocol.<br class="gmail_msg"><br class="gmail_msg">I’m not entirely sure why you would call it `HTTPRequestEncodable`. I would just call it `HTTPRequest`? To me an `Encodable` has a method which provides another value (the encoded representation). Like this:<br class="gmail_msg"><br class="gmail_msg">  protocol HTTPRequestEncodable {<br class="gmail_msg">    func encodeAsHTTPRequest() -&gt; HTTPRequest<br class="gmail_msg">  }<br class="gmail_msg"><br class="gmail_msg">which may still be useful. But extra indirections :-)<br class="gmail_msg"><br class="gmail_msg"><br class="gmail_msg">Your `HTTPRequestDecoder` is like a parser delegate, kinda like the peer to the `HTTPResponseWriter`. Could be done like this.<br class="gmail_msg">Though if you provide an “Encodable” I suppose the assumption would be that you also provide a “Decodable” too ...<br class="gmail_msg"><br class="gmail_msg"><br class="gmail_msg"><blockquote type="cite" class="gmail_msg">I can flesh out the APIs more if people are interested, but I think this is sufficient to communicate the idea, and I’d love to hear more feedback. <br class="gmail_msg"></blockquote><br class="gmail_msg">A complete proposal like Johannes’ would be more useful. Or maybe even better a revision of Johannes’ proposal with your ideas in it.<br class="gmail_msg"><br class="gmail_msg"><br class="gmail_msg"><blockquote type="cite" class="gmail_msg">There is a performance overhead to using protocols/generics, but I believe these can be effectively mediated by the compiler.<br class="gmail_msg"></blockquote><br class="gmail_msg">I don’t see how you would eliminate the protocol overhead cross-module. But I think it should be small enough (after all the proposal also uses Strings ;-).<br class="gmail_msg"><br class="gmail_msg">hh<br class="gmail_msg"><br class="gmail_msg">_______________________________________________<br class="gmail_msg">swift-server-dev mailing list<br class="gmail_msg"><a href="mailto:swift-server-dev@swift.org" class="gmail_msg" target="_blank">swift-server-dev@swift.org</a><br class="gmail_msg"><a href="https://lists.swift.org/mailman/listinfo/swift-server-dev" class="gmail_msg" target="_blank">https://lists.swift.org/mailman/listinfo/swift-server-dev</a><br class="gmail_msg"></div></div></blockquote></div><br class="gmail_msg"></div></div>_______________________________________________<br class="gmail_msg">
swift-server-dev mailing list<br class="gmail_msg">
<a href="mailto:swift-server-dev@swift.org" class="gmail_msg" target="_blank">swift-server-dev@swift.org</a><br class="gmail_msg">
<a href="https://lists.swift.org/mailman/listinfo/swift-server-dev" rel="noreferrer" class="gmail_msg" target="_blank">https://lists.swift.org/mailman/listinfo/swift-server-dev</a><br class="gmail_msg">
</blockquote></div></div></div>