Class: Arrow::Transaction
- Inherits:
-
Object
- Object
- Object
- Arrow::Transaction
- Extends:
- Forwardable
- Includes:
- Constants
- Defined in:
- lib/arrow/transaction.rb
Overview
The Arrow::Transaction class, a derivative of Arrow::Object. Instances of this class encapsulate a transaction within a web application implemented using the Arrow application framework.
Authors
Michael Granger
Please see the file LICENSE in the top-level directory for licensing details.
Constant Summary
- FORM_CONTENT_TYPES =
Regex to match the mimetypes that browsers use for sending form data
%r{application/x-www-form-urlencoded|multipart/form-data}i
- HTML_DOC =
A minimal HTML document for #status_doc
"<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n<html>\n<head><title>%d %s</title></head>\n<body><h1>%s</h1><p>%s</p></body>\n</html>\n".gsub(/^\t/, '')
- STATUS_NAME =
Names for redirect statuses for #status_doc
{ 300 => "Multiple Choices", 301 => "Moved Permanently", 302 => "Found", 303 => "See Other", 304 => "Not Modified", 305 => "Use Proxy", 307 => "Temporary Redirect", }
- DelegatedMethods =
Apache::Request.instance_methods(false) - [ "inspect", "to_s" ]
Constants included from Constants
HTML_MIMETYPE, RUBY_MARSHALLED_MIMETYPE, RUBY_OBJECT_MIMETYPE, XHTML_MIMETYPE, YAML_DOMAIN
Instance Attribute Summary
-
- (Object) applet_path
The applet portion of the path_info.
-
- (Object) broker
readonly
The Arrow::Broker that is responsible for delegating the Transaction to one or more Arrow::Applet objects.
-
- (Object) config
readonly
The Arrow::Config object for the Arrow application that created this transaction.
-
- (Object) cookies
readonly
The Arrow::CookieSet that contains cookies to be added to the response.
-
- (Object) data
readonly
User-data hash.
-
- (Object) handler_status
The handler status code to return to Apache.
-
- (Object) request
readonly
The Apache::Request that initiated this transaction.
-
- (Object) request_cookies
readonly
The Hash of Arrow::Cookies parsed from the request.
-
- (Object) serial
readonly
The transaction’s unique id in the context of the system.
-
- (Object) vargs
The argument validator (a FormValidator object).
Instance Method Summary
-
- (Object) accepted_types
Return the contents of the ‘Accept’ header as an Array of Arrow::AcceptParam objects.
-
- (Boolean) accepts?(content_type)
(also: #accept?)
Returns boolean true/false if the requestor can handle the given content_type.
-
- (Boolean) accepts_html?
Returns true if the request’s content-negotiation headers indicate that it can accept either ‘text/html’ or ‘application/xhtml+xml’.
-
- (Object) add_cookie_headers
Add a ‘Set-Cookie’ header to the response for each cookie that currently exists the transaction’s cookieset.
-
- (Object) app_root
(also: #approot)
Return the portion of the request’s URI that serves as the base URI for the application.
-
- (Object) app_root_url
(also: #approot_url)
Returns a fully-qualified URI String to the current applet using the request object’s server name and port.
-
- (Object) applet
(also: #applet_uri)
Return an absolute uri that refers back to the applet the transaction is being run in.
-
- (Object) applet_url
Returns a fully-qualified URI String to the current applet using the request object’s server name and port.
-
- (Object) arrow_version
Get the verson of Arrow currently running.
-
- (Object) attachment(filename)
Set the result’s ‘Content-Disposition’ header to ‘attachment’ and set the attachment’s filename.
-
- (Boolean) browser_is_ie?
Returns true if the User-Agent header indicates that the remote browser is Internet Explorer.
-
- (Object) construct_url(uri)
Overridden from Apache::Request to take Apache mod_proxy headers into account.
-
- (Boolean) explicitly_accepts?(content_type)
(also: #explicitly_accept?)
Returns boolean true/false if the requestor can handle the given content_type, not including mime wildcards.
-
- (Object) for_ie_users
Execute a block if the User-Agent header indicates that the remote browser is Internet Explorer.
-
- (Boolean) form_request?
Return true if there are HTML form parameters in the request, either in the query string with a GET request, or in the body of a POST with a mimetype of either ‘application/x-www-form-urlencoded’ or ‘multipart/form-data’.
-
- (Transaction) initialize(request, config, broker)
constructor
Create a new Arrow::Transaction object with the specified request (an Apache::Request object), config (an Arrow::Config object), broker object (an Arrow::Broker), and session (Arrow::Session) objects.
-
- (Object) inspect
Returns a human-readable String representation of the transaction, suitable for debugging.
-
- (Boolean) is_ajax_request?
Return true if the request is from XMLHttpRequest (as indicated by the ‘X-Requested-With’ header from Scriptaculous or jQuery).
-
- (Boolean) is_declined?
Returns true if the transaction’s server status will cause the request to be declined (i.e., not handled by Arrow).
-
- (Boolean) is_success?
Returns true if the transactions response status is 2xx.
-
- (Object) normalized_accept_string
Return a normalized list of acceptable types, sorted by q-value and specificity.
-
- (Object) not_modified
Set the necessary header fields in the response to cause a NOT_MODIFIED response to be sent.
-
- (Object) parsed_uri
Return a URI object that is parsed from the request’s URI.
-
- (Object) path
Returns the path operated on by the Arrow::Broker when delegating the transaction.
-
- (Object) proxied_host
If the request came from a reverse proxy (i.e., the X-Forwarded-Host or X-Forwarded-Server headers are present), return the hostname that the proxy is forwarding for.
-
- (Object) redirect(uri, status_code = Apache::HTTP_MOVED_TEMPORARILY)
Set the necessary fields in the request to cause the response to be a redirect to the given url with the specified status_code (302 by default).
-
- (Object) referer
Get the request’s referer, if any.
-
- (Object) referring_action
If the referer was another applet under the same Arrow instance, return the name of the action that preceded the current one.
-
- (Object) referring_applet
If the referer was another applet under the same Arrow instance, return the uri to it.
-
- (Object) refresh(seconds, url = nil)
Set the necessary header to make the displayed page refresh to the specified url in the given number of seconds.
-
- (Object) remote_ip
Fetch the client’s IP, either from proxy headers or the connection’s IP.
-
- (Object) request_content_type
Return the Content-type header given in the request’s headers, if any.
-
- (Boolean) root_dispatcher?
Returns true if the dispatcher is mounted on the root URI (“/”).
-
- (Object) session(config = {})
The session associated with the receiver (an Arrow::Session object).
-
- (Boolean) session?
Returns true if a session has been created for the receiver.
-
- (Object) status_doc(status_code, uri = nil)
Return a minimal HTML doc for representing a given status_code.
Methods inherited from Object
deprecate_class_method, deprecate_method, inherited
Methods included from Loggable
Constructor Details
- (Transaction) initialize(request, config, broker)
Create a new Arrow::Transaction object with the specified request (an Apache::Request object), config (an Arrow::Config object), broker object (an Arrow::Broker), and session (Arrow::Session) objects.
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
# File 'lib/arrow/transaction.rb', line 77 def initialize( request, config, broker ) @request = request @config = config @broker = broker @handler_status = Apache::OK @serial = make_transaction_serial( request ) # Stuff that may be filled in later @session = nil # Lazily-instantiated @applet_path = nil # Added by the broker @vargs = nil # Filled in by the applet @data = {} = ( request ) = Arrow::CookieSet.new() @accepted_types = nil # Check for a "RubyOption root_dispatcher true" if @request..key?('root_dispatcher') && @request.['root_dispatcher'].match( /^(true|yes|1)$/i ) self.log.debug "Dispatching from root path" @root_dispatcher = true else self.log.debug "Dispatching from sub-path" @root_dispatcher = false end @request.sync_header = true super() end |
Instance Attribute Details
- (Object) applet_path
The applet portion of the path_info
132 133 134 |
# File 'lib/arrow/transaction.rb', line 132 def applet_path @applet_path end |
- (Object) broker (readonly)
The Arrow::Broker that is responsible for delegating the Transaction to one or more Arrow::Applet objects.
126 127 128 |
# File 'lib/arrow/transaction.rb', line 126 def broker @broker end |
- (Object) config (readonly)
The Arrow::Config object for the Arrow application that created this transaction.
122 123 124 |
# File 'lib/arrow/transaction.rb', line 122 def config @config end |
- (Object) cookies (readonly)
The Arrow::CookieSet that contains cookies to be added to the response
144 145 146 |
# File 'lib/arrow/transaction.rb', line 144 def end |
- (Object) data (readonly)
User-data hash. Can be used to pass data between applets in a chain.
138 139 140 |
# File 'lib/arrow/transaction.rb', line 138 def data @data end |
- (Object) handler_status
The handler status code to return to Apache
147 148 149 |
# File 'lib/arrow/transaction.rb', line 147 def handler_status @handler_status end |
- (Object) request (readonly)
The Apache::Request that initiated this transaction
118 119 120 |
# File 'lib/arrow/transaction.rb', line 118 def request @request end |
- (Object) request_cookies (readonly)
The Hash of Arrow::Cookies parsed from the request
141 142 143 |
# File 'lib/arrow/transaction.rb', line 141 def end |
- (Object) serial (readonly)
The transaction’s unique id in the context of the system.
135 136 137 |
# File 'lib/arrow/transaction.rb', line 135 def serial @serial end |
- (Object) vargs
The argument validator (a FormValidator object)
129 130 131 |
# File 'lib/arrow/transaction.rb', line 129 def vargs @vargs end |
Instance Method Details
- (Object) accepted_types
Return the contents of the ‘Accept’ header as an Array of Arrow::AcceptParam objects.
400 401 402 403 |
# File 'lib/arrow/transaction.rb', line 400 def accepted_types @accepted_types ||= parse_accept_header( self.headers_in['Accept'] ) return @accepted_types end |
- (Boolean) accepts?(content_type) Also known as: accept?
Returns boolean true/false if the requestor can handle the given content_type.
408 409 410 |
# File 'lib/arrow/transaction.rb', line 408 def accepts?( content_type ) return self.accepted_types.find {|type| type =~ content_type } ? true : false end |
- (Boolean) accepts_html?
Returns true if the request’s content-negotiation headers indicate that it can accept either ‘text/html’ or ‘application/xhtml+xml’
425 426 427 |
# File 'lib/arrow/transaction.rb', line 425 def accepts_html? return self.accepts?( XHTML_MIMETYPE ) || self.accepts?( HTML_MIMETYPE ) end |
- (Object) add_cookie_headers
Add a ‘Set-Cookie’ header to the response for each cookie that currently exists the transaction’s cookieset.
312 313 314 315 316 317 318 319 320 321 322 323 324 |
# File 'lib/arrow/transaction.rb', line 312 def self..each do || if self.is_success? self.log.debug "Adding 'Set-Cookie' header: %p (%p)" % [, .to_s] self.headers_out['Set-Cookie'] = .to_s else self.log.debug "Adding 'Set-Cookie' to the error headers: %p (%p)" % [, .to_s] self.err_headers_out['Set-Cookie'] = .to_s end end end |
- (Object) app_root Also known as: approot
Return the portion of the request’s URI that serves as the base URI for the application. All self-referential URLs created by the application should include this.
235 236 237 238 |
# File 'lib/arrow/transaction.rb', line 235 def app_root return "" if self.root_dispatcher? return @request.script_name end |
- (Object) app_root_url Also known as: approot_url
Returns a fully-qualified URI String to the current applet using the request object’s server name and port.
244 245 246 |
# File 'lib/arrow/transaction.rb', line 244 def app_root_url return construct_url( self.app_root ) end |
- (Object) applet Also known as: applet_uri
Return an absolute uri that refers back to the applet the transaction is being run in
252 253 254 |
# File 'lib/arrow/transaction.rb', line 252 def applet return [ self.app_root, self.applet_path ].join("/").gsub( %r{//+}, '/' ) end |
- (Object) applet_url
Returns a fully-qualified URI String to the current applet using the request object’s server name and port.
261 262 263 |
# File 'lib/arrow/transaction.rb', line 261 def applet_url return construct_url( self.applet ) end |
- (Object) arrow_version
Get the verson of Arrow currently running.
541 542 543 |
# File 'lib/arrow/transaction.rb', line 541 def arrow_version return Arrow::VERSION end |
- (Object) attachment=(filename)
Set the result’s ‘Content-Disposition’ header to ‘attachment’ and set the attachment’s filename.
371 372 373 374 375 376 377 378 379 380 |
# File 'lib/arrow/transaction.rb', line 371 def ( filename ) # IE flubs attachments of any mimetype it handles directly. if self.browser_is_ie? self.content_type = 'application/octet-stream' end val = %q{attachment; filename="%s"} % [ filename ] self.headers_out['Content-Disposition'] = val end |
- (Boolean) browser_is_ie?
Returns true if the User-Agent header indicates that the remote browser is Internet Explorer. Useful for making the inevitable IE workarounds.
443 444 445 446 |
# File 'lib/arrow/transaction.rb', line 443 def browser_is_ie? agent = self.headers_in['user-agent'] || '' return agent =~ /MSIE/ ? true : false end |
- (Object) construct_url(uri)
Overridden from Apache::Request to take Apache mod_proxy headers into account. If the ‘X-Forwarded-Host’ or ‘X-Forwarded-Server’ headers exist in the request, the hostname specified is used instead of the canonical host.
331 332 333 334 335 336 337 338 339 340 341 342 343 |
# File 'lib/arrow/transaction.rb', line 331 def construct_url( uri ) url = @request.construct_url( uri ) # If the request came through a proxy, rewrite the url's host to match # the hostname the proxy is forwarding for. if (( host = self.proxied_host )) uriobj = URI.parse( url ) uriobj.host = host url = uriobj.to_s end return url end |
- (Boolean) explicitly_accepts?(content_type) Also known as: explicitly_accept?
Returns boolean true/false if the requestor can handle the given content_type, not including mime wildcards.
416 417 418 419 |
# File 'lib/arrow/transaction.rb', line 416 def explicitly_accepts?( content_type ) self.accepted_types.reject { |param| param.subtype.nil? }. find {|type| type =~ content_type } ? true : false end |
- (Object) for_ie_users
Execute a block if the User-Agent header indicates that the remote browser is Internet Explorer. Useful for making the inevitable IE workarounds.
452 453 454 |
# File 'lib/arrow/transaction.rb', line 452 def for_ie_users yield if self.browser_is_ie? end |
- (Boolean) form_request?
Return true if there are HTML form parameters in the request, either in the query string with a GET request, or in the body of a POST with a mimetype of either ‘application/x-www-form-urlencoded’ or ‘multipart/form-data’.
469 470 471 472 473 474 475 476 477 478 479 480 481 |
# File 'lib/arrow/transaction.rb', line 469 def form_request? case self.request_method when 'GET', 'HEAD', 'DELETE', 'PUT' return (!self.parsed_uri.query.nil? || self.request_content_type =~ FORM_CONTENT_TYPES) ? true : false when 'POST' return self.request_content_type =~ FORM_CONTENT_TYPES ? true : false else return false end end |
- (Object) inspect
Returns a human-readable String representation of the transaction, suitable for debugging.
152 153 154 155 156 157 158 159 |
# File 'lib/arrow/transaction.rb', line 152 def inspect "#<%s:0x%0x serial: %s; HTTP status: %d>" % [ self.class.name, self.object_id * 2, self.serial, self.status ] end |
- (Boolean) is_ajax_request?
Return true if the request is from XMLHttpRequest (as indicated by the ‘X-Requested-With’ header from Scriptaculous or jQuery)
459 460 461 462 463 |
# File 'lib/arrow/transaction.rb', line 459 def is_ajax_request? xrw_header = self.headers_in['x-requested-with'] return true if !xrw_header.nil? && xrw_header =~ /xmlhttprequest/i return false end |
- (Boolean) is_declined?
Returns true if the transaction’s server status will cause the request to be declined (i.e., not handled by Arrow)
183 184 185 186 187 |
# File 'lib/arrow/transaction.rb', line 183 def is_declined? self.log.debug "Checking to see if the transaction is declined (%p)" % [self.handler_status] return self.handler_status == Apache::DECLINED ? true : false end |
- (Boolean) is_success?
Returns true if the transactions response status is 2xx.
175 176 177 178 |
# File 'lib/arrow/transaction.rb', line 175 def is_success? return nil unless self.status return (self.status / 100) == 2 end |
- (Object) normalized_accept_string
Return a normalized list of acceptable types, sorted by q-value and specificity.
431 432 433 |
# File 'lib/arrow/transaction.rb', line 431 def normalized_accept_string return self.accepted_types.sort.collect {|ap| ap.to_s }.join( ', ' ) end |
- (Object) not_modified
Set the necessary header fields in the response to cause a NOT_MODIFIED response to be sent.
522 523 524 |
# File 'lib/arrow/transaction.rb', line 522 def not_modified return self.redirect( uri, Apache::HTTP_NOT_MODIFIED ) end |
- (Object) parsed_uri
Return a URI object that is parsed from the request’s URI.
384 385 386 |
# File 'lib/arrow/transaction.rb', line 384 def parsed_uri return URI.parse( self.request.unparsed_uri ) end |
- (Object) path
Returns the path operated on by the Arrow::Broker when delegating the transaction. Equal to the #uri minus the #app_root.
225 226 227 228 229 |
# File 'lib/arrow/transaction.rb', line 225 def path path = @request.uri uripat = Regexp.new( "^" + self.app_root ) return path.sub( uripat, '' ) end |
- (Object) proxied_host
If the request came from a reverse proxy (i.e., the X-Forwarded-Host or X-Forwarded-Server headers are present), return the hostname that the proxy is forwarding for. If no proxy headers are present, return nil.
350 351 352 353 |
# File 'lib/arrow/transaction.rb', line 350 def proxied_host headers = @request.headers_in return headers['x-forwarded-host'] || headers['x-forwarded-server'] end |
- (Object) redirect(uri, status_code = Apache::HTTP_MOVED_TEMPORARILY)
Set the necessary fields in the request to cause the response to be a redirect to the given url with the specified status_code (302 by default).
510 511 512 513 514 515 516 517 |
# File 'lib/arrow/transaction.rb', line 510 def redirect( uri, status_code=Apache::HTTP_MOVED_TEMPORARILY ) self.log.debug "Redirecting to %s" % uri self.headers_out[ 'Location' ] = uri.to_s self.status = status_code self.handler_status = Apache::REDIRECT return '' end |
- (Object) referer
Get the request’s referer, if any
364 365 366 |
# File 'lib/arrow/transaction.rb', line 364 def referer return self.headers_in['Referer'] end |
- (Object) referring_action
If the referer was another applet under the same Arrow instance, return the name of the action that preceded the current one. If there was no ‘Referer’ header, or the referer wasn’t an applet under the same Arrow instance, return nil.
289 290 291 292 293 294 295 296 297 298 299 300 301 302 |
# File 'lib/arrow/transaction.rb', line 289 def referring_action return nil unless self.referer uri = URI.parse( self.referer ) path = uri.path or return nil appletRe = Regexp.new( self.app_root + "/\\w+/" ) return nil unless appletRe.match( path ) subpath = path. sub( appletRe, '' ). split( %r{/} ). first return subpath end |
- (Object) referring_applet
If the referer was another applet under the same Arrow instance, return the uri to it. If there was no ‘Referer’ header, or the referer wasn’t an applet under the same Arrow instance, returns nil.
269 270 271 272 273 274 275 276 277 278 279 280 281 282 |
# File 'lib/arrow/transaction.rb', line 269 def referring_applet return nil unless self.referer uri = URI.parse( self.referer ) path = uri.path or return nil rootRe = Regexp.new( self.app_root + "/" ) return nil unless rootRe.match( path ) subpath = path. sub( rootRe, '' ). split( %r{/} ). first return subpath end |
- (Object) refresh(seconds, url = nil)
Set the necessary header to make the displayed page refresh to the specified url in the given number of seconds.
529 530 531 532 533 534 535 536 537 |
# File 'lib/arrow/transaction.rb', line 529 def refresh( seconds, url=nil ) seconds = Integer( seconds ) url ||= self.construct_url( '' ) if !URI.parse( url ).absolute? url = self.construct_url( url ) end self.headers_out['Refresh'] = "%d;%s" % [seconds, url] end |
- (Object) remote_ip
Fetch the client’s IP, either from proxy headers or the connection’s IP.
357 358 359 |
# File 'lib/arrow/transaction.rb', line 357 def remote_ip return self.headers_in['X-Forwarded-For'] || self.connection.remote_ip end |
- (Object) request_content_type
Return the Content-type header given in the request’s headers, if any
390 391 392 |
# File 'lib/arrow/transaction.rb', line 390 def request_content_type return self.headers_in['Content-type'] end |
- (Boolean) root_dispatcher?
Returns true if the dispatcher is mounted on the root URI (“/”)
218 219 220 |
# File 'lib/arrow/transaction.rb', line 218 def root_dispatcher? return @root_dispatcher end |
- (Object) session(config = {})
The session associated with the receiver (an Arrow::Session object).
169 170 171 |
# File 'lib/arrow/transaction.rb', line 169 def session( config={} ) @session ||= Arrow::Session.create( self, config ) end |
- (Boolean) session?
Returns true if a session has been created for the receiver.
163 164 165 |
# File 'lib/arrow/transaction.rb', line 163 def session? @session ? true : false end |
- (Object) status_doc(status_code, uri = nil)
Return a minimal HTML doc for representing a given status_code
489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 |
# File 'lib/arrow/transaction.rb', line 489 def status_doc( status_code, uri=nil ) body = '' if uri body = %q{<a href="%s">%s</a>} % [ uri, uri ] end #<head><title>%d %s</title></head> #<body><h1>%s</h1><p>%s</p></body> return HTML_DOC % [ status_code, STATUS_NAME[status_code], STATUS_NAME[status_code], body ] end |