Question

I have a very simple server for use in integration tests, built using eventmachine:

EM.run do
    EM::start_server(server, port, HttpRecipient)    
end

I can receive HTTP requests and parse them like so:

class HttpRecipient < EM::Connection

  def initialize
    @@stored = ''
  end

  # Data is received in chunks, so here we wait until we've got a full web request before
  # calling spool.
  def receive_data(data)
    @@stored << data
    begin
      spool(@@stored)
      EM.stop
    rescue WEBrick::HTTPStatus::BadRequest
      #Not received a complete request yet
    end
  end

  def spool(data)
      #Parse the request
      req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
      req.parse(StringIO.new(@@stored))
      #Send a response, e.g. HTTP OK
  end
end

The question is, how do I send a response? Eventmachine provides a send_data for sending responses, but that doesn't understand http. Similarly there is the em-http-request module for sending requests, but it's not obvious that this is capable of generating responses.

I can generate HTTP messages manually and then send them using send_data, but I wonder if there is a clean way to use an existing http library, or the functionality built in to eventmachine?

Était-ce utile?

La solution

If you want something easy then use Thin or Rainbows. It uses Eventmachine inside and provides Rack interface support.

# config.ru
http_server = proc do |env|
  response = "Hello World!"
  [200, {"Connection" => "close", "Content-Length" => response.bytesize.to_s}, [response]]
end
run http_server

And then

>> thin start -R config.ru

UPD.

If you need server to run in parallel you could run it in a Thread

require 'thin'
class ThreadedServer
  def initialize(*args)
    @server = Thin::Server.new(*args)
  end

  def start
    @thread = Thread.start do
      @server.start
    end
  end

  def stop
    @server.stop
    if @thread
      @thread.join
      @thread = nil
    end
  end
end

http_server = proc do |env|
  response = "Hello World!"
  [200, {"Connection" => "close", "Content-Length" => response.bytesize.to_s}, [response]]
end
server = ThreadedServer.new http_server
server.start
# Some job with server
server.stop
# Server is down
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top