Pergunta

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?

Foi útil?

Solução

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
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top