thin-fun_embed

trim of Thin web server for embedding into eventmachined application

MIT License

Downloads
16.4K
Stars
9
Committers
1

= 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

  • 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

  1. Fork it
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Added some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create new Pull Request