Class: N::App::Request
- Inherits:
-
Object
- Object
- N::App::Request
- Includes:
- CGI::QueryExtension, RequestUtils
- Defined in:
- lib/n/app/request.rb
Overview
Request
Encapsulates an http protocol request. Generally clones the Apache Request passed by mod_ruby.
Todo:
-
USE libapreq!
-
Dont use env_table (arghhhh!)
-
dont use a separate path and real path
-
MEGA: unify request and request (like a socket, io stream,etc). Evan subclass IO!
Design:
-
uri: the original uri entered to the browser (INCLUDES qs)
gmosx: i included the qs and removed full_uri (always forgot to use it anyway, was very error prone)
-
translated_uri: as translated by the web server (no query string)
-
path: the path to the actual script (or object)
Example:
www.site.com/faq/?id=1 -> uri: /faq/?id=1 translated_uri: /faq/index.sx path: base/site/root/faq/index.sx query_string: id=1
-
querystring should probably include the ?
-
Encapsulate ModRuby/Apache requests
-
Based on resin3.0 excellent code:
com/caucho/server/http/HttpRequest.java
-
use as much of ruby’s default cgi/http code as possible (why reinvent the wheel?)
Constant Summary collapse
- METHOD_GET =
request methods enumeration
0
- METHOD_POST =
1
- METHOD_HEAD =
2
- EXCLUDED_PARAMETERS =
exclude those parameters for security
%w{ oid pid name }
Instance Attribute Summary collapse
-
#content_type ⇒ Object
request content type, default: text/html.
-
#error_log ⇒ Object
Keep all errors to present them in-page when in admin mode.
-
#fragment_hash ⇒ Object
keep the original handler process uri, usefull as a cache key.
-
#in ⇒ Object
the incoming headers gmosx: writer needed for inject (sub-req cloning).
-
#in_cookies ⇒ Object
the incoming cookies.
-
#level ⇒ Object
the level of the request (0 = toplevel).
-
#lm ⇒ Object
last modified cache.
-
#locale ⇒ Object
the locale hash for this request.
-
#message ⇒ Object
HTTP request message.
-
#method ⇒ Object
request method.
-
#out ⇒ Object
the outgoing headers.
-
#out_buffer ⇒ Object
the outgoing buffer.
-
#out_cookies ⇒ Object
the outgoing cookies.
-
#parameters ⇒ Object
(also: #query)
The query string is parsed to the parameters hash.
-
#parts ⇒ Object
The parts attached to this request.
-
#path ⇒ Object
the path to the actual object (script) gets overriden by sub-requests, is not needed in scripts.
-
#path_info ⇒ Object
path info (extra parameters in the uri).
-
#query_string ⇒ Object
the query string part of the uri.
-
#remote_addr ⇒ Object
the remote address for this request.
-
#session ⇒ Object
the session this request is part-of.
-
#shader ⇒ Object
the shader for this request.
-
#status ⇒ Object
HTTP request status.
-
#tag ⇒ Object
the script hash for this request.
-
#top_script ⇒ Object
The top level script for this request.
-
#translated_uri ⇒ Object
the uri as translated by the web server.
-
#uncacheable ⇒ Object
Is the request cacheable? Set this attribute to ‘true’ to avoid caching the request fragment.
-
#uri ⇒ Object
the uri for the request.
Instance Method Summary collapse
-
#[](name) ⇒ Object
Return the value of a query parameter.
-
#[]=(name, value) ⇒ Object
Set the value of a query parameter.
-
#admin? ⇒ Boolean
Is this an admin request? FIXME: no longer valid, recode.
-
#anonymous? ⇒ Boolean
Shorthand for request.session.user.anonymous?.
-
#del_cookie(name) ⇒ Object
Removes a cookie from the client by seting the expire time to the past (epoch).
- #del_tx_entity!(txparam = "txid") ⇒ Object
-
#delete(param) ⇒ Object
Use the delete name to make the request compatible with hashes.
-
#errors ⇒ Object
Shorthand.
-
#errors_to_a ⇒ Object
(also: #errors_list)
Returns the errors as an array.
-
#expires!(exp_time) ⇒ Object
Utility method to set the expires header.
- #expires? ⇒ Boolean
-
#get(key, default = nil) ⇒ Object
Same as [] but enforces a default value to! Also tries to guess the parameters type from the default value.
-
#get_cookie(cookie_name) ⇒ Object
Input: the cookie name.
- #get_tx_entity(txparam = "txid") ⇒ Object
-
#include?(param) ⇒ Boolean
Check if a parameter exists! Example: url:www.mysite.com/page.sx?admin request.include?(admin) => true.
-
#initialize ⇒ Request
constructor
A new instance of Request.
-
#internal_redirect(url) ⇒ Object
Internal redirect.
-
#is_top? ⇒ Boolean
Returns true for the top-level request, but false for any inject or forward.
- #log_error(str) ⇒ Object
-
#new_tx_entity!(entity, txparam = "txid") ⇒ Object
The tx sequence increases, the count of transactions / session is usually bounded.
-
#param?(param) ⇒ Boolean
(also: #action?)
Check if a parameter is valid.
-
#parse_cookies(cookie_string) ⇒ Object
(also: #parse_cookie_string)
this method is also usefull for probing (testing) the request class.
-
#parse_query_string ⇒ Object
——————————————————————————- Query.
-
#redirect(url = nil, force_exit = false, status = 302) ⇒ Object
302 is the redirect status!.
-
#referer ⇒ Object
(also: #referrer)
Return the referer to this resource.
-
#set_errors(errors) ⇒ Object
Set errors as a transaction entity.
-
#set_not_modified! ⇒ Object
Set the HTTP NOT_MODIFIED status code.
-
#set_status(status = 200) ⇒ Object
Set the request HTTP status and lookup the corresponding request status message.
-
#set_tx_entity!(entity, txparam = "txid") ⇒ Object
(also: #update_tx_entity!)
Set (update) an existing tx entity.
- #update(*params) ⇒ Object
-
#update_entity(entity) ⇒ Object
gmosx: hmm this is a really dangerous method, the EXCLUDED params above dont seem enough :(.
-
#user ⇒ Object
Shorthand for request.session.user.
Methods included from RequestUtils
#expand_uri, #full_uri, #get_entity, #get_entity_by_name
Constructor Details
#initialize ⇒ Request
Returns a new instance of Request.
261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 |
# File 'lib/n/app/request.rb', line 261 def initialize # set to 0 (== top level). When including fragments # the level is incremented. @level = 0 # gmosx: it would be good to defere the hash creation, # but having the hash always created saves as a LOT of # checks in client code, so we create it here. # # FIXME: WE SHOULD NOT CREATE unneeded hash objects. # # @parts = {} # request: # provide some fair initialization values. set_status(200) @content_type = "text/html; charset=iso-8859-7" @out = {} @out_cookies = {} end |
Instance Attribute Details
#content_type ⇒ Object
request content type, default: text/html
162 163 164 |
# File 'lib/n/app/request.rb', line 162 def content_type @content_type end |
#error_log ⇒ Object
Keep all errors to present them in-page when in admin mode.
224 225 226 |
# File 'lib/n/app/request.rb', line 224 def error_log @error_log end |
#fragment_hash ⇒ Object
keep the original handler process uri, usefull as a cache key. Typically updated in subrequests only. Investigate if we could use a hash here!
221 222 223 |
# File 'lib/n/app/request.rb', line 221 def fragment_hash @fragment_hash end |
#in ⇒ Object
the incoming headers gmosx: writer needed for inject (sub-req cloning)
236 237 238 |
# File 'lib/n/app/request.rb', line 236 def in @in end |
#in_cookies ⇒ Object
the incoming cookies
239 240 241 |
# File 'lib/n/app/request.rb', line 239 def @in_cookies end |
#level ⇒ Object
the level of the request (0 = toplevel)
199 200 201 |
# File 'lib/n/app/request.rb', line 199 def level @level end |
#lm ⇒ Object
last modified cache
230 231 232 |
# File 'lib/n/app/request.rb', line 230 def lm @lm end |
#locale ⇒ Object
the locale hash for this request.
210 211 212 |
# File 'lib/n/app/request.rb', line 210 def locale @locale end |
#message ⇒ Object
HTTP request message
259 260 261 |
# File 'lib/n/app/request.rb', line 259 def @message end |
#method ⇒ Object
request method
159 160 161 |
# File 'lib/n/app/request.rb', line 159 def method @method end |
#out ⇒ Object
the outgoing headers
244 245 246 |
# File 'lib/n/app/request.rb', line 244 def out @out end |
#out_buffer ⇒ Object
the outgoing buffer
250 251 252 |
# File 'lib/n/app/request.rb', line 250 def out_buffer @out_buffer end |
#out_cookies ⇒ Object
the outgoing cookies
247 248 249 |
# File 'lib/n/app/request.rb', line 247 def @out_cookies end |
#parameters ⇒ Object Also known as: query
The query string is parsed to the parameters hash.
186 187 188 |
# File 'lib/n/app/request.rb', line 186 def parameters @parameters end |
#parts ⇒ Object
The parts attached to this request. A part is typically an uploaded file. By using a separate hash instead of the parameters hash one can easily enumerate parts.
196 197 198 |
# File 'lib/n/app/request.rb', line 196 def parts @parts end |
#path ⇒ Object
the path to the actual object (script) gets overriden by sub-requests, is not needed in scripts.
175 176 177 |
# File 'lib/n/app/request.rb', line 175 def path @path end |
#path_info ⇒ Object
path info (extra parameters in the uri)
179 180 181 |
# File 'lib/n/app/request.rb', line 179 def path_info @path_info end |
#query_string ⇒ Object
the query string part of the uri
182 183 184 |
# File 'lib/n/app/request.rb', line 182 def query_string @query_string end |
#remote_addr ⇒ Object
the remote address for this request
202 203 204 |
# File 'lib/n/app/request.rb', line 202 def remote_addr @remote_addr end |
#session ⇒ Object
the session this request is part-of
190 191 192 |
# File 'lib/n/app/request.rb', line 190 def session @session end |
#shader ⇒ Object
the shader for this request.
213 214 215 |
# File 'lib/n/app/request.rb', line 213 def shader @shader end |
#status ⇒ Object
HTTP request status
256 257 258 |
# File 'lib/n/app/request.rb', line 256 def status @status end |
#tag ⇒ Object
the script hash for this request
216 217 218 |
# File 'lib/n/app/request.rb', line 216 def tag @tag end |
#top_script ⇒ Object
The top level script for this request.
227 228 229 |
# File 'lib/n/app/request.rb', line 227 def top_script @top_script end |
#translated_uri ⇒ Object
the uri as translated by the web server. For sub-requests keeps the usri of the top level request.
171 172 173 |
# File 'lib/n/app/request.rb', line 171 def translated_uri @translated_uri end |
#uncacheable ⇒ Object
Is the request cacheable? Set this attribute to ‘true’ to avoid caching the request fragment. Used to avoid caching ‘action’ requests.
207 208 209 |
# File 'lib/n/app/request.rb', line 207 def uncacheable @uncacheable end |
#uri ⇒ Object
the uri for the request. For sub-requests keeps the uri of the top level request. gmosx: the writer is needed for injects.
167 168 169 |
# File 'lib/n/app/request.rb', line 167 def uri @uri end |
Instance Method Details
#[](name) ⇒ Object
Return the value of a query parameter
340 341 342 |
# File 'lib/n/app/request.rb', line 340 def [](name) return @parameters[name] end |
#[]=(name, value) ⇒ Object
Set the value of a query parameter
FIXME:
-
handle multivalued parameters!
367 368 369 |
# File 'lib/n/app/request.rb', line 367 def []=(name, value) @parameters[name] = value end |
#admin? ⇒ Boolean
Is this an admin request? FIXME: no longer valid, recode.
384 385 386 |
# File 'lib/n/app/request.rb', line 384 def admin? return @parameters.include?("*admin") end |
#anonymous? ⇒ Boolean
Shorthand for request.session.user.anonymous?
396 397 398 |
# File 'lib/n/app/request.rb', line 396 def anonymous? return @session.user.anonymous? end |
#del_cookie(name) ⇒ Object
Removes a cookie from the client by seting the expire time to the past (epoch).
324 325 326 327 328 329 |
# File 'lib/n/app/request.rb', line 324 def (name) = N::App::Cookie.new(name, "nil") .path = "/" .expires = Time.at(0) @out_cookies[name] = end |
#del_tx_entity!(txparam = "txid") ⇒ Object
531 532 533 534 535 |
# File 'lib/n/app/request.rb', line 531 def del_tx_entity!(txparam = "txid") if txid = @parameters[txparam] @session.delete(txid) end end |
#delete(param) ⇒ Object
Use the delete name to make the request compatible with hashes. Tests is a parameter is passed to the request and removes it! Used in action handlers.
450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 |
# File 'lib/n/app/request.rb', line 450 def delete(param) oparam = param if param = @parameters.delete(param) # gmosx: remove from querystring too! NEEDED. # perhaps kinda slow but happens seldom and optimizes # another frequent case @query_string = @parameters.collect { |k, v| (v && k.is_a?(String)) ? "#{k}=#{v}" : k }.join(";") # If the parameter exist this is an action request, so # do NOT cache the fragment. @uncacheable = true end # gmosx: to avoid using param? if param.is_a?(String) and (not N::StringUtils.valid?(param)) return nil else return param end end |
#errors ⇒ Object
Shorthand
Output: nil if no errors.
411 412 413 |
# File 'lib/n/app/request.rb', line 411 def errors return del_tx_entity!("errid") end |
#errors_to_a ⇒ Object Also known as: errors_list
Returns the errors as an array.
417 418 419 420 421 422 |
# File 'lib/n/app/request.rb', line 417 def errors_to_a if errors = del_tx_entity!("errid") return errors.values end return nil end |
#expires!(exp_time) ⇒ Object
Utility method to set the expires header.
643 644 645 |
# File 'lib/n/app/request.rb', line 643 def expires!(exp_time) @out["Expires"] = N::HttpUtils.time_to_string(exp_time) end |
#expires? ⇒ Boolean
647 648 649 |
# File 'lib/n/app/request.rb', line 647 def expires? return @out["Expires"] end |
#get(key, default = nil) ⇒ Object
Same as [] but enforces a default value to! Also tries to guess the parameters type from the default value. It works like delete (ie returns nil for ‘empty’ String parameters).
349 350 351 352 353 354 355 356 357 358 359 360 |
# File 'lib/n/app/request.rb', line 349 def get(key, default=nil) val = @parameters[key] if !val or (val.is_a?(String) and (not N::StringUtils.valid?(val))) @parameters[key] = default return default elsif default.is_a?(Integer) return val.to_i else return val end end |
#get_cookie(cookie_name) ⇒ Object
Input:
the cookie name
Output:
-
the cookie value, or an array of values for multivalued cookies.
-
nil if the cookie doesnt exist.
Example:
nsid = request.get_cookie(“nsid”)
314 315 316 317 318 319 |
# File 'lib/n/app/request.rb', line 314 def () return nil unless @in_cookies = @in_cookies[] return nil unless return CGI.unescape(.value) end |
#get_tx_entity(txparam = "txid") ⇒ Object
522 523 524 525 526 527 |
# File 'lib/n/app/request.rb', line 522 def get_tx_entity(txparam = "txid") if txid = @parameters[txparam] return @session[txid] end return nil end |
#include?(param) ⇒ Boolean
Check if a parameter exists! Example: url:www.mysite.com/page.sx?admin request.include?(admin) => true
437 438 439 |
# File 'lib/n/app/request.rb', line 437 def include?(param) return @parameters.include?(param) end |
#internal_redirect(url) ⇒ Object
Internal redirect
FIXME: implement me
638 639 |
# File 'lib/n/app/request.rb', line 638 def internal_redirect(url) end |
#is_top? ⇒ Boolean
Returns true for the top-level request, but false for any inject or forward
377 378 379 |
# File 'lib/n/app/request.rb', line 377 def is_top? return 0 == @level end |
#log_error(str) ⇒ Object
542 543 544 545 546 |
# File 'lib/n/app/request.rb', line 542 def log_error(str) @error_log = [] unless @error_log @error_log << str if @error_log.size < 200 # gmosx: dod attack! $log.error str end |
#new_tx_entity!(entity, txparam = "txid") ⇒ Object
The tx sequence increases, the count of transactions / session is usually bounded.
498 499 500 501 502 503 504 505 506 507 508 |
# File 'lib/n/app/request.rb', line 498 def new_tx_entity!(entity, txparam = "txid") unless seq = @session["TXSEQ"] seq = 0 end seq += 1 @session["TXSEQ"] = seq txid = "TX#{seq}" @session[txid] = entity @parameters[txparam] = txid return txid end |
#param?(param) ⇒ Boolean Also known as: action?
Check if a parameter is valid
427 428 429 |
# File 'lib/n/app/request.rb', line 427 def param?(param) return N::StringUtils.valid?(self[param]) end |
#parse_cookies(cookie_string) ⇒ Object Also known as:
this method is also usefull for probing (testing) the request class. FIXME: optimize this (libapreq)
299 300 301 |
# File 'lib/n/app/request.rb', line 299 def () @cookies = Cookie.parse() end |
#parse_query_string ⇒ Object
Query
334 335 336 |
# File 'lib/n/app/request.rb', line 334 def parse_query_string return N::UriUtils.query_string_to_hash(@query_string) end |
#redirect(url = nil, force_exit = false, status = 302) ⇒ Object
302 is the redirect status!
Status 303:
The request to the request can be found under a different URI and SHOULD be retrieved using a GET method on that resource. This method exists primarily to allow the output of a POST-activated script to redirect the user agent to a selected resource. The new URI is not a substitute reference for the originally requested resource. The 303 request MUST NOT be cached, but the request to the second (redirected) request might be cacheable.
Note: Many pre-HTTP/1.1 user agents do not understand the 303 status. When interoperability with such clients is a concern, the 302 status code may be used instead, since most user agents react to a 302 request as described here for 303.
WARNING:
Konqueror always performs a 307 redirect ARGH!
Redesign:
Use one redirect method with an optional status parameter, that reads messages from the status constants.
Input:
-
url to redirect to
-
if force_exit == true raises a ScriptExitException
-
status (303 or 307) default = 303
605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 |
# File 'lib/n/app/request.rb', line 605 def redirect(url = nil, force_exit = false, status = 302) # FIXME: normalize the url # url = $srv_url + url if url =~ /^\//om # FIXME: check arguments # enforce a meaningfull default url ||= self["_go"] || referer() # the url should have a leading "/" # enforce it to be sure. FIXME: optimize this! url = "/#{url}".squeeze("/") unless url =~ /^http/ @out["Location"] = url # gmosx: NOT needed? see the exceprt from the spec. # @out['Cache-Control'] = "max-age=1" set_status(status) @out_buffer = "The URL has moved <a href='#{url}'>here</a>" if force_exit # Stop rendering the script immediately! # This is the default behaviour! raise N::ScriptExitException end # for unit testing return url end |
#referer ⇒ Object Also known as: referrer
Return the referer to this resource. For the initial page in the clickstream there is no referer, set “/” by default.
288 289 290 |
# File 'lib/n/app/request.rb', line 288 def referer return @in["REFERER"] || "/" end |
#set_errors(errors) ⇒ Object
Set errors as a transaction entity. Returns the txid for the errors
402 403 404 |
# File 'lib/n/app/request.rb', line 402 def set_errors(errors) new_tx_entity!(errors, "errid") unless errors.empty? end |
#set_not_modified! ⇒ Object
Set the HTTP NOT_MODIFIED status code. Usefull for HTTP Caching.
564 565 566 567 |
# File 'lib/n/app/request.rb', line 564 def set_not_modified! @status = 304 @message = N::HTTP::STATUS_STRINGS[status] end |
#set_status(status = 200) ⇒ Object
Set the request HTTP status and lookup the corresponding request status message.
556 557 558 559 |
# File 'lib/n/app/request.rb', line 556 def set_status(status = 200) @status = status @message = HTTP::STATUS_STRINGS[status] end |
#set_tx_entity!(entity, txparam = "txid") ⇒ Object Also known as: update_tx_entity!
Set (update) an existing tx entity. Does NOT increase the tx sequence.
513 514 515 516 517 |
# File 'lib/n/app/request.rb', line 513 def set_tx_entity!(entity, txparam = "txid") if txid = @parameters[txparam] @session[txid] = entity end end |
#update(*params) ⇒ Object
441 442 443 |
# File 'lib/n/app/request.rb', line 441 def update(*params) @parameters.update(*params) end |
#update_entity(entity) ⇒ Object
gmosx: hmm this is a really dangerous method, the EXCLUDED params above dont seem enough :(
477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 |
# File 'lib/n/app/request.rb', line 477 def update_entity(entity) @parameters.each { |param, val| begin # gmosx: DO NOT escape by default !!! # gmosx: We need to get non valid params if (not EXCLUDED_PARAMETERS.include?(param)) entity.send("__force_#{param}", val) end rescue NameError next end } return entity end |
#user ⇒ Object
Shorthand for request.session.user
390 391 392 |
# File 'lib/n/app/request.rb', line 390 def user return @session.user end |