<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>web — jd:/dev/blog</title><description>Posts tagged &quot;web&quot; on jd:/dev/blog.</description><link>https://julien.danjou.info/</link><item><title>Python and fast HTTP clients</title><link>https://julien.danjou.info/blog/python-and-fast-http-clients/</link><guid isPermaLink="true">https://julien.danjou.info/blog/python-and-fast-http-clients/</guid><description>Nowadays, it is more than likely that you will have to write an HTTP client for your application that will have to talk to another HTTP server. The ubiquity of REST API makes HTTP a first class citize</description><pubDate>Mon, 07 Oct 2019 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Nowadays, it is more than likely that you will have to write an HTTP client for your application that will have to talk to another HTTP server. The ubiquity of REST API makes HTTP a first class citizen. That&apos;s why knowing optimization patterns are a prerequisite.&lt;/p&gt;
&lt;p&gt;There are many HTTP clients in Python; the most widely used and easy to&lt;br /&gt;
work with is &lt;em&gt;&lt;a href=&quot;https://requests.kennethreitz.org/&quot;&gt;requests&lt;/a&gt;&lt;/em&gt;. It is the de-factor standard nowadays.&lt;/p&gt;
&lt;h2&gt;Persistent Connections&lt;/h2&gt;
&lt;p&gt;The first optimization to take into account is the use of a persistent connection to the Web server. Persistent connections are a standard since HTTP 1.1 though many applications do not leverage them. This lack of optimization is simple to explain if you know that when using &lt;em&gt;requests&lt;/em&gt; in its simple mode (e.g. with the &lt;code&gt;get&lt;/code&gt; function) the connection is closed on return. To avoid that, an application needs to use a &lt;code&gt;Session&lt;/code&gt; object that allows reusing an already opened connection.&lt;/p&gt;
&lt;p&gt;Each connection is stored in a pool of connections (10 by default), the size of&lt;br /&gt;
which is also configurable:&lt;/p&gt;
&lt;p&gt;Reusing the TCP connection to send out several HTTP requests offers a number of performance advantages:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Lower CPU and memory usage (fewer connections opened simultaneously).&lt;/li&gt;
&lt;li&gt;Reduced latency in subsequent requests (no TCP handshaking).&lt;/li&gt;
&lt;li&gt;Exceptions can be raised without the penalty of closing the TCP connection.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The HTTP protocol also provides &lt;a href=&quot;https://en.wikipedia.org/wiki/HTTP_pipelining&quot;&gt;pipelining&lt;/a&gt;, which allows sending several requests on the same connection without waiting for the replies to come (think batch). Unfortunately, this is not supported by the &lt;em&gt;requests&lt;/em&gt; library. However, pipelining requests may not be as fast as sending them in parallel. Indeed, the HTTP 1.1 protocol forces the replies to be sent in the same order as the requests were sent – first-in first-out.&lt;/p&gt;
&lt;h2&gt;Parallelism&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;requests&lt;/em&gt; also has one major drawback: it is synchronous. Calling &lt;code&gt;requests.get(&quot;http://example.org&quot;)&lt;/code&gt; blocks the program until the HTTP server replies completely. Having the application waiting and doing nothing can be a drawback here. It is possible that the program could do something else rather than sitting idle.&lt;/p&gt;
&lt;p&gt;A smart application can mitigate this problem by using a pool of threads like the ones provided by &lt;code&gt;concurrent.futures&lt;/code&gt;. It allows parallelizing the HTTP requests in a very rapid way.&lt;/p&gt;
&lt;p&gt;This pattern being quite useful, it has been packaged into a library named &lt;em&gt;&lt;a href=&quot;https://github.com/ross/requests-futures&quot;&gt;requests-futures&lt;/a&gt;&lt;/em&gt;. The usage of &lt;code&gt;Session&lt;/code&gt; objects is made transparent to the developer:&lt;/p&gt;
&lt;p&gt;By default a worker with two threads is created, but a program can easily customize this value by passing the &lt;code&gt;max_workers&lt;/code&gt; argument or even its own executor to the &lt;code&gt;FuturSession&lt;/code&gt; object – for example like this: &lt;code&gt;FuturesSession(executor=ThreadPoolExecutor(max_workers=10))&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;Asynchronicity&lt;/h2&gt;
&lt;p&gt;As explained earlier, &lt;em&gt;requests&lt;/em&gt; is entirely synchronous. That blocks the application while waiting for the server to reply, slowing down the program. Making HTTP requests in threads is one solution, but threads do have their own overhead and this implies parallelism, which is not something everyone is always glad to see in a program.&lt;/p&gt;
&lt;p&gt;Starting with version 3.5, Python offers asynchronicity as its core using &lt;em&gt;asyncio&lt;/em&gt;. The &lt;a href=&quot;http://aiohttp.readthedocs.io/%5Baiohttp%5D&quot;&gt;aiohttp&lt;/a&gt; library provides an asynchronous HTTP client built on top of &lt;em&gt;asyncio&lt;/em&gt;. This library allows sending requests in series but without waiting for the first reply to come back before sending the new one. In contrast to HTTP pipelining, &lt;em&gt;aiohttp&lt;/em&gt; sends the requests over multiple connections in parallel, avoiding the ordering issue explained earlier.&lt;/p&gt;
&lt;p&gt;All those solutions (using &lt;code&gt;Session&lt;/code&gt;, &lt;em&gt;threads&lt;/em&gt;, &lt;em&gt;futures&lt;/em&gt; or &lt;em&gt;asyncio&lt;/em&gt;) offer different approaches to making HTTP clients faster.&lt;/p&gt;
&lt;h2&gt;Performances&lt;/h2&gt;
&lt;p&gt;The snippet below is an HTTP client sending requests to &lt;code&gt;httpbin.org&lt;/code&gt;, an HTTP API that provides (among other things) an endpoint simulating a long request (a second here). This example implements all the techniques listed above and times them.&lt;/p&gt;
&lt;p&gt;Running this program gives the following output:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Time needed for `serialized&apos; called: 12.12s
Time needed for `Session&apos; called: 11.22s
Time needed for `FuturesSession w/ 2 workers&apos; called: 5.65s
Time needed for `FuturesSession w/ max workers&apos; called: 1.25s
Time needed for `aiohttp&apos; called: 1.19s
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/content/images/07/20190716092338_hd.png&quot; alt=&quot;Benchmark chart comparing HTTP client performance in Python&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Without any surprise, the slower result comes with the dumb serialized version, since all the requests are made one after another without reusing the connection — 12 seconds to make 10 requests.&lt;/p&gt;
&lt;p&gt;Using a &lt;code&gt;Session&lt;/code&gt; object and therefore reusing the connection means saving 8% in terms of time, which is already a big and easy win. Minimally, you should always use a session.&lt;/p&gt;
&lt;p&gt;If your system and program allow the usage of threads, it is a good call to use them to parallelize the requests. However threads have some overhead, and they are not weight-less. They need to be created, started and then joined.&lt;/p&gt;
&lt;p&gt;Unless you are still using old versions of Python, without a doubt using &lt;em&gt;aiohttp&lt;/em&gt; should be the way to go nowadays if you want to write a fast and asynchronous HTTP client. It is the fastest and the most scalable solution as it can handle hundreds of parallel requests. The alternative, managing hundreds of threads in parallel is not a great option.&lt;/p&gt;
&lt;h2&gt;Streaming&lt;/h2&gt;
&lt;p&gt;Another speed optimization that can be efficient is streaming the requests. When making a request, by default the body of the response is downloaded immediately. The &lt;code&gt;stream&lt;/code&gt; parameter provided by the &lt;em&gt;requests&lt;/em&gt; library or the &lt;code&gt;content&lt;/code&gt; attribute for &lt;code&gt;aiohttp&lt;/code&gt; both provide a way to not load the full content in memory as soon as the request is executed.&lt;/p&gt;
&lt;p&gt;Not loading the full content is extremely important in order to avoid allocating potentially hundred of megabytes of memory for nothing. If your program does not need to access the entire content as a whole but can work on chunks, it is probably better to just use those methods. For example, if you&apos;re going to save and write the content to a file, reading only a chunk and writing it at the same time is going to be much more memory efficient than reading the whole HTTP body, allocating a giant pile of memory, and then writing it to disk.&lt;/p&gt;
&lt;p&gt;I hope that&apos;ll make it easier for you to write proper HTTP clients and requests. If you know any other useful technic or method, feel free to write it down in the comment section below!&lt;/p&gt;
</content:encoded><category>python</category><category>web</category></item><item><title>Handling multipart/form-data natively in Python</title><link>https://julien.danjou.info/blog/handling-multipart-form-data-python/</link><guid isPermaLink="true">https://julien.danjou.info/blog/handling-multipart-form-data-python/</guid><description>RFC7578 (who obsoletes RFC2388) defines the multipart/form-data type that is usually transported over HTTP when users submit forms on your Web page.</description><pubDate>Mon, 01 Jul 2019 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://tools.ietf.org/html/rfc7578&quot;&gt;RFC7578&lt;/a&gt; (who obsoletes &lt;a href=&quot;https://tools.ietf.org/html/rfc2388&quot;&gt;RFC2388&lt;/a&gt;) defines the &lt;code&gt;multipart/form-data&lt;/code&gt; type that is usually transported over HTTP when users submit forms on your Web page. Nowadays, it tends to be replaced by JSON encoded payloads; nevertheless, it is still widely used.&lt;/p&gt;
&lt;p&gt;While you could decode an HTTP body request made with JSON natively with Python — thanks to the &lt;code&gt;json&lt;/code&gt; module — there is no such way to do that with &lt;code&gt;multipart/form-data&lt;/code&gt;. That&apos;s something barely understandable considering how old the format is.&lt;/p&gt;
&lt;p&gt;There is a wide variety of way available to encode and decode this format. Libraries such as &lt;em&gt;requests&lt;/em&gt; support this natively without making you notice, and the same goes for the majority of Web server frameworks such as &lt;em&gt;Django&lt;/em&gt; or &lt;em&gt;Flask&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;However, in certain circumstances, you might be on your own to encode or decode this format, and it might not be an option to pull (significant) dependencies.&lt;/p&gt;
&lt;h2&gt;Encoding&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;multipart/form-data&lt;/code&gt; format is quite simple to understand and can be summarised as an easy way to encode a list of keys and values, i.e., a portable way of serializing a dictionary.&lt;/p&gt;
&lt;p&gt;There&apos;s nothing in Python to generate such an encoding. The format is quite simple and consists of the key and value surrounded by a random boundary delimiter. This delimiter must be passed as part of the &lt;code&gt;Content-Type&lt;/code&gt;, so that the decoder can decode the form data.&lt;/p&gt;
&lt;p&gt;There&apos;s a simple implementation in &lt;em&gt;urllib3&lt;/em&gt; that does the job. It&apos;s possible to summarize it in this simple implementation:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import binascii
import os

def encode_multipart_formdata(fields):
    boundary = binascii.hexlify(os.urandom(16)).decode(&apos;ascii&apos;)

    body = (
        &quot;&quot;.join(&quot;--%s\r\n&quot;
                &quot;Content-Disposition: form-data; name=\&quot;%s\&quot;\r\n&quot;
                &quot;\r\n&quot;
                &quot;%s\r\n&quot; % (boundary, field, value)
                for field, value in fields.items()) +
        &quot;--%s--\r\n&quot; % boundary
    )

    content_type = &quot;multipart/form-data; boundary=%s&quot; % boundary

    return body, content_type
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can use by passing a dictionary where keys and values are bytes. For example:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;encode_multipart_formdata({&quot;foo&quot;: &quot;bar&quot;, &quot;name&quot;: &quot;jd&quot;})
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Which returns:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;--00252461d3ab8ff5c25834e0bffd6f70
Content-Disposition: form-data; name=&quot;foo&quot;

bar
--00252461d3ab8ff5c25834e0bffd6f70
Content-Disposition: form-data; name=&quot;name&quot;

jd
--00252461d3ab8ff5c25834e0bffd6f70--
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;multipart/form-data; boundary=00252461d3ab8ff5c25834e0bffd6f70
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can use the returned content type in your HTTP reply header &lt;code&gt;Content-Type&lt;/code&gt;. Note that this format is used for forms: it can also be used by emails.&lt;/p&gt;
&lt;p&gt;Emails did you say?&lt;/p&gt;
&lt;h2&gt;Encoding with &lt;code&gt;email&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Right, emails are usually encoded using MIME, which is defined by yet another RFC, &lt;a href=&quot;https://tools.ietf.org/html/rfc2046&quot;&gt;RFC2046&lt;/a&gt;. It turns out that &lt;code&gt;multipart/form-data&lt;/code&gt; is just a particular MIME format, and that if you have code that implements MIME handling, it&apos;s easy to use it to implement this format.&lt;/p&gt;
&lt;p&gt;Fortunately for us, Python standard library comes with a module that handles exactly that: &lt;code&gt;email.mime&lt;/code&gt;. I told you it was heavily used by email — I guess that&apos;s why they put that code in the &lt;code&gt;email&lt;/code&gt; subpackage.&lt;/p&gt;
&lt;p&gt;Here&apos;s a piece of code that handles &lt;code&gt;multipart/form-data&lt;/code&gt; in a few lines of code:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;from email import message
from email.mime import multipart
from email.mime import nonmultipart
from email.mime import text

class MIMEFormdata(nonmultipart.MIMENonMultipart):
    def __init__(self, keyname, *args, **kwargs):
        super(MIMEFormdata, self).__init__(*args, **kwargs)
        self.add_header(
            &quot;Content-Disposition&quot;, &quot;form-data; name=\&quot;%s\&quot;&quot; % keyname)

def encode_multipart_formdata(fields):
    m = multipart.MIMEMultipart(&quot;form-data&quot;)

    for field, value in fields.items():
        data = MIMEFormdata(field, &quot;text&quot;, &quot;plain&quot;)
        data.set_payload(value)
        m.attach(data)

    return m
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Using this piece of code returns the following:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Content-Type: multipart/form-data; boundary=&quot;===============1107021068307284864==&quot;
MIME-Version: 1.0

--===============1107021068307284864==
Content-Type: text/plain
MIME-Version: 1.0
Content-Disposition: form-data; name=&quot;foo&quot;

bar
--===============1107021068307284864==
Content-Type: text/plain
MIME-Version: 1.0
Content-Disposition: form-data; name=&quot;name&quot;

jd
--===============1107021068307284864==--
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This method has several advantages over our first implementation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It handles &lt;code&gt;Content-Type&lt;/code&gt; for each of the added MIME parts. We could add other data types than just &lt;code&gt;text/plain&lt;/code&gt; like it is implicitly done in the first version. We could also specify the charset (encoding) of the textual data.&lt;/li&gt;
&lt;li&gt;It&apos;s very likely more robust by leveraging the wildly tested Python standard library.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main downside, in that case, is that the &lt;code&gt;Content-Type&lt;/code&gt; header is included with the content. In case of handling HTTP, it is problematic as this needs to be sent as part of the HTTP header and not as part of the payload.&lt;/p&gt;
&lt;p&gt;It should be possible to build a particular generator from &lt;code&gt;email.generator&lt;/code&gt; that does this. I&apos;ll leave that as an exercise to you, reader.&lt;/p&gt;
&lt;h2&gt;Decoding&lt;/h2&gt;
&lt;p&gt;We must be able to use that same &lt;code&gt;email&lt;/code&gt; package to decode our encoded data, right? It turns out that&apos;s the case, with a piece of code that looks like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import email.parser

msg = email.parser.BytesParser().parsebytes(my_multipart_data)

print({
    part.get_param(&apos;name&apos;, header=&apos;content-disposition&apos;): part.get_payload(decode=True)
    for part in msg.get_payload()
})
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With the example data above, this returns:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{&apos;foo&apos;: b&apos;bar&apos;, &apos;name&apos;: b&apos;jd&apos;}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Amazing, right?&lt;/p&gt;
&lt;p&gt;The moral of this story is that you should never underestimate the power of the standard library. While it&apos;s easy to add a single line in your list of dependencies, it&apos;s not always required if you dig a bit into what Python provides for you!&lt;/p&gt;
</content:encoded><category>python</category><category>email</category><category>web</category></item><item><title>Correct HTTP scheme in WSGI with Cloudflare</title><link>https://julien.danjou.info/blog/correct-http-scheme-in-wsgi-with-cloudflare/</link><guid isPermaLink="true">https://julien.danjou.info/blog/correct-http-scheme-in-wsgi-with-cloudflare/</guid><description>I&apos;ve recently been using Cloudflare as an HTTP frontend for some applications, and getting things working correctly with WSGI was unobvious.</description><pubDate>Wed, 25 Apr 2018 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I&apos;ve recently been using &lt;a href=&quot;https://cloudflare.com&quot;&gt;Cloudflare&lt;/a&gt; as an HTTP frontend for some applications, and getting things working correctly with WSGI was unobvious.&lt;/p&gt;
&lt;p&gt;In Python, &lt;a href=&quot;https://en.wikipedia.org/wiki/Web_Server_Gateway_Interface&quot;&gt;WSGI&lt;/a&gt; is the standard protocol to write a Web application. All Web frameworks that I know follows it. And many of those Web frameworks leverage some request environment variables to learn how the request has been made.&lt;/p&gt;
&lt;p&gt;One of those environment variables is &lt;code&gt;wsgi.url_scheme&lt;/code&gt;, and it contains either &lt;code&gt;http&lt;/code&gt; or &lt;code&gt;https&lt;/code&gt;, depending on the protocol that has been used to connect to your WSGI server.&lt;/p&gt;
&lt;p&gt;And that&apos;s where things can get messy. If you enable SSL at Cloudflare in &quot;Flexible&quot; mode, your visitor will connect to your Web site using HTTPS, but Cloudflare will connect to your backend using HTTP. That means that for your application, the traffic will appear to be over HTTP, and not HTTPS: &lt;code&gt;wsgi.url_scheme&lt;/code&gt; will be set to &lt;code&gt;http&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/content/images/04/Screen-Shot-2018-04-19-at-22.43.55.png&quot; alt=&quot;Cloudflare SSL setting&quot; /&gt;&lt;/p&gt;
&lt;p&gt;That can lead to several problems with some frameworks. For example, the function &lt;code&gt;url_for&lt;/code&gt; of &lt;a href=&quot;http://flask.pocoo.org/&quot;&gt;Flask&lt;/a&gt; will rely on this variable to generate the scheme part of any URL. In this case, it would, therefore, generate URL starting with &lt;code&gt;http://&lt;/code&gt; whereas your visitors are using &lt;code&gt;https&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The usual workaround is to leverage the &lt;code&gt;X-Forwarded-Proto&lt;/code&gt; that is actually &lt;a href=&quot;https://support.cloudflare.com/hc/en-us/articles/200170986-How-does-Cloudflare-handle-HTTP-Request-headers-&quot;&gt;set by Cloudflare&lt;/a&gt;. In the case where Cloudflare proxies the request to your HTTP host, this will be set to &lt;code&gt;https&lt;/code&gt;. By using the &lt;a href=&quot;http://werkzeug.pocoo.org/docs/contrib/fixers/#werkzeug.contrib.fixers.ProxyFix&quot;&gt;werkzeug.contrib.fixers.ProxyFix&lt;/a&gt; module, the variable &lt;code&gt;wsgi.url_scheme&lt;/code&gt; will be set to what &lt;code&gt;X-Forwarded-Proto&lt;/code&gt; is set.&lt;/p&gt;
&lt;p&gt;That would work fine for any application that is directly behind Cloudflare, or any single HTTP reverse proxy.&lt;/p&gt;
&lt;p&gt;But that does not work as soon as you have multiple reverse proxies. If your application runs on top of &lt;a href=&quot;https://heroku.com&quot;&gt;Heroku&lt;/a&gt; for example, they already provide a reverse proxy and overwrite those headers. That gives the following: &lt;code&gt;Visitor -HTTPS-&amp;gt; Cloudflare -HTTP-&amp;gt; Heroku proxy -HTTP-&amp;gt; Heroku dyno&lt;/code&gt;. Once your dyno is reacher, &lt;code&gt;X-Forwarded-For&lt;/code&gt; will be set to &lt;code&gt;http&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Damn it!&lt;/p&gt;
&lt;p&gt;The proper solution is, therefore, to have all your proxies implement &lt;a href=&quot;https://tools.ietf.org/html/rfc7239&quot;&gt;RFC7239&lt;/a&gt;. This RFC defines a new &lt;code&gt;Forwarded&lt;/code&gt; header that can contain all the hops that have forwarded this request, including all the scheme and IP addresses. Unfortunately, this is not implemented by Cloudflare nor Heroku. Bummer!&lt;/p&gt;
&lt;p&gt;Finally, Cloudflare provides yet another custom header named &lt;code&gt;Cf-Visitor&lt;/code&gt;. It contains a JSON payload with the original HTTP scheme used by the visitor: we can use that to solve our issue. Here&apos;s a WSGI middleware to do that:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;class CloudflareProxy(object):
    &quot;&quot;&quot;This middleware sets the proto scheme based on the Cf-Visitor header.&quot;&quot;&quot;

    def __init__(self, app):
        self.app = app

    def __call__(self, environ, start_response):
        cf_visitor = environ.get(&quot;HTTP_CF_VISITOR&quot;)
        if cf_visitor:
            try:
                cf_visitor = json.loads(cf_visitor)
            except ValueError:
                pass
            else:
                proto = cf_visitor.get(&quot;scheme&quot;)
                if proto is not None:
                    environ[&apos;wsgi.url_scheme&apos;] = proto
        return self.app(environ, start_response)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can then use it to encapsulate your WSGI application with &lt;code&gt;app = CloudflareProxy(app)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If you&apos;re using JavaScript, I noticed that the &lt;a href=&quot;https://github.com/jshttp/forwarded&quot;&gt;forwarded&lt;/a&gt; library provides that same support for Cloudflare along all the other headers – even RFC7239!&lt;/p&gt;
</content:encoded><category>python</category><category>web</category></item><item><title>Scalable metrics storage: Gnocchi on Amazon Web Services</title><link>https://julien.danjou.info/blog/metrics-on-amazon-with-gnocchi-s3-driver/</link><guid isPermaLink="true">https://julien.danjou.info/blog/metrics-on-amazon-with-gnocchi-s3-driver/</guid><description>As I wrote a few weeks ago in my post about Gnocchi 3.1 being released, one of the new feature available in this version it the S3 driver.</description><pubDate>Wed, 22 Feb 2017 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;As I wrote a few weeks ago in my &lt;a href=&quot;https://julien.danjou.info/blog/gnocchi-3-1-unleashed&quot;&gt;post about Gnocchi 3.1 being released&lt;/a&gt;, one of the new feature available in this version it the &lt;a href=&quot;https://aws.amazon.com/s3/&quot;&gt;S3&lt;/a&gt; driver. Today I would like to show you how easy it is to use it and store millions of metrics into the simple, durable and massively scalable object storage provided&lt;br /&gt;
by &lt;a href=&quot;https://aws.amazon.com/&quot;&gt;Amazon Web Services&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;The installation of Gnocchi for this use case is not different than&lt;br /&gt;
the &lt;a href=&quot;http://gnocchi.xyz/install.html&quot;&gt;standard installation procedure described in the documentation&lt;/a&gt;. Simply install Gnocchi from &lt;a href=&quot;http://pypi.python.org&quot;&gt;PyPI&lt;/a&gt; using the following command:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ pip install gnocchi[s3,postgresql] gnocchiclient
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This will install Gnocchi with the dependencies for the S3 and PostgreSQL drivers and the command-line interface to talk with Gnocchi.&lt;/p&gt;
&lt;h2&gt;Configuring Amazon RDS&lt;/h2&gt;
&lt;p&gt;Since you need a SQL database for the indexer, the easiest way to get started is to create a database on &lt;a href=&quot;https://console.aws.amazon.com/rds/&quot;&gt;Amazon RDS&lt;/a&gt;. You can create a managed &lt;a href=&quot;http://postgresql.org&quot;&gt;PostgreSQL&lt;/a&gt; database instance in just a few clicks.&lt;/p&gt;
&lt;p&gt;Once you&apos;re on the homepage of &lt;a href=&quot;https://console.aws.amazon.com/rds/&quot;&gt;Amazon RDS&lt;/a&gt;, pick PostgreSQL as a&lt;br /&gt;
database:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/content/images/03/gnocchi-rds-postgresql.png&quot; alt=&quot;gnocchi-rds-postgresql&quot; /&gt;&lt;/p&gt;
&lt;p&gt;You can then configure your PostgreSQL instance: I&apos;ve picked a dev/test instance with the basic options available within the RDS Free Tier, but you can pick whatever you think is needed for your production use. Set a username and a password and note them for later: we&apos;ll need them to configure Gnocchi.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/content/images/03/gnocchi-rds-postgresql-conf.png&quot; alt=&quot;gnocchi-rds-postgresql-conf&quot; /&gt;&lt;/p&gt;
&lt;p&gt;The next step is to configure the database in details. Just set the database name to &quot;gnocchi&quot; and leave the other options to their default values (I&apos;m lazy).&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/content/images/03/gnocchi-rds-postgresql-details.png&quot; alt=&quot;gnocchi-rds-postgresql-details&quot; /&gt;&lt;/p&gt;
&lt;p&gt;After a few minutes, your instance should be created and running. Note down the endpoint. In this case, my instance is &lt;code&gt;gnocchi.cywagbaxpert.us-east-1.rds.amazonaws.com&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/content/images/03/gnocchi-rds-postgresql-running.png&quot; alt=&quot;gnocchi-rds-postgresql-running&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;Configuring Gnocchi for S3 access&lt;/h2&gt;
&lt;p&gt;In order to give Gnocchi an access to S3, you need to create access keys. The easiest way to create them is to go to &lt;a href=&quot;https://console.aws.amazon.com/iam&quot;&gt;IAM&lt;/a&gt; in your AWS console, pick a user with S3 access and click on the big gray button named &quot;Create access key&quot;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/content/images/03/gnocchi-iam-create-keys.png&quot; alt=&quot;gnocchi-iam-create-keys&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Once you do that, you&apos;ll get the &lt;em&gt;access key id&lt;/em&gt; and &lt;em&gt;secret access key&lt;/em&gt;. Note them down, we will need these later.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/content/images/03/gnocchi-iam-get-keys.png&quot; alt=&quot;gnocchi-iam-get-keys&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;Creating &lt;code&gt;gnocchi.conf&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Now is time to create the &lt;code&gt;gnocchi.conf&lt;/code&gt; file. You can place it in &lt;code&gt;/etc/gnocchi&lt;/code&gt; if you want to deploy it system-wide, or in any other directory and add the &lt;code&gt;--config-file&lt;/code&gt; option to each Gnocchi command..&lt;/p&gt;
&lt;p&gt;Here are the values that you should retrieve and write in the configuration file:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;indexer.url&lt;/code&gt;: the PostgreSQL RDS instance endpoint and credentials (see above) to set into&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage.s3_endpoint_url&lt;/code&gt;: the S3 endpoint URL – that depends on the region you want to use and &lt;a href=&quot;http://docs.aws.amazon.com/general/latest/gr/rande.html#s3_region&quot;&gt;they are listed here&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage.s3_region_name&lt;/code&gt;: the S3 region name matching the endpoint you picked.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage.s3_access_key_id&lt;/code&gt; and &lt;code&gt;storage.s3_secret_acess_key&lt;/code&gt;: your AWS access key id and secret access key.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Your &lt;code&gt;gnocchi.conf&lt;/code&gt; file should then look like that:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[indexer]
url = postgresql://gnocchi:gn0cch1rul3z@gnocchi.cywagbaxpert.us-east-1.rds.amazonaws.com:5432/gnocchi

[storage]
driver = s3
s3_endpoint_url = https://s3-eu-west-1.amazonaws.com
s3_region_name = eu-west-1
s3_access_key_id = &amp;lt;you access key id&amp;gt;
s3_secret_access_key = &amp;lt;your secret access key&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Once that&apos;s done, you can run &lt;code&gt;gnocchi-upgrade&lt;/code&gt; in order to initialize Gnocchi indexer (PostgreSQL) and storage (S3):&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ gnocchi-upgrade --config-file gnocchi.conf
2017-02-07 15:35:52.491 3660 INFO gnocchi.cli [-] Upgrading indexer &amp;lt;gnocchi.indexer.sqlalchemy.SQLAlchemyIndexer object at 0x108221950&amp;gt;
2017-02-07 15:36:04.127 3660 INFO gnocchi.cli [-] Upgrading storage &amp;lt;gnocchi.storage.s3.S3Storage object at 0x10ca943d0&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then you can run the API endpoint using the test endpoint &lt;code&gt;gnocchi-api&lt;/code&gt; and specifying its default port 8041:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ gnocchi-api --port 8041 -- --config-file gnocchi.conf
2017-02-07 15:53:06.823 6290 INFO gnocchi.rest.app [-] WSGI config used: /Users/jd/Source/gnocchi/gnocchi/rest/api-paste.ini
********************************************************************************
STARTING test server gnocchi.rest.app.build_wsgi_app
Available at http://127.0.0.1:8041/
DANGER! For testing only, do not use in production
********************************************************************************
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The best way to run Gnocchi API is to use &lt;a href=&quot;http://gnocchi.xyz/master/running.html#running-api-as-a-wsgi-application&quot;&gt;uwsgi as documented&lt;/a&gt;, but in this case, using the testing daemon &lt;code&gt;gnocchi-api&lt;/code&gt; is good enough.&lt;/p&gt;
&lt;p&gt;Finally, in another terminal, you can start the &lt;code&gt;gnocchi-metricd&lt;/code&gt; daemon that will process metrics in background:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ gnocchi-metricd --config-file gnocchi.conf
2017-02-07 15:52:41.416 6262 INFO gnocchi.cli [-] 0 measurements bundles across 0 metrics wait to be processed.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Once everything is running, you can use Gnocchi&apos;s client to query it and check that everything is OK. The backlog should be empty at this stage, obviously.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ gnocchi status
+-----------------------------------------------------+-------+
| Field                                               | Value |
+-----------------------------------------------------+-------+
| storage/number of metric having measures to process | 0     |
| storage/total number of measures to process         | 0     |
+-----------------------------------------------------+-------+
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Gnocchi is ready to be used!&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ # Create a generic resource &quot;foobar&quot; with a metric named &quot;visitor&quot;
$ gnocchi resource create foobar -n visitor
+-----------------------+-----------------------------------------------+
| Field                 | Value                                         |
+-----------------------+-----------------------------------------------+
| created_by_project_id |                                               |
| created_by_user_id    | admin                                         |
| creator               | admin                                         |
| ended_at              | None                                          |
| id                    | b4d568e4-7af1-5aec-ac3f-9c09fa3685a9          |
| metrics               | visitor: 05f45876-1a69-4a64-8575-03eea5b79407 |
| original_resource_id  | foobar                                        |
| project_id            | None                                          |
| revision_end          | None                                          |
| revision_start        | 2017-02-07T14:54:54.417447+00:00              |
| started_at            | 2017-02-07T14:54:54.417414+00:00              |
| type                  | generic                                       |
| user_id               | None                                          |
+-----------------------+-----------------------------------------------+

## Send the number of visitor at 2 different timestamps
$ gnocchi measures add --resource-id foobar -m 2017-02-07T15:56@23 visitor
$ gnocchi measures add --resource-id foobar -m 2017-02-07T15:57@42 visitor

## Check the average number of visitor
## (the --refresh option is given to be sure the measure are processed)
$ gnocchi measures show --resource-id foobar visitor --refresh
+---------------------------+-------------+-------+
| timestamp                 | granularity | value |
+---------------------------+-------------+-------+
| 2017-02-07T15:55:00+00:00 |       300.0 |  32.5 |
+---------------------------+-------------+-------+

## Now shows the minimum number of visitor
$ gnocchi measures show --aggregation min --resource-id foobar visitor
+---------------------------+-------------+-------+
| timestamp                 | granularity | value |
+---------------------------+-------------+-------+
| 2017-02-07T15:55:00+00:00 |       300.0 |  23.0 |
+---------------------------+-------------+-------+
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And voilà! You&apos;re ready to store millions of metrics and measures on your Amazon Web Services cloud platform. I hope you&apos;ll enjoy it and feel free to ask any question in the comment section or by reaching me directly!&lt;/p&gt;
</content:encoded><category>gnocchi</category><category>web</category></item><item><title>Doing A/B testing with Apache httpd</title><link>https://julien.danjou.info/blog/a-b-testing-with-apache/</link><guid isPermaLink="true">https://julien.danjou.info/blog/a-b-testing-with-apache/</guid><description>When I started writing the landing page for The Hacker&apos;s Guide to Python, I wanted to try new things at the same time.</description><pubDate>Sun, 06 Apr 2014 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;When I started writing the landing page for &lt;a href=&quot;https://thehackerguidetopython.com&quot;&gt;The Hacker&apos;s Guide to Python&lt;/a&gt;, I wanted to try new things at the same time. I read about A/B testing a while ago, and I figured it was a good opportunity to test it out.&lt;/p&gt;
&lt;h2&gt;A/B testing&lt;/h2&gt;
&lt;p&gt;If you do not know what A/B testing is about, take a quick look at the &lt;a href=&quot;http://en.wikipedia.org/wiki/A/B_testing&quot;&gt;Wikipedia page on that subject&lt;/a&gt;. Long story short, the idea is to serve two different version of a page to your visitors and check which one is getting the most success. When you found which version is better, you can definitely switch to it.&lt;/p&gt;
&lt;p&gt;In the case of my book, I used that technique on the pre-launch page where people were able to subscribe to the newsletter. I didn&apos;t have a lot of things I wanted to test out on that page, so I just used that approach on the subtitle, being either &quot;Learn everything you need to build a successful Python project&quot; or &quot;It&apos;s time you make the most out of Python&quot;.&lt;/p&gt;
&lt;p&gt;Statistically, each version would be served half of the time, so both would get the same number of view. I then would build statistics about which page was attracting the most subscribers. With the results I would be able to switch definitively to that version of the landing page.&lt;/p&gt;
&lt;h2&gt;Technical design&lt;/h2&gt;
&lt;p&gt;My Web site, this Web site, is entirely static and served by &lt;a href=&quot;http://httpd.apache.org/&quot;&gt;Apache httpd&lt;/a&gt;. I didn&apos;t want to use any dynamic page, language or whatever. Mainly because I didn&apos;t want to have something else to install and maintain just for that on my server.&lt;/p&gt;
&lt;p&gt;It turns out that Apache httpd is powerful enough to implement such a feature. There are different ways to build it, and I&apos;m going to describe my choices here.&lt;/p&gt;
&lt;p&gt;The first thing to pick is a way to balance the display of the page. You need to find a way so that if you get 100 visitors, around 50 will see the version A of your page, and around 50 will see the version B of the page.&lt;/p&gt;
&lt;p&gt;You could use a random number generator, pick a random number for each visitor, and decides which page he&apos;s going to see. But it turns out that I didn&apos;t find a way to do that with Apache httpd at first sight.&lt;/p&gt;
&lt;p&gt;My second thought was to pick the client IP address. But it&apos;s not such a good idea, because if you got visitors from, for example, people behind a company firewall, they are all going to be served the same page, so that kind of kills the statistics.&lt;/p&gt;
&lt;p&gt;Finally, I picked time based balancing: if you visit the page on a second that is even, you get version A of the page, and if you visit the page on a second that is odd, you get version B. Simple, and so far nothing proves there are more visitors on even than odd seconds, or vice-versa.&lt;/p&gt;
&lt;p&gt;The next thing is to always serve the same page to a returning visitor. I mean that if the visitor comes back later and get a different version, that&apos;s cheating. I decided the system should always serve the same page once a visitor &quot;picked&quot; a version. To do that, it&apos;s simple enough, you just have to use cookies to store the page the visitor has been attributed, and then use that cookie if he comes back.&lt;/p&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;p&gt;To do that in Apache httpd, I used the powerful &lt;a href=&quot;http://httpd.apache.org/docs/current/mod/mod_rewrite.html&quot;&gt;mod_rewrite&lt;/a&gt; that is shipped with it. I put 2 files in the books directory, named either &quot;the-hacker-guide-to-python-a.html&quot; and &quot;the-hacker-guide-to-python-b.html&quot; that got served when you requested &quot;&lt;a href=&quot;https://thehackerguidetopython.com&quot;&gt;https://thehackerguidetopython.com&lt;/a&gt;&quot;.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;RewriteEngine On
RewriteBase /books

## If there&apos;s a cookie called thgtp-pre-version set,
## use its value and serve the page
RewriteCond %{HTTP_COOKIE} thgtp-pre-version=([^;])
RewriteRule ^the-hacker-guide-to-python$ %{REQUEST_FILENAME}-%1.html [L]

## No cookie yet and…
RewriteCond %{HTTP_COOKIE} !thgtp-pre-version=([^;]+)
## … the number of seconds of the time right now is even
RewriteCond %{TIME_SEC} [02468]$
## Then serve the page A and store &quot;a&quot; in a cookie
RewriteRule ^the-hacker-guide-to-python$ %{REQUEST_FILENAME}-a.html [cookie=thgtp-pre-version:a:julien.danjou.info,L]

## No cookie yet and…
RewriteCond %{HTTP_COOKIE} !thgtp-pre-version=([^;]+)
## … the number of seconds of the time right now is odd
RewriteCond %{TIME_SEC} [13579]$
## Then serve the page B and store &quot;b&quot; in a cookie
RewriteRule ^the-hacker-guide-to-python$ %{REQUEST_FILENAME}-b.html [cookie=thgtp-pre-version:b:julien.danjou.info,L]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With that few lines, it worked flawlessly.&lt;/p&gt;
&lt;h2&gt;Results&lt;/h2&gt;
&lt;p&gt;The results were very good, as it worked perfectly. Combined with Google Analytics, I was able to follow the score of each page. It turns out that testing this particular little piece of content of the page was, as expected, really useless. The final score didn&apos;t allow to pick any winner. Which also kind of proves that the system worked perfectly.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/content/images/03/google-analytics-ab-testing-thgtp.png&quot; alt=&quot;google-analytics-ab-testing-thgtp&quot; /&gt;&lt;/p&gt;
&lt;p&gt;But it still was an interesting challenge!&lt;/p&gt;
</content:encoded><category>web</category></item><item><title>Overriding cl-json object encoding</title><link>https://julien.danjou.info/blog/cl-postmodern-dao-json/</link><guid isPermaLink="true">https://julien.danjou.info/blog/cl-postmodern-dao-json/</guid><description>CL-JSON provides an encoder for Lisp data structures and objects to JSON format. Unfortunately, in some case, its default encoding mechanism for CLOS objects isn&apos;t exactly doing the right thing.</description><pubDate>Fri, 11 Jan 2013 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;http://common-lisp.net/project/cl-json/&quot;&gt;CL-JSON&lt;/a&gt; provides an encoder for Lisp data structures and objects to JSON format. Unfortunately, in some case, its default encoding mechanism for CLOS objects isn&apos;t exactly doing the right thing. I&apos;ll show you how Common Lisp makes it easy to change that.&lt;/p&gt;
&lt;h2&gt;Identifying the problem&lt;/h2&gt;
&lt;h3&gt;CL-JSON &amp;amp; CLOS&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;CL-JSON&lt;/em&gt; mechanism encoding CLOS object is really neat. Let&apos;s see how it works for a simple case:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(defclass kitten ()
  ((tail :initarg :tail)))

(json:encode-json-to-string (make-instance &apos;kitten :tail &apos;black))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;will produce:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{&quot;tail&quot;:&quot;black&quot;}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Still using CL-JSON, we can also decode the JSON object to a CLOS object:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(slot-value
 (json:with-decoder-simple-clos-semantics
   (json:decode-json-from-string &quot;{\&quot;tail\&quot;:\&quot;black\&quot;}&quot;))
 :tail)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That code will return &lt;em&gt;&quot;black&quot;&lt;/em&gt;. Note that it&apos;s also possible to specify which class should be used when decoding objects, but that&apos;s beyond the purpose of this article.&lt;/p&gt;
&lt;h3&gt;Postmodern&lt;/h3&gt;
&lt;p&gt;Now, let&apos;s introduce &lt;a href=&quot;http://marijnhaverbeke.nl/postmodern/&quot;&gt;Postmodern&lt;/a&gt;, a wonderful Common Lisp system providing access to the wonderful &lt;a href=&quot;http://postgresql.org&quot;&gt;PostgreSQL&lt;/a&gt; database. It also provides a simple system to map rows in a database to CLOS classes, called DAO for &lt;em&gt;Database access objects&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;With this, we can easily store our &lt;em&gt;kitten&lt;/em&gt; into a table.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(defclass kitten ()
  ((tail :initarg :tail))
  (:metaclass postmodern:dao-class))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If we try to encode this to JSON, it will produce the exact same result seen previously.&lt;/p&gt;
&lt;p&gt;The problem is what happens when one of our column has a &lt;em&gt;NULL&lt;/em&gt; value. Postmodern encodes this using the &lt;em&gt;:null&lt;/em&gt; symbol.&lt;/p&gt;
&lt;p&gt;So this code:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(defclass kitten ()
  ((tail :initarg :tail :col-type (or s-sql:db-null text)))
  (:metaclass postmodern:dao-class))

(postmodern:deftable kitten
  (postmodern:!dao-def))

(postmodern:connect-toplevel …)

(postmodern:create-table &apos;kitten)

(json:encode-json-to-string
  (postmodern:make-dao &apos;kitten))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;will return:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&quot;{&quot;tail&quot;:&quot;null&quot;}&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Fail! The fact that the column is &lt;em&gt;NULL&lt;/em&gt; is represented by the &lt;em&gt;:null&lt;/em&gt; symbol. And CL-JSON encodes all symbols as string.&lt;/p&gt;
&lt;p&gt;This is not at all what we want here!&lt;/p&gt;
&lt;h2&gt;Overriding encode-json&lt;/h2&gt;
&lt;p&gt;CL-JSON provides and uses the &lt;em&gt;encode-json&lt;/em&gt; method to encode all kind of object. It is defined as a &lt;em&gt;generic function&lt;/em&gt;, and a lot of different methods are implemented to handle the different standard Common Lisp types. The one used for &lt;em&gt;standard-object&lt;/em&gt; is defined liked that:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(defmethod encode-json ((o standard-object)
                        &amp;amp;optional (stream *json-output*))
  &quot;Write the JSON representation (Object) of the CLOS object O to
STREAM (or to *JSON-OUTPUT*).&quot;
  (with-object (stream)
    (map-slots (stream-object-member-encoder stream) o)))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;All we need to do here, is to create a new method for our &lt;em&gt;kitten&lt;/em&gt; objects, that handles correctly the &lt;em&gt;:null&lt;/em&gt; case.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(defclass kitten ()
  ((tail :initarg :tail :col-type (or s-sql:db-null text)))
  (:metaclass postmodern:dao-class))

(export &apos;kitten)

;; Switch package just to define the new method
(in-package :json)
(defmethod encode-json ((o cl-user:kitten)
                        &amp;amp;optional (stream json:*json-output*))
  &quot;Write the JSON representation (Object) of the postmodern DAO CLOS object
O to STREAM (or to *JSON-OUTPUT*).&quot;
  (with-object (stream)
    (map-slots (lambda (key value)
                 (as-object-member (key stream)
                   (encode-json (if (eq value :null) nil value) stream)))
               o)))

;; Go back into our package
(in-package :cl-user)

(postmodern:deftable kitten
  (postmodern:!dao-def))

(postmodern:connect-toplevel …)

(postmodern:create-table &apos;kitten)

(json:encode-json-to-string
  (postmodern:make-dao &apos;kitten))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With that new method, as soon as we encounter a &lt;em&gt;:null&lt;/em&gt; symbol as a value for an object&apos;s slot, we replace it by &lt;em&gt;nil&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Now if we try to encode another &lt;em&gt;kitten&lt;/em&gt;, we&apos;ll get:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{&quot;tail&quot;:null}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;which is far better for our JavaScript data consumers!&lt;/p&gt;
&lt;p&gt;In the end, I think that this kind of trick is feasible that easily because of the way CLOS provides its generic method implementation.&lt;br /&gt;
The fact that methods don&apos;t belong to any class makes the extension of every program, library and class so much easier. Doing this in another language like Java would likely by impossible, and in Python it would unlikely be as clean as it is done in Common Lisp.&lt;/p&gt;
&lt;p&gt;The ability to teach &lt;em&gt;any&lt;/em&gt; library about how it should handle your class just by defining a new method is really handy!&lt;/p&gt;
</content:encoded><category>lisp</category><category>web</category><category>databases</category></item><item><title>How to make Twitter&apos;s Bootstrap tabs bookmarkable</title><link>https://julien.danjou.info/blog/twitter-bootstrap-tabs-bookmark/</link><guid isPermaLink="true">https://julien.danjou.info/blog/twitter-bootstrap-tabs-bookmark/</guid><description>I&apos;ve been using Twitter&apos;s bootstrap library recently to build this Web site, and wondered how to be able to use the bootstrap-tab Javascript plugin in a bookmark friendly manner.</description><pubDate>Fri, 29 Jun 2012 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I&apos;ve been using &lt;a href=&quot;http://twitter.github.com/bootstrap/&quot;&gt;Twitter&apos;s bootstrap&lt;/a&gt; library recently to build this Web site, and wondered how to be able to use &lt;a href=&quot;http://twitter.github.com/bootstrap/javascript.html#tabs&quot;&gt;the bootstrap-tab&lt;/a&gt; Javascript plugin in a bookmark friendly manner.&lt;/p&gt;
&lt;p&gt;I ended up with a simple solution. These are my first steps in Javascript and front-end manipulation, and it&apos;s really not my area of expertise, so don&apos;t be harsh.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;function bootstrap_tab_bookmark (selector) { if (selector == undefined) {
    selector = &quot;&quot;; }

    /* Automagically jump on good tab based on anchor */
    $(document).ready(function() {
        url = document.location.href.split(&apos;#&apos;);
        if(url[1] != undefined) {
            $(selector + &apos;[href=#&apos;+url[1]+&apos;]&apos;).tab(&apos;show&apos;);
        }
    });

    var update_location = function (event) {
        document.location.hash = this.getAttribute(&quot;href&quot;);
    }

    /* Update hash based on tab */
    $(selector + &quot;[data-toggle=pill]&quot;).click(update_location);
    $(selector + &quot;[data-toggle=tab]&quot;).click(update_location);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;All you need is to use and call this function with a selector (only useful if you have several tabs/pills divisions) when the document is ready.&lt;/p&gt;
&lt;p&gt;The first part takes care of showing the good tab based on the hash contained in the URL. The second part takes care of changing the document location to add the current tab to it when the user clicks.&lt;/p&gt;
</content:encoded><category>web</category></item><item><title>mod_defensible 1.5 released</title><link>https://julien.danjou.info/blog/mod_defensible-1-5/</link><guid isPermaLink="true">https://julien.danjou.info/blog/mod_defensible-1-5/</guid><description>Apache 2.4 being out, I noticed that my good old mod defensible did not compile anymore.</description><pubDate>Tue, 03 Apr 2012 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Apache 2.4 being out, I noticed that my good old &lt;a href=&quot;http://github.com/jd/mod_defensible&quot;&gt;mod_defensible&lt;/a&gt; did not compile anymore.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;http://httpd.apache.org/docs/2.4/developer/new_api_2_4.html&quot;&gt;changes in the new Apache 2.4 API&lt;/a&gt; were small for its concern, so it was pretty easy to update this software to make it compile again.&lt;/p&gt;
&lt;p&gt;Honestly, I&apos;m not sure that this module is really used into the wild, but I still think that it can serve as a good prototype for doing other things so I like keeping it around. :-)&lt;/p&gt;
&lt;p&gt;All this has been triggered by the Apache 2.4 arrival into Debian experimental. Therefore I&apos;ve updated the mod_defensible package to use the new dh_apache2, and imported it into Git at the same time.&lt;/p&gt;
</content:encoded><category>web</category><category>email</category><category>debian</category></item><item><title>OAuth 2.0 for Emacs</title><link>https://julien.danjou.info/blog/oauth-2-0-for-emacs/</link><guid isPermaLink="true">https://julien.danjou.info/blog/oauth-2-0-for-emacs/</guid><description>This week, I&apos;ve finished my OAuth 2.0 client implementation for GNU Emacs.</description><pubDate>Fri, 23 Sep 2011 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;This week, I&apos;ve finished my &lt;a href=&quot;http://oauth.net/2/&quot;&gt;OAuth 2.0&lt;/a&gt; client implementation for &lt;a href=&quot;http://www.gnu.org/software/emacs/&quot;&gt;GNU Emacs&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I have &lt;a href=&quot;http://bzr.savannah.gnu.org/lh/emacs/elpa/revision/126?start_revid=126&quot;&gt;imported it&lt;/a&gt; into &lt;a href=&quot;http://elpa.gnu.org/&quot;&gt;GNU ELPA&lt;/a&gt; so Emacs 24 users will be soon able to install it using the new Emacs packaging system.&lt;/p&gt;
&lt;p&gt;OAuth 2.0 can be used to access, among others, &lt;a href=&quot;http://code.google.com/apis/accounts/docs/OAuth2.html&quot;&gt;Google APIs&lt;/a&gt; or the &lt;a href=&quot;http://developers.facebook.com/docs/authentication/&quot;&gt;Facebook Graph API&lt;/a&gt;.&lt;/p&gt;
</content:encoded><category>emacs</category><category>web</category></item><item><title>Using advanced filter with mod_authnz_ldap</title><link>https://julien.danjou.info/blog/using-advanced-filter-with-mod_authnz_ldap/</link><guid isPermaLink="true">https://julien.danjou.info/blog/using-advanced-filter-with-mod_authnz_ldap/</guid><description>How to work around mod_authnz_ldap&apos;s limited filtering by using a custom LDAP filter for Apache authentication.</description><pubDate>Mon, 04 Apr 2011 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;As you may know, Apache&apos;s &lt;a href=&quot;http://httpd.apache.org/docs/2.2/mod/mod_authnz_ldap.html&quot;&gt;mod_authzn_ldap&lt;/a&gt; allows to authenticate users in Apache HTTP server using an LDAP server. Unfortunately, it has a little implementation flaw.&lt;/p&gt;
&lt;p&gt;The filter used to authenticate the user is built by abusing the &lt;a href=&quot;http://www.ietf.org/rfc/rfc2255.txt&quot;&gt;RFC 2255&lt;/a&gt; which specifies the LDAP URL format. This format has an &quot;attribute&quot; field which is normally used to specify which attributes should be returned. But &lt;em&gt;mod_authzn_ldap&lt;/em&gt; uses this attribute to compare with the username given by the client. That means that you have to have an attribute in your LDAP entries which matches the username, and you have to use it in the &quot;attribute&quot; part of the URL to get things working.&lt;/p&gt;
&lt;p&gt;Therefore, I wrote a patch to add a format string in the LDAP URL in order to user the provided username in the filter, and ignore the attribute part of the URL, which has no use in such a context anyway.&lt;/p&gt;
&lt;p&gt;The bug has been opened in ASF Bugzilla and has number &lt;a href=&quot;https://issues.apache.org/bugzilla/show_bug.cgi?id=51005&quot;&gt;#51005&lt;/a&gt;, with the patch. The patch is backward compatible with the current configuration format, which is not the best choice in theory, but probably the more pragmatic.&lt;/p&gt;
&lt;p&gt;I&apos;ve no clue on the typical delay for patches inclusion in Apache HTTP&lt;br /&gt;
server, so let&apos;s just wait&apos;n see.&lt;/p&gt;
</content:encoded><category>web</category><category>email</category></item><item><title>Kicking out Web spammers with DNSBL</title><link>https://julien.danjou.info/blog/kicking-out-web-spammers-with-dnsbl/</link><guid isPermaLink="true">https://julien.danjou.info/blog/kicking-out-web-spammers-with-dnsbl/</guid><description>Every project has its story. Every war has its winner, and its casualties. They were 20 millions men, fighting for their freedom.  And you&apos;ll never know their story.  Because during last week, I was l</description><pubDate>Mon, 15 Jan 2007 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Every project has its story. Every war has its winner, and its casualties. They were 20 millions men, fighting for their freedom.&lt;/p&gt;
&lt;p&gt;And you&apos;ll never know their story.&lt;/p&gt;
&lt;p&gt;Because during last week, I was looking why my Web server was so heavily loaded. And I discovered that my blog was attacked by spammers trying to post comments. They were stopped by a great plug-in named &lt;em&gt;spamplemousse&lt;/em&gt;, which use spam keywords and DNSBL to drop spam comments. However, this plug-in is written in PHP, like the rest of my blog, so it loads Apache and MySQL in a way that is no more acceptable: the page have still to be rendered for this !@#$ spammers.&lt;/p&gt;
&lt;p&gt;Consequently, I decided to write a Apache 2.x module which will just drop a &lt;em&gt;403 Forbidden&lt;/em&gt; error page in the spammers&apos; head using DNSBL servers. Here it is, and it is called &lt;a href=&quot;https://github.com/jd/mod_defensible&quot;&gt;mod_defensible&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I&apos;m using it since 3 days now, and I got some pretty interesting result and less load on my Web server, so &lt;em&gt;c&apos;est tout bon&lt;/em&gt;.&lt;/p&gt;
</content:encoded><category>web</category><category>email</category><category>security</category></item></channel></rss>