class Phrender::RackMiddleware

Public Class Methods

new(app, opts = {}) click to toggle source
# File lib/phrender/rack_middleware.rb, line 6
def initialize(app, opts = {})
  @app = app
  @index_file = opts[:index_file]
  @javascript_paths = opts[:javascript_files]
  @raw_javascript = opts[:javascript].join(';')
  @phantom = Phrender::PhantomJSEngine.new(opts)
end

Public Instance Methods

call(env) click to toggle source
# File lib/phrender/rack_middleware.rb, line 14
def call(env)
  @req = Rack::Request.new(env)

  # Check if the next middleware can handle the request
  status, headers, body = @app.call(@req.env)

  # If it can't, or if it's just the index file delivered via aliasing for
  # pushstate, do phrender stuff.
  if status == 404 || headers['Push-State-Redirect']
    # If it's phantom making the request, then the phrender index file has
    # a request that the upstream server can't resolve, so catch it, instead
    # of recursively invoking the index
    if @req.user_agent && @req.user_agent.match(/PhantomJS/)
      [ 500, { 'Content-Type'  => 'text/html' }, [
      'Server Error: HTML file contains recursive lookup' ] ]
    else
      # Render the page
      body = render(@req.url)
      [ 200, { 'Content-Type'  => 'text/html' }, [ body ] ]
    end
  else
    [ status, headers, body ]
  end
end

Protected Instance Methods

load_html() click to toggle source
# File lib/phrender/rack_middleware.rb, line 47
def load_html
  req = @req.dup
  req.path_info = @index_file

  # Attach a param to indicate that it's phrender requesting the page. This is
  # only useful if the index file is delivered via a dynamic backend. Ignored
  # otherwise.
  req.update_param('phrender', true)
  req.env['REQUEST_METHOD'] = 'GET'

  status, headers, body = @app.call(req.env)
  parse_body body
end
load_js() click to toggle source
# File lib/phrender/rack_middleware.rb, line 61
def load_js
  js_from_files = @javascript_paths.map do |path|
    if path == :ember_driver
      Phrender::EMBER_DRIVER
    else
      req = @req.dup
      req.path_info = path
      req.env['REQUEST_METHOD'] = 'GET'

      status, headers, body = @app.call(req.env)
      parse_body body
    end
  end.join(';')
  program = js_from_files + @raw_javascript
  program.to_s
end
parse_body(body) click to toggle source
# File lib/phrender/rack_middleware.rb, line 78
def parse_body(body)
  # Rack responses must respond to each, which is generally a polyfil that
  # yields the response, so reassemble it here, or just treat it like a
  # string.
  if body.respond_to? :each
    data = ''
    body.each{ |part| data << part }
    data
  else
    body.to_s
  end
end
render(request_uri) click to toggle source
# File lib/phrender/rack_middleware.rb, line 41
def render(request_uri)
  program = load_js
  html = load_html
  @phantom.render(html, program, request_uri)
end