Thin::FunEmbed¶ ↑
This is minimalistic web server for embedding into EventMachine-enabled application based on idea of Nils Franzén, 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
-
with Thin::FunEmbed (see examples/rack_like.rb) ~ 14000 req/sec
-
with ‘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¶ ↑
-
Fork it
-
Create your feature branch (‘git checkout -b my-new-feature`)
-
Commit your changes (‘git commit -am ’Added some feature’‘)
-
Push to the branch (‘git push origin my-new-feature`)
-
Create new Pull Request