Skip to content

Middleware

Ilya Grigorik edited this page Feb 1, 2011 · 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(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 self.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 middleware 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 Request Middleware

Different middleware filters can be applied on a per connection basis, or, you can provide a global middleware that 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

  req = conn.get
  req.callback { }
end

Creating a middleware

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

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

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

Note that self.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.