Module: Tap::Support::Gems::Rack
- Defined in:
- lib/tap/support/gems/rack.rb
Overview
UNDER CONSTRUCTION
Support for a Tap::Server, built on Rack.
Tap::Support::Gems::Rack is intended to extend a Tap::Env
Defined Under Namespace
Modules: Render
Constant Summary collapse
- DEFAULT_ERROR_TEMPLATE =
The default error template used by response when an error occurs.
%Q{ <html> <body> # Error handling request: <%= error.message %></br> # <%= error.backtrace.join("<br/># ") %> <code><pre> <%= cgi.to_yaml %> <%= rack.to_yaml %> </pre></code> </body> </html> }
Instance Attribute Summary collapse
-
#handler ⇒ Object
The handler for the server (ex Rack::Handler::WEBrick).
Instance Method Summary collapse
-
#call(rack_env) ⇒ Object
The Rack interface method.
-
#cgi_response(cgi_path, rack_env) ⇒ Object
Generates a [status, headers, body] response for the specified cgi.
- #env_attrs(rack_env) ⇒ Object
-
#file_response(path, rack_env) ⇒ Object
Generates a [status, headers, body] response for the specified file.
-
#render(path, attributes = {}) ⇒ Object
Builds the specified template using the rack_env and additional attributes.
-
#render_response(path, rack_env) ⇒ Object
Generates a [status, headers, body] response using the first existing template matching path (as determined by Env#search_path) and the specified rack_env.
-
#response(rack_env) ⇒ Object
Creates a [status, headers, body] response using the result of the block as the body.
-
#template(template, attributes = {}) ⇒ Object
:nodoc:.
Instance Attribute Details
#handler ⇒ Object
The handler for the server (ex Rack::Handler::WEBrick)
26 27 28 |
# File 'lib/tap/support/gems/rack.rb', line 26 def handler @handler end |
Instance Method Details
#call(rack_env) ⇒ Object
The Rack interface method. Call routesrequests (with preference) to:
-
static pages
-
cgi scripts
-
default responses
Static pages
Static pages may be served from any env in self. A static page is served if a file with the request path exists under the ‘public’ directory for any env.
Envs are searched in order, using the Env#search_path method.
CGI scripts
Like static pages, cgi scripts may be served from any env in self.
Scripts are discovered using a search of the cgi manifest. See cgi_response for more details.
Default responses
The default response is path-dependent:
path action
/, /index render the manifest.
all others render a 404 response
The manifest may be refreshed by setting a query string:
/?refresh=true
/index?refresh=true
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 117 118 119 |
# File 'lib/tap/support/gems/rack.rb', line 89 def call(rack_env) path = rack_env['PATH_INFO'] case when static_path = search_path(:public, path) {|file| File.file?(file) } # serve named static pages file_response(static_path, rack_env) when cgi_path = cgis.search(path) # serve cgis cgi_response(cgi_path, rack_env) # when task_path = search(:tasks, path) # # serve tasks # cgi_response('task', rack_env) when path == "/" || path == "/index" # serve up the homepage if rack_env["QUERY_STRING"] == "refresh=true" # reset(:cgis) do |key, path| # Support::Lazydoc[path].resolved = false # end end render_response('index.erb', rack_env) else # handle all other requests as errors render_response('404.erb', rack_env) end end |
#cgi_response(cgi_path, rack_env) ⇒ Object
Generates a [status, headers, body] response for the specified cgi. The cgi will be run with ENV set as specified in rack_env.
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 |
# File 'lib/tap/support/gems/rack.rb', line 137 def cgi_response(cgi_path, rack_env) # setup standard ios for capture current_input = $stdin current_output = $stdout cgi_input = rack_env['rack.input'] cgi_output = StringIO.new("") begin $stdin = cgi_input $stdout = cgi_output # run the cgi with_ENV(rack_env) { load(cgi_path) } # collect the headers and body from the output headers, body = cgi_output.string.split(/\r?\n\r?\n/, 2) raise "missing headers from: #{cgi_path}" if headers == nil body = "" if body == nil headers = headers.split(/\r?\n/).inject({}) do |hash, line| key, value = line.split(/:/, 2) hash[key] = value hash end # generate the response [headers.delete('Status') || 200, headers, body] rescue(Exception) # when an error occurs, return a standard cgi error with backtrace [500, {'Content-Type' => 'text/plain'}, %Q{#{$!.class}: #{$!.}\n#{$!.backtrace.join("\n")}}] ensure $stdin = current_input $stdout = current_output end end |
#env_attrs(rack_env) ⇒ Object
236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 |
# File 'lib/tap/support/gems/rack.rb', line 236 def env_attrs(rack_env) # partition and sort the env variables into # cgi and rack variables. rack, cgi = rack_env.to_a.partition do |(key, value)| key =~ /^rack/ end.collect do |part| part.sort_by do |key, value| key end.inject({}) do |hash, (key,value)| hash[key] = value hash end end {:env => self, :cgi => cgi, :rack => rack} end |
#file_response(path, rack_env) ⇒ Object
Generates a [status, headers, body] response for the specified file. Patterned after Rack::File#._call.
123 124 125 126 127 128 129 130 131 132 133 |
# File 'lib/tap/support/gems/rack.rb', line 123 def file_response(path, rack_env) response(rack_env) do |res| content = File.read(path) res.headers.merge!( "Last-Modified" => File.mtime(path).httpdate, "Content-Type" => ::Rack::File::MIME_TYPES[File.extname(path)] || "text/plain", # Rack::Mime.mime_type(File.extname(path), 'text/plain'), "Content-Length" => content.size.to_s) content end end |
#render(path, attributes = {}) ⇒ Object
Builds the specified template using the rack_env and additional attributes. The rack_env is partitioned into rack-related and cgi-related hashes (all rack_env entries where the key starts with ‘rack’ are rack-related, the others are cgi-related).
The template is built with the following standard locals:
server self
cgi the cgi-related hash
rack the rack-related hash
Plus the attributes.
229 230 231 232 233 234 |
# File 'lib/tap/support/gems/rack.rb', line 229 def render(path, attributes={}) # :nodoc: path = search_path(:template, path) {|file| File.file?(file) } raise("no such template: #{path}") if path == nil template(File.read(path) , attributes) end |
#render_response(path, rack_env) ⇒ Object
Generates a [status, headers, body] response using the first existing template matching path (as determined by Env#search_path) and the specified rack_env.
186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 |
# File 'lib/tap/support/gems/rack.rb', line 186 def render_response(path, rack_env) # partition and sort the env variables into # cgi and rack variables. rack, cgi = rack_env.to_a.partition do |(key, value)| key =~ /^rack/ end.collect do |part| part.sort_by do |key, value| key end.inject({}) do |hash, (key,value)| hash[key] = value hash end end response(rack_env) do render(path, env_attrs(rack_env)) end end |
#response(rack_env) ⇒ Object
Creates a [status, headers, body] response using the result of the block as the body. The status and headers the defaults for Rack::Response. If an error occurs, a default error message is generated using the DEFAULT_ERROR_TEMPLATE.
49 50 51 52 53 54 55 56 57 |
# File 'lib/tap/support/gems/rack.rb', line 49 def response(rack_env) ::Rack::Response.new.finish do |res| res.write begin yield(res) rescue template(DEFAULT_ERROR_TEMPLATE, env_attrs(rack_env).merge(:error => $!)) end end end |