deb-python-eventlet/doc/modules/wsgi.html

322 lines
25 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>wsgi WSGI server &mdash; Eventlet 0.20.0 documentation</title>
<link rel="stylesheet" href="../_static/classic.css" type="text/css" />
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: '../',
VERSION: '0.20.0',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true
};
</script>
<script type="text/javascript" src="../_static/jquery.js"></script>
<script type="text/javascript" src="../_static/underscore.js"></script>
<script type="text/javascript" src="../_static/doctools.js"></script>
<link rel="top" title="Eventlet 0.20.0 documentation" href="../index.html" />
<link rel="up" title="Module Reference" href="../modules.html" />
<link rel="next" title="eventlet.green.zmq ØMQ support" href="zmq.html" />
<link rel="prev" title="websocket Websocket Server" href="websocket.html" />
</head>
<body role="document">
<div class="related" role="navigation" aria-label="related navigation">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="zmq.html" title="eventlet.green.zmq ØMQ support"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="websocket.html" title="websocket Websocket Server"
accesskey="P">previous</a> |</li>
<li class="nav-item nav-item-0"><a href="../index.html">Eventlet 0.20.0 documentation</a> &raquo;</li>
<li class="nav-item nav-item-1"><a href="../modules.html" accesskey="U">Module Reference</a> &raquo;</li>
</ul>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<div class="section" id="wsgi-wsgi-server">
<h1><code class="xref py py-mod docutils literal"><span class="pre">wsgi</span></code> &#8211; WSGI server<a class="headerlink" href="#wsgi-wsgi-server" title="Permalink to this headline"></a></h1>
<p>The wsgi module provides a simple and easy way to start an event-driven
<a class="reference external" href="http://wsgi.org/wsgi/">WSGI</a> server. This can serve as an embedded
web server in an application, or as the basis for a more full-featured web
server package. One such package is <a class="reference external" href="http://pypi.python.org/pypi/Spawning/">Spawning</a>.</p>
<p>To launch a wsgi server, simply create a socket and call <a class="reference internal" href="#eventlet.wsgi.server" title="eventlet.wsgi.server"><code class="xref py py-func docutils literal"><span class="pre">eventlet.wsgi.server()</span></code></a> with it:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">eventlet</span> <span class="kn">import</span> <span class="n">wsgi</span>
<span class="kn">import</span> <span class="nn">eventlet</span>
<span class="k">def</span> <span class="nf">hello_world</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">start_response</span><span class="p">):</span>
<span class="n">start_response</span><span class="p">(</span><span class="s1">&#39;200 OK&#39;</span><span class="p">,</span> <span class="p">[(</span><span class="s1">&#39;Content-Type&#39;</span><span class="p">,</span> <span class="s1">&#39;text/plain&#39;</span><span class="p">)])</span>
<span class="k">return</span> <span class="p">[</span><span class="s1">&#39;Hello, World!</span><span class="se">\r\n</span><span class="s1">&#39;</span><span class="p">]</span>
<span class="n">wsgi</span><span class="o">.</span><span class="n">server</span><span class="p">(</span><span class="n">eventlet</span><span class="o">.</span><span class="n">listen</span><span class="p">((</span><span class="s1">&#39;&#39;</span><span class="p">,</span> <span class="mi">8090</span><span class="p">)),</span> <span class="n">hello_world</span><span class="p">)</span>
</pre></div>
</div>
<p>You can find a slightly more elaborate version of this code in the file
<code class="docutils literal"><span class="pre">examples/wsgi.py</span></code>.</p>
<span class="target" id="module-eventlet.wsgi"></span><dl class="function">
<dt id="eventlet.wsgi.server">
<code class="descclassname">eventlet.wsgi.</code><code class="descname">server</code><span class="sig-paren">(</span><em>sock</em>, <em>site</em>, <em>log=None</em>, <em>environ=None</em>, <em>max_size=None</em>, <em>max_http_version='HTTP/1.1'</em>, <em>protocol=&lt;class 'eventlet.wsgi.HttpProtocol'&gt;</em>, <em>server_event=None</em>, <em>minimum_chunk_size=None</em>, <em>log_x_forwarded_for=True</em>, <em>custom_pool=None</em>, <em>keepalive=True</em>, <em>log_output=True</em>, <em>log_format='%(client_ip)s - - [%(date_time)s] &quot;%(request_line)s&quot; %(status_code)s %(body_length)s %(wall_seconds).6f'</em>, <em>url_length_limit=8192</em>, <em>debug=True</em>, <em>socket_timeout=None</em>, <em>capitalize_response_headers=True</em><span class="sig-paren">)</span><a class="headerlink" href="#eventlet.wsgi.server" title="Permalink to this definition"></a></dt>
<dd><p>Start up a WSGI server handling requests from the supplied server
socket. This function loops forever. The <em>sock</em> object will be
closed after server exits, but the underlying file descriptor will
remain open, so if you have a dup() of <em>sock</em>, it will remain usable.</p>
<div class="admonition warning">
<p class="first admonition-title">Warning</p>
<p>At the moment <a class="reference internal" href="#eventlet.wsgi.server" title="eventlet.wsgi.server"><code class="xref py py-func docutils literal"><span class="pre">server()</span></code></a> will always wait for active connections to finish before
exiting, even if there&#8217;s an exception raised inside it
(<em>all</em> exceptions are handled the same way, including <code class="xref py py-class docutils literal"><span class="pre">greenlet.GreenletExit</span></code>
and those inheriting from <cite>BaseException</cite>).</p>
<p class="last">While this may not be an issue normally, when it comes to long running HTTP connections
(like <a class="reference internal" href="websocket.html#module-eventlet.websocket" title="eventlet.websocket"><code class="xref py py-mod docutils literal"><span class="pre">eventlet.websocket</span></code></a>) it will become problematic and calling
<a class="reference internal" href="greenthread.html#eventlet.greenthread.GreenThread.wait" title="eventlet.greenthread.GreenThread.wait"><code class="xref py py-meth docutils literal"><span class="pre">wait()</span></code></a> on a thread that runs the server may hang,
even after using <a class="reference internal" href="greenthread.html#eventlet.greenthread.GreenThread.kill" title="eventlet.greenthread.GreenThread.kill"><code class="xref py py-meth docutils literal"><span class="pre">kill()</span></code></a>, as long
as there are active connections.</p>
</div>
<table class="docutils field-list" frame="void" rules="none">
<col class="field-name" />
<col class="field-body" />
<tbody valign="top">
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first last simple">
<li><strong>sock</strong> &#8211; Server socket, must be already bound to a port and listening.</li>
<li><strong>site</strong> &#8211; WSGI application function.</li>
<li><strong>log</strong> &#8211; logging.Logger instance or file-like object that logs should be written to.
If a Logger instance is supplied, messages are sent to the INFO log level.
If not specified, sys.stderr is used.</li>
<li><strong>environ</strong> &#8211; Additional parameters that go into the environ dictionary of every request.</li>
<li><strong>max_size</strong> &#8211; Maximum number of client connections opened at any time by this server.
Default is 1024.</li>
<li><strong>max_http_version</strong> &#8211; Set to &#8220;HTTP/1.0&#8221; to make the server pretend it only supports HTTP 1.0.
This can help with applications or clients that don&#8217;t behave properly using HTTP 1.1.</li>
<li><strong>protocol</strong> &#8211; Protocol class. Deprecated.</li>
<li><strong>server_event</strong> &#8211; Used to collect the Server object. Deprecated.</li>
<li><strong>minimum_chunk_size</strong> &#8211; Minimum size in bytes for http chunks. This can be used to improve
performance of applications which yield many small strings, though
using it technically violates the WSGI spec. This can be overridden
on a per request basis by setting environ[&#8216;eventlet.minimum_write_chunk_size&#8217;].</li>
<li><strong>log_x_forwarded_for</strong> &#8211; If True (the default), logs the contents of the x-forwarded-for
header in addition to the actual client ip address in the &#8216;client_ip&#8217; field of the
log line.</li>
<li><strong>custom_pool</strong> &#8211; A custom GreenPool instance which is used to spawn client green threads.
If this is supplied, max_size is ignored.</li>
<li><strong>keepalive</strong> &#8211; If set to False, disables keepalives on the server; all connections will be
closed after serving one request.</li>
<li><strong>log_output</strong> &#8211; A Boolean indicating if the server will log data or not.</li>
<li><strong>log_format</strong> &#8211; A python format string that is used as the template to generate log lines.
The following values can be formatted into it: client_ip, date_time, request_line,
status_code, body_length, wall_seconds. The default is a good example of how to
use it.</li>
<li><strong>url_length_limit</strong> &#8211; A maximum allowed length of the request url. If exceeded, 414 error
is returned.</li>
<li><strong>debug</strong> &#8211; True if the server should send exception tracebacks to the clients on 500 errors.
If False, the server will respond with empty bodies.</li>
<li><strong>socket_timeout</strong> &#8211; Timeout for client connections&#8217; socket operations. Default None means
wait forever.</li>
<li><strong>capitalize_response_headers</strong> &#8211; Normalize response headers&#8217; names to Foo-Bar.
Default is True.</li>
</ul>
</td>
</tr>
</tbody>
</table>
</dd></dl>
<dl class="function">
<dt id="eventlet.wsgi.format_date_time">
<code class="descclassname">eventlet.wsgi.</code><code class="descname">format_date_time</code><span class="sig-paren">(</span><em>timestamp</em><span class="sig-paren">)</span><a class="headerlink" href="#eventlet.wsgi.format_date_time" title="Permalink to this definition"></a></dt>
<dd><p>Formats a unix timestamp into an HTTP standard string.</p>
</dd></dl>
<div class="section" id="ssl">
<span id="wsgi-ssl"></span><h2>SSL<a class="headerlink" href="#ssl" title="Permalink to this headline"></a></h2>
<p>Creating a secure server is only slightly more involved than the base example. All that&#8217;s needed is to pass an SSL-wrapped socket to the <a class="reference internal" href="#eventlet.wsgi.server" title="eventlet.wsgi.server"><code class="xref py py-func docutils literal"><span class="pre">server()</span></code></a> method:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="n">wsgi</span><span class="o">.</span><span class="n">server</span><span class="p">(</span><span class="n">eventlet</span><span class="o">.</span><span class="n">wrap_ssl</span><span class="p">(</span><span class="n">eventlet</span><span class="o">.</span><span class="n">listen</span><span class="p">((</span><span class="s1">&#39;&#39;</span><span class="p">,</span> <span class="mi">8090</span><span class="p">)),</span>
<span class="n">certfile</span><span class="o">=</span><span class="s1">&#39;cert.crt&#39;</span><span class="p">,</span>
<span class="n">keyfile</span><span class="o">=</span><span class="s1">&#39;private.key&#39;</span><span class="p">,</span>
<span class="n">server_side</span><span class="o">=</span><span class="bp">True</span><span class="p">),</span>
<span class="n">hello_world</span><span class="p">)</span>
</pre></div>
</div>
<p>Applications can detect whether they are inside a secure server by the value of the <code class="docutils literal"><span class="pre">env['wsgi.url_scheme']</span></code> environment variable.</p>
</div>
<div class="section" id="non-standard-extension-to-support-post-hooks">
<h2>Non-Standard Extension to Support Post Hooks<a class="headerlink" href="#non-standard-extension-to-support-post-hooks" title="Permalink to this headline"></a></h2>
<p>Eventlet&#8217;s WSGI server supports a non-standard extension to the WSGI
specification where <code class="samp docutils literal"><span class="pre">env['eventlet.posthooks']</span></code> contains an array of
<cite>post hooks</cite> that will be called after fully sending a response. Each post hook
is a tuple of <code class="samp docutils literal"><span class="pre">(func,</span> <span class="pre">args,</span> <span class="pre">kwargs)</span></code> and the <cite>func</cite> will be called with
the WSGI environment dictionary, followed by the <cite>args</cite> and then the <cite>kwargs</cite>
in the post hook.</p>
<p>For example:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">eventlet</span> <span class="kn">import</span> <span class="n">wsgi</span>
<span class="kn">import</span> <span class="nn">eventlet</span>
<span class="k">def</span> <span class="nf">hook</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">arg1</span><span class="p">,</span> <span class="n">arg2</span><span class="p">,</span> <span class="n">kwarg3</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span> <span class="n">kwarg4</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span>
<span class="k">print</span><span class="p">(</span><span class="s1">&#39;Hook called: </span><span class="si">%s</span><span class="s1"> </span><span class="si">%s</span><span class="s1"> </span><span class="si">%s</span><span class="s1"> </span><span class="si">%s</span><span class="s1"> </span><span class="si">%s</span><span class="s1">&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">arg1</span><span class="p">,</span> <span class="n">arg2</span><span class="p">,</span> <span class="n">kwarg3</span><span class="p">,</span> <span class="n">kwarg4</span><span class="p">))</span>
<span class="k">def</span> <span class="nf">hello_world</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">start_response</span><span class="p">):</span>
<span class="n">env</span><span class="p">[</span><span class="s1">&#39;eventlet.posthooks&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
<span class="p">(</span><span class="n">hook</span><span class="p">,</span> <span class="p">(</span><span class="s1">&#39;arg1&#39;</span><span class="p">,</span> <span class="s1">&#39;arg2&#39;</span><span class="p">),</span> <span class="p">{</span><span class="s1">&#39;kwarg3&#39;</span><span class="p">:</span> <span class="mi">3</span><span class="p">,</span> <span class="s1">&#39;kwarg4&#39;</span><span class="p">:</span> <span class="mi">4</span><span class="p">}))</span>
<span class="n">start_response</span><span class="p">(</span><span class="s1">&#39;200 OK&#39;</span><span class="p">,</span> <span class="p">[(</span><span class="s1">&#39;Content-Type&#39;</span><span class="p">,</span> <span class="s1">&#39;text/plain&#39;</span><span class="p">)])</span>
<span class="k">return</span> <span class="p">[</span><span class="s1">&#39;Hello, World!</span><span class="se">\r\n</span><span class="s1">&#39;</span><span class="p">]</span>
<span class="n">wsgi</span><span class="o">.</span><span class="n">server</span><span class="p">(</span><span class="n">eventlet</span><span class="o">.</span><span class="n">listen</span><span class="p">((</span><span class="s1">&#39;&#39;</span><span class="p">,</span> <span class="mi">8090</span><span class="p">)),</span> <span class="n">hello_world</span><span class="p">)</span>
</pre></div>
</div>
<p>The above code will print the WSGI environment and the other passed function
arguments for every request processed.</p>
<p>Post hooks are useful when code needs to be executed after a response has been
fully sent to the client (or when the client disconnects early). One example is
for more accurate logging of bandwidth used, as client disconnects use less
bandwidth than the actual Content-Length.</p>
</div>
<div class="section" id="continue-response-headers">
<h2>&#8220;100 Continue&#8221; Response Headers<a class="headerlink" href="#continue-response-headers" title="Permalink to this headline"></a></h2>
<p>Eventlet&#8217;s WSGI server supports sending (optional) headers with HTTP &#8220;100 Continue&#8221;
provisional responses. This is useful in such cases where a WSGI server expects
to complete a PUT request as a single HTTP request/response pair, and also wants to
communicate back to client as part of the same HTTP transaction. An example is
where the HTTP server wants to pass hints back to the client about characteristics
of data payload it can accept. As an example, an HTTP server may pass a hint in a
header the accompanying &#8220;100 Continue&#8221; response to the client indicating it can or
cannot accept encrypted data payloads, and thus client can make the encrypted vs
unencrypted decision before starting to send the data).</p>
<p>This works well for WSGI servers as the WSGI specification mandates HTTP
expect/continue mechanism (PEP333).</p>
<p>To define the &#8220;100 Continue&#8221; response headers, one may call
<code class="xref py py-func docutils literal"><span class="pre">set_hundred_continue_response_header()</span></code> on <code class="samp docutils literal"><span class="pre">env['wsgi.input']</span></code>
as shown in the following example:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">eventlet</span> <span class="kn">import</span> <span class="n">wsgi</span>
<span class="kn">import</span> <span class="nn">eventlet</span>
<span class="k">def</span> <span class="nf">wsgi_app</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">start_response</span><span class="p">):</span>
<span class="c1"># Define &quot;100 Continue&quot; response headers</span>
<span class="n">env</span><span class="p">[</span><span class="s1">&#39;wsgi.input&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">set_hundred_continue_response_headers</span><span class="p">(</span>
<span class="p">[(</span><span class="s1">&#39;Hundred-Continue-Header-1&#39;</span><span class="p">,</span> <span class="s1">&#39;H1&#39;</span><span class="p">),</span>
<span class="p">(</span><span class="s1">&#39;Hundred-Continue-Header-k&#39;</span><span class="p">,</span> <span class="s1">&#39;Hk&#39;</span><span class="p">)])</span>
<span class="c1"># The following read() causes &quot;100 Continue&quot; response to</span>
<span class="c1"># the client. Headers &#39;Hundred-Continue-Header-1&#39; and</span>
<span class="c1"># &#39;Hundred-Continue-Header-K&#39; are sent with the response</span>
<span class="c1"># following the &quot;HTTP/1.1 100 Continue\r\n&quot; status line</span>
<span class="n">text</span> <span class="o">=</span> <span class="n">env</span><span class="p">[</span><span class="s1">&#39;wsgi.input&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">read</span><span class="p">()</span>
<span class="n">start_response</span><span class="p">(</span><span class="s1">&#39;200 OK&#39;</span><span class="p">,</span> <span class="p">[(</span><span class="s1">&#39;Content-Length&#39;</span><span class="p">,</span> <span class="nb">str</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">text</span><span class="p">)))])</span>
<span class="k">return</span> <span class="p">[</span><span class="n">text</span><span class="p">]</span>
</pre></div>
</div>
<p>You can find a more elaborate example in the file:
<code class="docutils literal"><span class="pre">tests/wsgi_test.py</span></code>, <code class="xref py py-func docutils literal"><span class="pre">test_024a_expect_100_continue_with_headers()</span></code>.</p>
<p>Per HTTP RFC 7231 (<a class="reference external" href="http://tools.ietf.org/html/rfc7231#section-6.2">http://tools.ietf.org/html/rfc7231#section-6.2</a>) a client is
required to be able to process one or more 100 continue responses. A sample
use case might be a user protocol where the server may want to use a 100-continue
response to indicate to a client that it is working on a request and the
client should not timeout.</p>
<p>To support multiple 100-continue responses, evenlet wsgi module exports
the API <code class="xref py py-func docutils literal"><span class="pre">send_hundred_continue_response()</span></code>.</p>
<p>Sample use cases for chunked and non-chunked HTTP scenarios are included
in the wsgi test case <code class="docutils literal"><span class="pre">tests/wsgi_test.py</span></code>,
<code class="xref py py-func docutils literal"><span class="pre">test_024b_expect_100_continue_with_headers_multiple_chunked()</span></code> and
<code class="xref py py-func docutils literal"><span class="pre">test_024c_expect_100_continue_with_headers_multiple_nonchunked()</span></code>.</p>
</div>
</div>
</div>
</div>
</div>
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
<div class="sphinxsidebarwrapper">
<h3><a href="../index.html">Table Of Contents</a></h3>
<ul>
<li><a class="reference internal" href="#"><code class="docutils literal"><span class="pre">wsgi</span></code> &#8211; WSGI server</a><ul>
<li><a class="reference internal" href="#ssl">SSL</a></li>
<li><a class="reference internal" href="#non-standard-extension-to-support-post-hooks">Non-Standard Extension to Support Post Hooks</a></li>
<li><a class="reference internal" href="#continue-response-headers">&#8220;100 Continue&#8221; Response Headers</a></li>
</ul>
</li>
</ul>
<h4>Previous topic</h4>
<p class="topless"><a href="websocket.html"
title="previous chapter"><code class="docutils literal"><span class="pre">websocket</span></code> &#8211; Websocket Server</a></p>
<h4>Next topic</h4>
<p class="topless"><a href="zmq.html"
title="next chapter"><code class="docutils literal"><span class="pre">eventlet.green.zmq</span></code> &#8211; ØMQ support</a></p>
<div role="note" aria-label="source link">
<h3>This Page</h3>
<ul class="this-page-menu">
<li><a href="../_sources/modules/wsgi.txt"
rel="nofollow">Show Source</a></li>
</ul>
</div>
<div id="searchbox" style="display: none" role="search">
<h3>Quick search</h3>
<form class="search" action="../search.html" method="get">
<input type="text" name="q" />
<input type="submit" value="Go" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
<p class="searchtip" style="font-size: 90%">
Enter search terms or a module, class or function name.
</p>
</div>
<script type="text/javascript">$('#searchbox').show(0);</script>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="related" role="navigation" aria-label="related navigation">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="General Index"
>index</a></li>
<li class="right" >
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="zmq.html" title="eventlet.green.zmq ØMQ support"
>next</a> |</li>
<li class="right" >
<a href="websocket.html" title="websocket Websocket Server"
>previous</a> |</li>
<li class="nav-item nav-item-0"><a href="../index.html">Eventlet 0.20.0 documentation</a> &raquo;</li>
<li class="nav-item nav-item-1"><a href="../modules.html" >Module Reference</a> &raquo;</li>
</ul>
</div>
<div class="footer" role="contentinfo">
&copy; Copyright 2005-2010, Eventlet Contributors.
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.3.5.
</div>
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-42952223-1', 'eventlet.net');
ga('send', 'pageview');
</script>
</body>
</html>