Skip to content

Middleware

Renato Riccieri Santos Zannon edited this page Aug 22, 2012 · 6 revisions

Middleware

em-http provides a simple mechanism to inject custom pre and post processing steps for each connection, or globally, through a middleware interface.

First, when the request is issued, em-http will initialize the headers, and then pass control back to your middleware (request(client, headers, body)) where you can inject your own custom logic to modify the headers or body (ex: OAuth headers, encode the body, etc). Once the response is fulfilled, the response(request) callback will be called, where you will have control over the response object before it is passed to the regular callbacks.

require 'json'

class JSONify
  def response(resp)
    resp.response = JSON.parse(resp.response)
  end
end

EventMachine.run do
  conn = EventMachine::HttpRequest.new('http://twitter.com/igrigorik.json')
  conn.use JSONify

  req = conn.get
  req.callback {
    req.response # => { ... twitter data as a Ruby hash ... }
  }
end

In the example above, the JSONify parses the response JSON body before returning control to our regular callback. In similar fashion, you can modify the outbound headers or body of the original request, or do whatever you wish with the response object before you regular code gets to it.

Global vs Connection Middleware

Different middleware filters can be applied on a per connection basis, or, you can specify global middleware filters which will span all requests (ex: insert a custom header across all requests, or parse all returned bodies with custom logic).

EventMachine.run do
  EM::HttpRequest.use GlobalMiddleware

  conn = EventMachine::HttpRequest.new('http://www.website.com/')
  conn.use ConnectionMiddleware
  conn.use OAuthMiddleware, {:config_data => {}} do
    # .. custom signing logic
  end

  req = conn.get
  req.callback { }
end

Creating a middleware

Any class that responds to request(client, headers, body) and response(resp) methods is a valid middleware:

class JSONify
  def request(client, head, body)
    [head, body]
  end

  def response(resp)
    resp.response = JSON.parse(resp.response)
  end
end

Note that request must return the headers and the body when called.

Execution order

Middleware filters will be executed in the order you’ve added them through HttpRequest.use or connection.use. First, global middleware will be executed, then connection specific middleware, and only then will the regular callbacks fire.