Class: ServerSide::Router
- Inherits:
-
HTTP::Request
- Object
- HTTP::Request
- ServerSide::Router
- Defined in:
- lib/serverside/routing.rb
Overview
The Router class defines a kind of connection that can route requests to 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 in 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]+))/
Constants inherited from HTTP::Request
HTTP::Request::AMPERSAND, HTTP::Request::CLOSE, HTTP::Request::CONNECTION, 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
Instance Attribute Summary
Attributes inherited from HTTP::Request
#body, #content_length, #content_type, #cookies, #headers, #method, #parameters, #path, #persistent, #query, #response_cookies, #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.
-
.define_proc(&block) ⇒ Object
Converts a proc into a method, returning the method’s name (as a symbol).
-
.has_routes? ⇒ Boolean
Returns true if routes were defined.
-
.route(rule, &block) ⇒ Object
Adds a routing rule.
-
.route_default(&block) ⇒ Object
Sets the default handler for incoming requests.
-
.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_response, #set_cookie, #stream
Methods included from StaticFiles
#serve_dir, #serve_file, #serve_static, #serve_template
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
112 113 114 115 116 |
# File 'lib/serverside/routing.rb', line 112 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.
47 48 49 50 51 52 |
# File 'lib/serverside/routing.rb', line 47 def self.compile_rules @@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.
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
# File 'lib/serverside/routing.rb', line 84 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 |
.define_proc(&block) ⇒ Object
Converts a proc into a method, returning the method’s name (as a symbol)
104 105 106 107 108 |
# File 'lib/serverside/routing.rb', line 104 def self.define_proc(&block) tag = block.proc_tag define_method(tag.to_sym, &block) unless instance_methods.include?(tag) tag.to_sym end |
.has_routes? ⇒ Boolean
Returns true if routes were defined.
26 27 28 |
# File 'lib/serverside/routing.rb', line 26 def self.has_routes? @@rules && !@@rules.empty? rescue false 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')}
38 39 40 41 42 43 |
# File 'lib/serverside/routing.rb', line 38 def self.route(rule, &block) @@rules ||= [] rule = {:path => rule} unless (Hash === rule) || (Proc === rule) @@rules.unshift [rule, block] compile_rules end |
.route_default(&block) ⇒ Object
Sets the default handler for incoming requests.
119 120 121 122 |
# File 'lib/serverside/routing.rb', line 119 def self.route_default(&block) define_method(:default_handler, &block) compile_rules 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.
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
# File 'lib/serverside/routing.rb', line 56 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 "return #{proc_tag} if #{cond}\n" end |
Instance Method Details
#unhandled ⇒ Object Also known as: default_handler
Generic responder for unhandled requests.
125 126 127 |
# File 'lib/serverside/routing.rb', line 125 def unhandled send_response(403, 'text', 'No handler found.') end |