Update: HTTP client now has HTTPS support, and some minor fix.<div><br></div><div>(import openssl-sack) enables the HTTPS support in http-client.</div><div><br>SOCKS support essentially implemented and to be released someday.<br>

<div><br></div><div>When the IO error handling currently discussed is resolved, multithreaded HTTP connection reuse can be implemented in a robust, holistic, clean way. Will be great as by that Gambit finally has a complete HTTP client.</div>

<div><br></div><div>Mikael<br><br><div class="gmail_quote">2013/3/20 Mikael <span dir="ltr"><<a href="mailto:mikael.rcv@gmail.com" target="_blank">mikael.rcv@gmail.com</a>></span><br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

<div>Hi guys,</div><div><br></div><div>For anyone interested here's the pre-release version of the OpenSSL SSL channels ("openssl") module and an early pre-release of the HTTP client.</div><div><br></div><div>


<div>(If you read this after May 2013 the attachment is most probably outdated and you better look at <a href="https://github.com/gambit-community" target="_blank">https://github.com/gambit-community</a> or <a href="https://github.com/m-i-k-a-e-l/" target="_blank">https://github.com/m-i-k-a-e-l/</a> .)</div>


</div><div><br></div><div><br></div><div><b>openssl module</b></div><div>The openssl module works extremely well and is mature.</div><div><br></div><div>Relative to the amount of functionality provided, extreme effort has been put into its making. This is because OpenSSL's documentation on nonblocking use is incorrect in several parts, so study of other user implementations and practical testing has been required to make it work. Over the course of a couple of years, in the range three man weeks has gone into it this way.</div>


<div><br></div><div>Due to that this is the nature of the problem addressed by this module, I hope that this openssl module will be the main one for Gambit and that any more effort into OpenSSL SSL channel modules in Gambit will go into making this one even better.</div>


<div><br></div><div>The current version however relies on a version-unsafe hack for extracting the respective TCP port's socket, which possibly would be a feature to be included in Gambit, please see the "Next steps for release" section below. OpenSSL is let to write and read from the OS socket directly. This saves lots of roundtrips and buffering.</div>


<div><br></div><div><br></div><div><b>http-client module</b></div><div>The HTTP client supports the passing of custom method, headers and request body, and supports retrieval of status code, headers and request body, and it does both these with support for all of HTTP 1.0 and 1.1, so this is all there is to the HTTP protocol in itself.</div>


<div><br></div><div>Exports:</div><div><br></div><div><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div><font face="courier new, monospace">(simple-raw-http-request uri #!optional request-body (headers '())) => req</font></div>


<div><font face="courier new, monospace"><br></font></div><div><div><font face="courier new, monospace">(define-macro (with-http-client-all-response all-response . code)</font></div><div><font face="courier new, monospace">  `(apply (lambda (reached-uri result stage status-code headers get-header response) ,@code) ,all-response))</font></div>


</div><div><font face="courier new, monospace"><br></font></div><div><div><font face="courier new, monospace">(define (simple-raw-http-request-resp uri #!optional request-body)</font></div><div><font face="courier new, monospace">  (with-http-client-all-response</font></div>


<div><font face="courier new, monospace">   (simple-raw-http-request uri request-body)</font></div><div><font face="courier new, monospace">   response))</font></div></div><div><font face="courier new, monospace"><br></font></div>


</blockquote><font face="arial, helvetica, sans-serif">Use:</font></div><div><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div><font face="courier new, monospace"><br></font></div><div><font face="courier new, monospace"><div>


> (simple-raw-http-request "<a href="http://www.iro.umontreal.ca/~gambit/" target="_blank">http://www.iro.umontreal.ca/~gambit/</a>")</div><div>(#<uri #13 scheme: "http" userinfo: #f host: "<a href="http://www.iro.umontreal.ca" target="_blank">www.iro.umontreal.ca</a>" port: #f path: "/~gambit/" query: () fragment: #f></div>


<div> #t</div><div> done</div><div> 200</div><div> (("connection" . "close")</div><div>  ("content-type" . "text/html")</div><div>  ("content-length" . "115")</div>


<div>  ("accept-ranges" . "bytes")</div><div>  ("etag" . "\"1c93d75-73-4443e1da730c0\"")</div><div>  ("last-modified" . "Mon, 21 Jan 2008 16:38:03 GMT")</div>


<div>  ("server" . "Apache/2.0.54 (Fedora)")</div><div>  ("date" . "Wed, 20 Mar 2013 19:20:12 GMT"))</div><div> #<procedure #14 26#get-header></div><div> "<HTML>\n<HEAD>\n<META HTTP-EQUIV=REFRESH CONTENT=0;URL=<a href="http://dynamo.iro.umontreal.ca/~gambit/wiki/" target="_blank">http://dynamo.iro.umontreal.ca/~gambit/wiki/</a>>\n</HEAD>\n</HTML>\n")</div>


<div><br></div><div>> (simple-raw-http-request-resp "<a href="http://www.iro.umontreal.ca/~gambit/" target="_blank">http://www.iro.umontreal.ca/~gambit/</a>")</div></font></div><div><font face="courier new, monospace">"<HTML>\n<HEAD>\n<META HTTP-EQUIV=REFRESH CONTENT=0;URL=<a href="http://dynamo.iro.umontreal.ca/~gambit/wiki/" target="_blank">http://dynamo.iro.umontreal.ca/~gambit/wiki/</a>>\n</HEAD>\n</HTML>\n"</font></div>


</blockquote></div><div><br></div><div><div>Currently it supports single threaded execution i.e. it opens HTTP connection, makes request, retrieves response and closes the connection in a sequence and there's no connection reuse - reuse and multiplexing across threads as well as following redirects will be implemented. Also invocation of several declared callbacks is not done currently, and will be trivial to implement.</div>


</div><div><br></div><div>The DSL uses Sack's idea of providing all protocol functionality in a 'core' form. It can extremely easily be wrapped to a XMLHTTPRequest object.</div><div><br></div><div>This http-client module replaces Sack's previous http-client module, which unlike Sack's web server module which works great, had terrible problems, for more info see the header section in http-client.scm .</div>


<div><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div><br></div><div><br></div></blockquote></div><div><br></div><div><b>Next steps for release</b></div><div>I'll make a "real" release of these two modules when the IO exception handling question discussed on the list now has got an answer and maybe extraction of TCP port socket can be done with a Gambit-builtin procedure. These two things currently bring version-unsafe hacks into the code, more specifically into <font face="courier new, monospace">tcpip.scm</font> and <font face="courier new, monospace">sack/src/gamgambit-noexceptions-io.scm</font> , so this is why I call this a pre-release.</div>


<div><br></div><div>(Note that <font face="courier new, monospace">port-wait-for-input</font> and <font face="courier new, monospace">port-wait-for-output</font> of the <font face="courier new, monospace">tcpip</font> module are not needed anymore as the firstmentioned has been in Gambit all the time and the latter was recently included in Gambit, ##-prefixed. Will remove them when I doublechecked they're in the newest Gambit version's namespace. As it looks the <font face="courier new, monospace">tcpip</font> module will be removed.)</div>


<div><br></div><div><br></div><div><b>Future development</b></div><div>I'll be happy to see when current Black Hole will have package management functionality so that installation of these packages will be easy.</div>


<div><br></div><div><br></div><div>Currently the OpenSSL module exports its functionality as a set of IO primitive closures, and, the HTTP server and client uses such IO primitive closures for interaction with its underlying IO layer.</div>


<div><br></div><div>When there will be good support for application-layer port implementations in Gambit - I hope that will happen the next 1.5 years or so, we'll see - the HTTP server and client will use Gambit's IO primitives directly instead of these custom primitives, which will provide for a cleaner and more general code, and,</div>


<div><br></div><div>The OpenSSL module and I suppose the HTTP-client (and probably HTTP server too) will export Gambit ports for use something like</div><div><br></div><blockquote style="margin:0 0 0 40px;border:none;padding:0px">


<div><font face="courier new, monospace">(open-ssl-channel-port settings) => port</font></div><div><font face="courier new, monospace">(open-http-client-port settings (lambda (request-body-port) (display .. request-body-port))) => response-body-port</font></div>


</blockquote><div><br></div><div><br></div><div><br></div><div>Thoughts, feedback, patches much welcome.</div><div><br></div><div><br></div><div>Best regards,</div><div>Mikael</div><div><br></div>
</blockquote></div><br></div></div>