Class: ServerSide::Router
- Inherits:
-
HTTP::Request
- Object
- HTTP::Request
- ServerSide::Router
- Defined in:
- lib/serverside/routing.rb
Overview
The Router class is a subclass of HTTP::Request that can invoke different handlers based on rules that can be specified either by lambdas or by hashes that contain variable names corresponding to patterns.
The simplest form of a routing rule specifies a path pattern:
ServerSide.route('/static') {serve_static('.'/@path)}
But you can also check for other attributes of the request:
ServerSide.route(:path => '/static', :host => '^:subdomain\.mydomain') {
serve_static(@parameters[:subdomain]/@path)
}
It also possible to pass a lambda as a rule:
ServerSide.route(lambda {@headers['Agent'] =~ /Moz/}) {serve_static('moz'/@path)}
Routing rules are evaluated backwards, so the rules should be ordered from the general to the specific.
Constant Summary collapse
- ParamRegexp =
Pattern for finding parameters inside patterns. Parameters are parts of the pattern, which the routing pre-processor turns into sub-regexp that are used to extract parameter values from the pattern.
For example, matching ‘/controller/show’ against ‘/controller/:action’ will give us @parameters #=> “show”
/(?::([a-z]+))/
- @@rules =
[]
- @@default_route =
nil
Constants inherited from HTTP::Request
HTTP::Request::AMPERSAND, HTTP::Request::CLOSE, HTTP::Request::CONNECTION, HTTP::Request::CONTENT_DESCRIPTION, HTTP::Request::CONTENT_DISPOSITION, HTTP::Request::CONTENT_DISPOSITION_REGEXP, HTTP::Request::CONTENT_LENGTH, HTTP::Request::CONTENT_TYPE, HTTP::Request::CONTENT_TYPE_REGEXP, HTTP::Request::CONTENT_TYPE_URL_ENCODED, HTTP::Request::COOKIE, HTTP::Request::COOKIE_EXPIRED_TIME, HTTP::Request::COOKIE_REGEXP, HTTP::Request::COOKIE_SPLIT, HTTP::Request::EMPTY_HASH, HTTP::Request::EMPTY_STRING, HTTP::Request::EQUAL_SIGN, HTTP::Request::FIELD_ATTRIBUTE_REGEXP, HTTP::Request::HEADER, HTTP::Request::HEADER_REGEXP, HTTP::Request::LINE_BREAK, HTTP::Request::LOCATION, HTTP::Request::MULTIPART_REGEXP, HTTP::Request::PARAMETER_REGEXP, HTTP::Request::REQUEST_REGEXP, HTTP::Request::SET_COOKIE, HTTP::Request::SLASH, HTTP::Request::STATUS_CLOSE, HTTP::Request::STATUS_PERSIST, HTTP::Request::STATUS_REDIRECT, HTTP::Request::STATUS_STREAM, HTTP::Request::VERSION_1_1
Constants included from Static
Static::DIR_LISTING, Static::DIR_LISTING_START, Static::DIR_LISTING_STOP, Static::ETAG_FORMAT, Static::FILE_NOT_FOUND, Static::MAX_AGE, Static::MAX_CACHE_FILE_SIZE, Static::RHTML, Static::TEXT_HTML, Static::TEXT_PLAIN
Constants included from HTTP::Caching
HTTP::Caching::CACHE_CONTROL, HTTP::Caching::ETAG, HTTP::Caching::ETAG_QUOTE_FORMAT, HTTP::Caching::EXPIRES, HTTP::Caching::EXPIRY_ETAG_FORMAT, HTTP::Caching::EXPIRY_ETAG_REGEXP, HTTP::Caching::IF_MODIFIED_SINCE, HTTP::Caching::IF_NONE_MATCH, HTTP::Caching::IF_NONE_MATCH_REGEXP, HTTP::Caching::LAST_MODIFIED, HTTP::Caching::NOT_MODIFIED_CLOSE, HTTP::Caching::NOT_MODIFIED_PERSIST, HTTP::Caching::NO_CACHE, HTTP::Caching::VARY, HTTP::Caching::WILDCARD
Instance Attribute Summary
Attributes inherited from HTTP::Request
#body, #content_length, #content_type, #cookies, #headers, #method, #parameters, #path, #persistent, #query, #response_cookies, #response_headers, #socket, #version
Class Method Summary collapse
-
.cache_constant(value) ⇒ Object
Converts a value into a local constant and freezes it.
-
.compile_rules ⇒ Object
Compiles all rules into a respond method that is invoked when a request is received.
-
.condition_part(key, value) ⇒ Object
Returns the condition part for the key and value specified.
-
.default_route(&block) ⇒ Object
Sets the default handler for incoming requests.
-
.define_proc(&block) ⇒ Object
Converts a proc into a method, returning the method’s name (as a symbol).
-
.route(rule, &block) ⇒ Object
Adds a routing rule.
-
.routes_defined? ⇒ Boolean
Returns true if routes were defined.
-
.rule_to_statement(rule, block) ⇒ Object
Converts a rule into an if statement.
Instance Method Summary collapse
-
#unhandled ⇒ Object
(also: #default_handler)
Generic responder for unhandled requests.
Methods inherited from HTTP::Request
#delete_cookie, #initialize, #parse, #parse_body, #parse_cookies, #parse_parameters, #process, #redirect, #send_file, #send_response, #set_cookie, #stream
Methods included from Static
#serve_dir, #serve_file, #serve_static, #serve_template
Methods included from HTTP::Caching
#disable_caching, #etag_validators, #expiry_etag, #send_not_modified_response, #valid_etag?, #valid_stamp?, #validate_cache
Constructor Details
This class inherits a constructor from ServerSide::HTTP::Request
Class Method Details
.cache_constant(value) ⇒ Object
Converts a value into a local constant and freezes it. Returns the constant’s tag name
113 114 115 116 117 |
# File 'lib/serverside/routing.rb', line 113 def self.cache_constant(value) tag = value.const_tag class_eval "#{tag} = #{value.inspect}.freeze" rescue nil tag end |
.compile_rules ⇒ Object
Compiles all rules into a respond method that is invoked when a request is received.
49 50 51 52 53 |
# File 'lib/serverside/routing.rb', line 49 def self.compile_rules code = @@rules.inject('lambda {') {|m, r| m << rule_to_statement(r[0], r[1])} code << 'default_handler}' define_method(:respond, &eval(code)) end |
.condition_part(key, value) ⇒ Object
Returns the condition part for the key and value specified. The key is the name of an instance variable and the value is a pattern to match against. If the pattern contains parameters (for example, /controller/:action,) the method creates a lambda for extracting the parameter values.
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
# File 'lib/serverside/routing.rb', line 85 def self.condition_part(key, value) p_parse, p_count = '', 0 while (String === value) && (value =~ ParamRegexp) value = value.dup p_name = $1 p_count += 1 value.sub!(ParamRegexp, '(.+)') p_parse << "@parameters[:#{p_name}] = $#{p_count}\n" end cond = "(@#{key} =~ #{cache_constant(Regexp.new(value))})" if p_count == 0 cond else tag = define_proc(&eval( "lambda {if #{cond}\n#{p_parse}true\nelse\nfalse\nend}")) "(#{tag})" end end |
.default_route(&block) ⇒ Object
Sets the default handler for incoming requests.
120 121 122 123 124 |
# File 'lib/serverside/routing.rb', line 120 def self.default_route(&block) @@default_route = block define_method(:default_handler, &block) compile_rules end |
.define_proc(&block) ⇒ Object
Converts a proc into a method, returning the method’s name (as a symbol)
105 106 107 108 109 |
# File 'lib/serverside/routing.rb', line 105 def self.define_proc(&block) tag = block.proc_tag define_method(tag.to_sym, &block) unless instance_methods.include?(tag) tag.to_sym end |
.route(rule, &block) ⇒ Object
Adds a routing rule. The normalized rule is a hash containing keys (acting as instance variable names) with patterns as values. If the rule is not a hash, it is normalized into a pattern checked against the request path. Pattern values can also be arrays, any member of which is checked as a pattern. The rule can also be a Proc or lambda which is run with the connection object’s binding. A contrived example:
ServerSide.route(lambda{path = 'mypage'}) {serve_static('mypage.html')}
41 42 43 44 45 |
# File 'lib/serverside/routing.rb', line 41 def self.route(rule, &block) rule = {:path => rule} unless (Hash === rule) || (Proc === rule) @@rules.unshift [rule, block] compile_rules end |
.routes_defined? ⇒ Boolean
Returns true if routes were defined.
29 30 31 |
# File 'lib/serverside/routing.rb', line 29 def self.routes_defined? !@@rules.empty? || @@default_route end |
.rule_to_statement(rule, block) ⇒ Object
Converts a rule into an if statement. All keys in the rule are matched against their respective values.
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
# File 'lib/serverside/routing.rb', line 57 def self.rule_to_statement(rule, block) proc_tag = define_proc(&block) if Proc === rule cond = define_proc(&rule).to_s else cond = rule.to_a.map {|kv| if Array === kv[1] '(' + kv[1].map {|v| condition_part(kv[0], v)}.join('||') + ')' else condition_part(kv[0], kv[1]) end }.join('&&') end "if #{cond} && (r = #{proc_tag}); return r; end\n" end |
Instance Method Details
#unhandled ⇒ Object Also known as: default_handler
Generic responder for unhandled requests.
127 128 129 |
# File 'lib/serverside/routing.rb', line 127 def unhandled send_response(403, 'text', 'No handler found.') end |