class Webmachine::Adapters::Rack

A minimal “shim” adapter to allow Webmachine to interface with Rack. The intention here is to allow Webmachine to run under Rack-compatible web-servers, like unicorn and pow.

The adapter expects your Webmachine application to be mounted at the root path - it will NOT allow you to nest your Webmachine application at an arbitrary path eg. map “/api” { run MyWebmachineAPI } To use map your Webmachine application at an arbitrary path, use the ‘Webmachine::Adapters::RackMapped` subclass instead.

To use this adapter, create a config.ru file and populate it like so:

require 'webmachine/adapters/rack'

# put your own Webmachine resources in another file:
require 'my/resources'

run MyApplication.adapter

Servers like pow and unicorn will read config.ru by default and it should all “just work”.

And for development or testing your application can be run with Rack’s builtin Server identically to the WEBrick adapter with:

MyApplication.run

Constants

DEFAULT_OPTIONS

Used to override default Rack server options (useful in testing)

NEWLINE
REQUEST_URI
VERSION_STRING

Public Instance Methods

call(env) click to toggle source

Handles a Rack-based request. @param [Hash] env the Rack environment

# File lib/webmachine/adapters/rack.rb, line 61
def call(env)
  headers = Webmachine::Headers.from_cgi(env)

  rack_req = ::Rack::Request.new env
  request = build_webmachine_request(rack_req, headers)

  response = Webmachine::Response.new
  application.dispatcher.dispatch(request, response)

  response.headers[SERVER] = VERSION_STRING

  rack_status = response.code
  rack_headers = response.headers.flattened(NEWLINE)
  rack_body = case response.body
  when String # Strings are enumerable in ruby 1.8
    [response.body]
  else
    if (io_body = IO.try_convert(response.body))
      io_body
    elsif response.body.respond_to?(:call)
      Webmachine::ChunkedBody.new(Array(response.body.call))
    elsif response.body.respond_to?(:each)
      # This might be an IOEncoder with a Content-Length, which shouldn't be chunked.
      if response.headers[TRANSFER_ENCODING] == 'chunked'
        Webmachine::ChunkedBody.new(response.body)
      else
        response.body
      end
    else
      [response.body.to_s]
    end
  end

  rack_res = RackResponse.new(rack_body, rack_status, rack_headers)
  rack_res.finish
end
run() click to toggle source

Start the Rack adapter

# File lib/webmachine/adapters/rack.rb, line 48
def run
  options = DEFAULT_OPTIONS.merge({
    app: self,
    Port: application.configuration.port,
    Host: application.configuration.ip
  }).merge(application.configuration.adapter_options)

  @server = ::Rack::Server.new(options)
  @server.start
end

Protected Instance Methods

base_uri(rack_req) click to toggle source
# File lib/webmachine/adapters/rack.rb, line 104
def base_uri(rack_req)
  nil # no-op for default, un-mapped rack adapter
end
routing_tokens(rack_req) click to toggle source
# File lib/webmachine/adapters/rack.rb, line 100
def routing_tokens(rack_req)
  nil # no-op for default, un-mapped rack adapter
end

Private Instance Methods

build_webmachine_request(rack_req, headers) click to toggle source
# File lib/webmachine/adapters/rack.rb, line 110
def build_webmachine_request(rack_req, headers)
  RackRequest.new(rack_req.request_method,
    rack_req.url,
    headers,
    RequestBody.new(rack_req),
    routing_tokens(rack_req),
    base_uri(rack_req),
    rack_req.env)
end