Class: Webmachine::Adapters::Rack

Inherits:
Webmachine::Adapter show all
Defined in:
lib/webmachine/adapters/rack.rb

Overview

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

Direct Known Subclasses

RackMapped

Defined Under Namespace

Classes: RackRequest, RackResponse, RequestBody

Constant Summary collapse

DEFAULT_OPTIONS =

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

{}
REQUEST_URI =
'REQUEST_URI'.freeze
VERSION_STRING =
"#{Webmachine::SERVER_STRING} Rack/#{::Rack.release}".freeze
NEWLINE =
"\n".freeze

Instance Attribute Summary

Attributes inherited from Webmachine::Adapter

#application

Instance Method Summary collapse

Methods inherited from Webmachine::Adapter

#initialize, run

Constructor Details

This class inherits a constructor from Webmachine::Adapter

Instance Method Details

#call(env) ⇒ Object

Handles a Rack-based request.

Parameters:

  • env (Hash)

    the Rack environment



66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/webmachine/adapters/rack.rb', line 66

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 = build_rack_response_headers(response.headers)
  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)
      if rack_v3?
        # In Rack 3 the server (e.g. WEBrick via Rackup) buffers the body
        # and applies chunked encoding itself when Transfer-Encoding is set,
        # so we must not pre-encode with ChunkedBody.
        [response.body.call]
      else
        # Rack 2's WEBrick handler sends the body as-is; ChunkedBody is
        # required to produce valid chunked-encoded wire data.
        Webmachine::ChunkedBody.new(Array(response.body.call))
      end
    elsif response.body.respond_to?(:each)
      if rack_v3?
        # Return the plain enumerable. Rackup buffers it into a String then
        # WEBrick chunks that String when Transfer-Encoding: chunked is set.
        response.body
      elsif response.headers[TRANSFER_ENCODING] == 'chunked'
        # Rack 2: only pre-encode bodies that are already marked chunked;
        # IOEncoder bodies carry their own Content-Length and must not be
        # wrapped.
        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

#runObject

Start the Rack adapter



48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# 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)

  if rack_v3?
    require 'rackup'
    @server = ::Rackup::Server.new(options)
  else
    @server = ::Rack::Server.new(options)
  end
  @server.start
end