<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Aapo Talvensaari on Medium]]></title>
        <description><![CDATA[Stories by Aapo Talvensaari on Medium]]></description>
        <link>https://medium.com/@bungle?source=rss-c5ca7e8e6622------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*VJPUXpBsy0wa14KKJsIAmQ.jpeg</url>
            <title>Stories by Aapo Talvensaari on Medium</title>
            <link>https://medium.com/@bungle?source=rss-c5ca7e8e6622------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sat, 16 May 2026 17:23:30 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@bungle/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[WebSockets with OpenResty]]></title>
            <link>https://medium.com/technology-and-programming/websockets-with-openresty-1778601c9e05?source=rss-c5ca7e8e6622------2</link>
            <guid isPermaLink="false">https://medium.com/p/1778601c9e05</guid>
            <dc:creator><![CDATA[Aapo Talvensaari]]></dc:creator>
            <pubDate>Mon, 16 Sep 2013 21:22:07 GMT</pubDate>
            <atom:updated>2014-08-14T08:59:29.111Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/700/0*4YkQe4c9XENmP1L4.png" /></figure><h4>Lua WebSocket Implementation Installation</h4><blockquote>This blog post is updated for OpenResty 1.4.2.9.</blockquote><p>I have been following <a href="http://openresty.org/">OpenResty</a> development closely for a while now, but I did never got an inspiration to really try it out, until now. Yichun Zhang (<a href="https://github.com/agentzh">@agentzh</a>) of OpenResty-fame <a href="https://twitter.com/agentzh/status/378612823934251010">announced</a> that he just released a preliminary WebSockets support for Lua Nginx module (<a href="https://github.com/chaoslawful/lua-nginx-module">lua-nginx-module</a>). I have been <a href="https://github.com/chaoslawful/lua-nginx-module/issues/165#issuecomment-14015192">waiting</a> for this to happen.</p><p>I managed to install, and test this on my Mac. Here is how I did it:</p><pre>$ brew install pcre<br>$ wget http://openresty.org/download/ngx_openresty-1.4.2.9.tar.gz<br>$ tar zxf ngx_openresty-1.4.2.9.tar.gz<br>$ cd ngx_openresty-1.4.2.9<br>$ ./configure \<br>    --with-luajit \<br>    --with-cc-opt=&quot;-I/usr/local/Cellar/pcre/8.33/include&quot; \<br>    --with-ld-opt=&quot;-L/usr/local/Cellar/pcre/8.33/lib&quot;<br>$ make<br>$ make install</pre><p>Now we should have OpenResty installed with Lua module that supports WebSockets at /usr/local/openresty.</p><p>Next we need to write the WebSockets server code (right now just a stupid echoing server). Again, edit nginx.conf, and add a new location after “location / { … }”:</p><pre>location /s {<br>  lua_socket_log_errors off;<br>  lua_check_client_abort on;<br>  content_by_lua &#39;<br>    local server = require &quot;resty.websocket.server&quot;<br>    local wb, err = server:new{<br>      timeout = 5000,<br>      max_payload_len = 65535<br>    }<br>    if not wb then<br>      ngx.log(ngx.ERR, &quot;failed to new websocket: &quot;, err)<br>      return ngx.exit(444)<br>    end<br>    while true do<br>      local data, typ, err = wb:recv_frame()<br>      if wb.fatal then<br>        ngx.log(ngx.ERR, &quot;failed to receive frame: &quot;, err)<br>        return ngx.exit(444)<br>      end<br>      if not data then<br>        local bytes, err = wb:send_ping()<br>        if not bytes then<br>          ngx.log(ngx.ERR, &quot;failed to send ping: &quot;, err)<br>          return ngx.exit(444)<br>        end<br>      elseif typ == &quot;close&quot; then break<br>      elseif typ == &quot;ping&quot; then<br>        local bytes, err = wb:send_pong()<br>        if not bytes then<br>          ngx.log(ngx.ERR, &quot;failed to send pong: &quot;, err)<br>          return ngx.exit(444)<br>        end<br>      elseif typ == &quot;pong&quot; then<br>        ngx.log(ngx.INFO, &quot;client ponged&quot;)<br>      elseif typ == &quot;text&quot; then<br>        local bytes, err = wb:send_text(data)<br>        if not bytes then<br>          ngx.log(ngx.ERR, &quot;failed to send text: &quot;, err)<br>          return ngx.exit(444)<br>        end<br>      end<br>    end<br>    wb:send_close()<br>  &#39;;<br>}</pre><p>Looks great. Now add websockets.html to /usr/local/openresty/nginx/html directory:</p><pre>&lt;html&gt;<br>&lt;head&gt;<br>&lt;script&gt;<br>var ws = null;<br>function connect() {<br>  if (ws !== null) return log(&#39;already connected&#39;);<br>  ws = new WebSocket(&#39;ws://127.0.0.1/s/&#39;);<br>  ws.onopen = function () {<br>    log(&#39;connected&#39;);<br>  };<br>  ws.onerror = function (error) {<br>    log(error);<br>  };<br>  ws.onmessage = function (e) {<br>    log(&#39;recv: &#39; + e.data);<br>  };<br>  ws.onclose = function () {<br>    log(&#39;disconnected&#39;);<br>    ws = null;<br>  };<br>  return false;<br>}<br>function disconnect() {<br>  if (ws === null) return log(&#39;already disconnected&#39;);<br>  ws.close();<br>  return false;<br>}<br>function send() {<br>  if (ws === null) return log(&#39;please connect first&#39;);<br>  var text = document.getElementById(&#39;text&#39;).value;<br>  document.getElementById(&#39;text&#39;).value = &quot;&quot;;<br>  log(&#39;send: &#39; + text);<br>  ws.send(text);<br>  return false;<br>}<br>function log(text) {<br>  var li = document.createElement(&#39;li&#39;);<br>  li.appendChild(document.createTextNode(text));<br>  document.getElementById(&#39;log&#39;).appendChild(li);<br>  return false;<br>}<br>&lt;/script&gt;<br>&lt;/head&gt;<br>&lt;body&gt;<br>  &lt;form onsubmit=&quot;return send();&quot;&gt;<br>    &lt;button type=&quot;button&quot; onclick=&quot;return connect();&quot;&gt;<br>      Connect<br>    &lt;/button&gt;<br>    &lt;button type=&quot;button&quot; onclick=&quot;return disconnect();&quot;&gt;<br>      Disconnect<br>    &lt;/button&gt;<br>    &lt;input id=&quot;text&quot; type=&quot;text&quot;&gt;<br>    &lt;button type=&quot;submit&quot;&gt;Send&lt;/button&gt;<br>  &lt;/form&gt;<br>  &lt;ol id=&quot;log&quot;&gt;&lt;/ol&gt;<br>&lt;/body&gt;<br>&lt;/html&gt;</pre><p>And now start the nginx with:</p><pre>sudo /usr/local/openresty/nginx/sbin/nginx</pre><p>Then open a browser that has WebSocket support enabled, and open following url:</p><pre><a href="http://127.0.0.1/websockets.html">http://127.0.0.1/websockets.html</a></pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/766/0*CMw6ds22UvLkxFIE.png" /><figcaption>Lua Web Sockets in Action</figcaption></figure><p>To guard against half-open TCP connections, it is a good idea to enable TCP keepalive in your Nginx listen configuration directive:</p><pre># so_keepalive=on|off|[<em>keepidle</em>]:[<em>keepintvl</em>]:[<em>keepcnt</em>]];<br># for example:<br>listen 80 so_keepalive=2s:2s:8;</pre><p>(<a href="http://nginx.org/en/docs/http/ngx_http_core_module.html#listen">nginx documentation about so_keepalive</a>)</p><p>You could also do this on system level, if you wish:</p><pre>$ sysctl net.inet.tcp.always_keepalive<br>net.inet.tcp.always_keepalive: 0<br>$ sudo sysctl -w net.inet.tcp.always_keepalive=1<br>net.inet.tcp.always_keepalive: 0 -&gt; 1</pre><p>(for Linux, see: <a href="http://tldp.org/HOWTO/TCP-Keepalive-HOWTO/usingkeepalive.html">Using TCP keepalive under Linux</a>)</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=1778601c9e05" width="1" height="1" alt=""><hr><p><a href="https://medium.com/technology-and-programming/websockets-with-openresty-1778601c9e05">WebSockets with OpenResty</a> was originally published in <a href="https://medium.com/technology-and-programming">Technology, and Programming</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>