trim of Thin web server for embedding into eventmachined application
MIT License
= Thin::FunEmbed
This is minimalistic web server for embedding into EventMachine-enabled application based on {idea of Nils Franzén}[http://www.franzens.org/2011/10/writing-minimalistic-web-server-using.html], but it uses origin Thin::Request instead of custom wrapper to thin parser.
It is intentionally not full fledge rack server, but you could use +send_status_headers_body+ to return rack application's response to client.
It is capable to serve keep-alive requests (but not pipelined).
It is faster than Thin itself cause it allows you to send very custom response, and even for Rack like response it doesn't do many checks on your output. But it meens, that you responsible for you response :)
Rack hello world, tested with +ab -k -c 500 -n 50000 127.0.0.1:8080/+ on Core i3@1600Mhz
thin -p 8080 -e production start
~ 6500 req/sec(But consider, that this is for very dump response. Do not expect big speedup for heavy weight ones')
Also, it doesn't bother with keep-alive timeouts, limits and many other things that Thin do. But it is not too hard too look for them in the Thin's sources. And, in any way, it is better to place this "server" behind "something like" Nginx, which could use keep-alive connections to upstream since version 1.1 .
== Installation
Add this line to your application's Gemfile:
gem 'thin-fun_embed'
And then execute:
$ bundle
Or install it yourself as:
$ gem install thin-fun_embed
== Usage
You should subclass Thin::FunEmbed and override #handle_http_request method. Then you should start it with EM.start_server as any other EM::Connection .
Abstract example: require 'thin/fun_embed.rb' class MyServer < Thin::FunEmbed def handle_http_request(env) if rack_like_response? send_status_headers_body(status, headers, body) elsif is_200_ok? send_200_ok(body) elsif is_status_body? send_status_body(status, body) elsif is_raw_string? send_raw_string(full_http_response_string, try_to_keep_alive) end end end
host, port = '0.0.0.0', 8080 EM.run do EM.start_server host, port, MyServer end
200 ok example: require 'thin/fun_embed.rb'
class Simple200ok < Thin::FunEmbed def handle_http_request(env) if rand(2) == 1 send_200_ok('{"hello":"world"}', 'application/javascript') else send_200_ok('hello world') end end end
EM.run do EM.start_server '0.0.0.0', 8080, Simple200ok end
Rack like example with correct socket closing: require 'thin/fun_embed.rb'
class RackLikeServer < Thin::FunEmbed attr_accessor :app def handle_http_request(env) send_rack_response(*app.call(env)) end end
app = proc{|env| [200, {'Content-Length'=>6}, ['hello', "\n"]]}
host, port = '0.0.0.0', 8080 all_conns = {} trap(:INT) do EM.schedule{ all_conns.each{|conn, _| conn.close_after_writting} EM.next_tick{ EM.stop } } end
EM.run do EM.start_server host, port, RackLikeServer do |conn| conn.app = app all_conns[conn] = true conn.unbind_callback = all_conns.method(:delete) end end
== Contributing
git checkout -b my-new-feature
)git commit -am 'Added some feature'
)git push origin my-new-feature
)