Class: Sidewalk::Application

Inherits:
Object
  • Object
show all
Defined in:
lib/sidewalk/application.rb

Overview

The main Rack Application.

This class is responsible for dispatch requests (based on a UriMapper), and handling some exceptions, such as NotFoundError, ForbiddenError, or SeeOtherRedirect.

If you want special error handling, subclass this, and reimplement #respond_to_error.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(uri_map) ⇒ Application

Construct an instance, based on a URI-mapping Hash.

Parameters:

  • uri_map (Hash)

    is a String => Class, Symbol, String, or Proc map. See UriMapper#initialize for details of acceptable keys; the short version is that they are Strings that contain regular expression patterns. They are not Regexps.



37
38
39
# File 'lib/sidewalk/application.rb', line 37

def initialize uri_map
  @mapper = Sidewalk::UriMapper.new(uri_map)
end

Instance Attribute Details

#mapperObject (readonly)

The UriMapper class this application is using.

This is constructed from the uri_map Hash argument to #initialize.



21
22
23
# File 'lib/sidewalk/application.rb', line 21

def mapper
  @mapper
end

Class Method Details

.local_rootObject

The path on the server where the application code is.

This should be the path containing config.ru. This will be something like /var/www, or /home/fred/public_html.



27
28
29
# File 'lib/sidewalk/application.rb', line 27

def self.local_root
  @local_root ||= Dir.pwd
end

Instance Method Details

#call(env) ⇒ Object

Per-request Rack entry point.

This is called for every request. It’s responsible for:

  • Normalizing the environment parameter

  • Finding what should respond to the request (via UriMapper)

  • Actually responding

  • Error handling - see #handle_error

Parameters:

  • env (Hash)

    is an environment Hash, defined in the Rack specification.



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/sidewalk/application.rb', line 51

def call env
  logger = ::Logger.new(env['rack.error'])

  path_info = env['PATH_INFO']
  if path_info.start_with? '/'
    path_info[0,1] = ''
  end

  match = @mapper.map path_info
  if match
    env['sidewalk.urimatch'] = match
    # Normalize reponders to Procs
    if match.controller.is_a? Class
      responder = lambda do |request, logger|
        match.controller.new(request, logger).call
      end
    else
      responder = match.controller
    end
  else
    responder = lambda { |*args| raise NotFoundError.new }
  end
  request = Sidewalk::Request.new(env)

  # Try and call - but it can throw special exceptions that we
  # want to map into HTTP status codes - for example, NotFoundError
  # is a 404
  begin
    responder.call(
      request,
      logger
    )
  rescue Exception => e
    response = respond_to_error(e, request, logger)
    raise if response.nil? || response.empty?
    response
  end
end

#respond_to_error(error, request, logger) ⇒ Object

Give a response for a given error.

If you want custom error pages, you will want to subclass Sidewalk::Application, reimplementing this method. At a minimum, you will probably want to include support for:

This implementation has hard-coded responses in the format defined in the Rack specification.

Examples:

An implementation that uses Controller subclasses:

def respond_to_error(error, request, logger)
  case error
  when Redirect
    MyRedirectController.new(error, request, logger).call
  when HttpError
    # ...
  else
    super(error, request, logger)
  end
end

Parameters:

  • error (Exception)

    is the error that was raised

  • request (Request)

    gives information on the request that led to the error.

  • logger (Logger)

    is something implementing a similiar API to Ruby’s standard Logger class.

Returns:

  • A Rack response Array - i.e.: [status, headers, body_parts] - see the specification for details.

  • nil to indicate the error isn’t handled - it will get escalated to Rack and probably lead to a 500.



124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
# File 'lib/sidewalk/application.rb', line 124

def respond_to_error(error, request, logger)
  case error
  when Redirect
    [
      error.status(request),
      {
        'Content-Type' => 'text/plain',
        'Location' => error.url,
      },
      ["#{error.status(request)} #{error.description(request)}"]
    ]
  when HttpError
    [
      error.status(request),
      {'Content-Type' => 'text/plain'},
      ["#{error.status(request)} #{error.description(request)}"]
    ]
  else
    nil
  end
end