Class: Web::Connection
- Includes:
- Test::Unit::Assertions
- Defined in:
- lib/web/testing.rb,
lib/web/validate.rb,
lib/web/connection.rb,
lib/web/traceoutput.rb
Direct Known Subclasses
Defined Under Namespace
Classes: BufferSet, CallbackBuffer, CaseInsensitiveHash, CookieHash
Constant Summary collapse
- MULTIPLE_KEY =
/\[\]\z/- HTTP_STATUS =
{"200" => "OK", "206" => "Partial Content", "300" => "Multiple Choices", "301" => "Moved Permanently", "302" => "Found", "304" => "Not Modified", "400" => "Bad Request", "401" => "Authorization Required", "403" => "Forbidden", "404" => "Not Found", "405" => "Method Not Allowed", "406" => "Not Acceptable", "411" => "Length Required", "412" => "Precondition Failed", "500" => "Internal Server Error", "501" => "Method Not Implemented", "502" => "Bad Gateway", "506" => "Variant Also Negotiates" }
- ENV_KEYS =
[ :path_info, :document_root, :script_name ]
- EOL =
"\r\n"
Instance Attribute Summary collapse
-
#application_loaded ⇒ Object
Returns the value of attribute application_loaded.
-
#cgd ⇒ Object
readonly
Returns the value of attribute cgd.
-
#content ⇒ Object
readonly
Returns the value of attribute content.
-
#cookie ⇒ Object
Returns the value of attribute cookie.
-
#env ⇒ Object
readonly
Returns the value of attribute env.
-
#get ⇒ Object
readonly
Returns the value of attribute get.
-
#local ⇒ Object
readonly
Returns the value of attribute local.
-
#options ⇒ Object
readonly
Returns the value of attribute options.
-
#output ⇒ Object
readonly
Returns the value of attribute output.
-
#post ⇒ Object
readonly
Returns the value of attribute post.
-
#raw_post_data ⇒ Object
readonly
Returns the value of attribute raw_post_data.
-
#request ⇒ Object
readonly
Returns the value of attribute request.
-
#ruleset ⇒ Object
Returns the value of attribute ruleset.
-
#run_caller ⇒ Object
Returns the value of attribute run_caller.
-
#templates ⇒ Object
Returns the value of attribute templates.
Class Method Summary collapse
- .create(options = {}) ⇒ Object
-
.downcase_env(env_in) ⇒ Object
returns a hash with downcased keys of the env_in variable.
-
.normalize(params) ⇒ Object
normalizes a params hash.
-
.parse_query_string(query) ⇒ Object
Parse a query_string into parameters.
-
.server_sniff ⇒ Object
returns one of these values: :cgi, :fastcgi, :mod_ruby, :webrick.
- .trace_output_template ⇒ Object
Instance Method Summary collapse
-
#[](key) ⇒ Object
access parameters.
-
#[]=(key, value) ⇒ Object
set param at the given key.
-
#add_header(name, value) ⇒ Object
There’s a bit of special casing in here, for the follow reasons: * some headers should only be sent once.
- #apply_options(options = {}) ⇒ Object
-
#assert_content(expected, message = "") ⇒ Object
for testing: raises Test::Unit exception if content is not set to the provided string.
-
#assert_cookie(name, values, message = "") ⇒ Object
Throws Test::Unit::AssertionFailedException if cookie values are not present.
-
#assert_form_includes(formname, vars) ⇒ Object
assert output content contains a form that includes the given hash of values.
-
#assert_header(name, values, message = "") ⇒ Object
Raises Test::Unit::AssertionFailedError if the header has not been set to the provided value(s).
-
#assert_local_includes(expected) ⇒ Object
Check that these values were included in the output.
-
#assert_template_not_used(expected, message = "") ⇒ Object
Check that a particluar template was not used.
-
#assert_template_used(expected, message = "") ⇒ Object
Check that a particluar template was used.
- #assert_vars_equals ⇒ Object
- #call_progress_hook(full, read) ⇒ Object
- #charset ⇒ Object
- #charset=(new_charset) ⇒ Object
-
#clear ⇒ Object
Reset output buffer.
-
#close ⇒ Object
TODO: at_close handlers flushes the output and, if applicable, saves the session.
- #closed? ⇒ Boolean
-
#content_type ⇒ Object
the default content-type is “text/html”.
- #content_type=(new_content_type) ⇒ Object
-
#cookies_sent ⇒ Object
returns a hash of all the cookie n/v pairs that have been set on the cgi.
- #encoding ⇒ Object
- #encoding=(new_encoding) ⇒ Object
-
#flush ⇒ Object
send header to the client, and flush any buffered output.
-
#full_content_type ⇒ Object
The content type header is a combination of the content_type and the charset.
-
#get_content ⇒ Object
returns the body content of the response (sans headers).
-
#get_cookie(key) ⇒ Object
returns an array of cookie values that have been set.
-
#get_form(name) ⇒ Object
:nodoc:.
-
#get_form_fields(name) ⇒ Object
:nodoc:.
-
#get_form_value(formname, name) ⇒ Object
:nodoc:.
-
#get_formreader ⇒ Object
:nodoc:.
-
#get_header(name) ⇒ Object
returns an array of header values set with the given name.
- #header ⇒ Object
- #header_sent? ⇒ Boolean
-
#initialize(options = {}) ⇒ Connection
constructor
A new instance of Connection.
-
#key?(key) ⇒ Boolean
test whether a param was submitted.
-
#keys ⇒ Object
list the submitted params.
- #location ⇒ Object
-
#location=(location) ⇒ Object
see set redirect.
- #merge_get_and_post ⇒ Object
-
#mod_ruby_query_string ⇒ Object
this method solely exists b/c of difficulties setting MOD_RUBY dynamically.
- #multipart? ⇒ Boolean
-
#nph? ⇒ Boolean
Aside from when :nph is set in the options, scripts running in IIS always use nph mode.
- #ob_get_flush ⇒ Object
- #ob_start(&callback) ⇒ Object (also: #filter)
-
#parse_multipart ⇒ Object
parse multipart/form-data.
-
#parse_request ⇒ Object
It will set @cookie, @get, @post, and @request.
- #progress_hook ⇒ Object
- #read_multipart(boundary, content_length) ⇒ Object
-
#report_error(error) ⇒ Object
—————————— implementation details, aka refactoring targets below ——————————.
- #report_error2stderr(err) ⇒ Object
-
#send_file(filename) ⇒ Object
This method will replace the contents of the output buffer by reading from the given filename.
-
#send_header ⇒ Object
Send header to the client.
- #send_header_implementation ⇒ Object
- #session ⇒ Object
-
#set_cookie(name, value, options = {}) ⇒ Object
Cookies require a name and a value.
- #set_full_content_type(new_content, new_charset) ⇒ Object
-
#set_redirect(new_location) ⇒ Object
Sets the status and the location appropriately.
- #setup_variables ⇒ Object
-
#single_param(key) ⇒ Object
If request[0] is a Web::Upload, returns that value.
- #split_content_type(target = full_content_type) ⇒ Object
-
#split_params ⇒ Object
:nodoc:.
-
#status ⇒ Object
the default status is 200.
- #status=(new_status) ⇒ Object
- #trace_output ⇒ Object
- #unbuffered? ⇒ Boolean
Methods included from Test::Unit::Assertions
Constructor Details
#initialize(options = {}) ⇒ Connection
Returns a new instance of Connection.
87 88 89 90 91 |
# File 'lib/web/connection.rb', line 87 def initialize( ={} ) ( ) parse_request setup_variables end |
Instance Attribute Details
#application_loaded ⇒ Object
Returns the value of attribute application_loaded.
176 177 178 |
# File 'lib/web/connection.rb', line 176 def application_loaded @application_loaded end |
#cgd ⇒ Object (readonly)
Returns the value of attribute cgd.
175 176 177 |
# File 'lib/web/connection.rb', line 175 def cgd @cgd end |
#content ⇒ Object (readonly)
Returns the value of attribute content.
175 176 177 |
# File 'lib/web/connection.rb', line 175 def content @content end |
#cookie ⇒ Object
Returns the value of attribute cookie.
175 176 177 |
# File 'lib/web/connection.rb', line 175 def end |
#env ⇒ Object (readonly)
Returns the value of attribute env.
175 176 177 |
# File 'lib/web/connection.rb', line 175 def env @env end |
#get ⇒ Object (readonly)
Returns the value of attribute get.
175 176 177 |
# File 'lib/web/connection.rb', line 175 def get @get end |
#local ⇒ Object (readonly)
Returns the value of attribute local.
175 176 177 |
# File 'lib/web/connection.rb', line 175 def local @local end |
#options ⇒ Object (readonly)
Returns the value of attribute options.
175 176 177 |
# File 'lib/web/connection.rb', line 175 def end |
#output ⇒ Object (readonly)
Returns the value of attribute output.
175 176 177 |
# File 'lib/web/connection.rb', line 175 def output @output end |
#post ⇒ Object (readonly)
Returns the value of attribute post.
175 176 177 |
# File 'lib/web/connection.rb', line 175 def post @post end |
#raw_post_data ⇒ Object (readonly)
Returns the value of attribute raw_post_data.
175 176 177 |
# File 'lib/web/connection.rb', line 175 def raw_post_data @raw_post_data end |
#request ⇒ Object (readonly)
Returns the value of attribute request.
175 176 177 |
# File 'lib/web/connection.rb', line 175 def request @request end |
#ruleset ⇒ Object
Returns the value of attribute ruleset.
19 20 21 |
# File 'lib/web/validate.rb', line 19 def ruleset @ruleset end |
#run_caller ⇒ Object
Returns the value of attribute run_caller.
176 177 178 |
# File 'lib/web/connection.rb', line 176 def run_caller @run_caller end |
#templates ⇒ Object
Returns the value of attribute templates.
176 177 178 |
# File 'lib/web/connection.rb', line 176 def templates @templates end |
Class Method Details
.create(options = {}) ⇒ Object
770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 |
# File 'lib/web/connection.rb', line 770 def Connection::create(={}) if ([:connection]) [:connection] else case Connection::server_sniff when :fcgi require 'web/sapi/fastcgi' Web::FastCGIConnection.new( ) when :mod_ruby Web::ModRubyConnection.new( ) else Connection.new() end end end |
.downcase_env(env_in) ⇒ Object
returns a hash with downcased keys of the env_in variable
860 861 862 863 864 865 866 |
# File 'lib/web/connection.rb', line 860 def Connection::downcase_env( env_in ) env = CaseInsensitiveHash.new env_in.each{ |k, v| env[k.downcase] = v } env end |
.normalize(params) ⇒ Object
normalizes a params hash
869 870 871 872 873 874 875 876 877 |
# File 'lib/web/connection.rb', line 869 def Connection::normalize( params ) params.each { |key, value| unless value.kind_of? Array params[key] = [value] end } params.default = [] params end |
.parse_query_string(query) ⇒ Object
Parse a query_string into parameters
881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 |
# File 'lib/web/connection.rb', line 881 def Connection::parse_query_string(query) query ||= "" params = Hash.new([]) query.split(/[&;]/n).each do |pairs| key, value = pairs.split('=',2).collect{|v| Web::unescape(v) } if params.has_key?(key) params[key].push(value) else params[key] = [value] end end params end |
.server_sniff ⇒ Object
returns one of these values: :cgi, :fastcgi, :mod_ruby, :webrick
795 796 797 798 799 800 801 802 803 804 805 806 |
# File 'lib/web/connection.rb', line 795 def Connection::server_sniff if( Object.const_defined?( "Apache" ) \ && Apache.const_defined?( "Request" ) \ && $stdin.kind_of?( Apache::Request ) ) :mod_ruby elsif ( Object.const_defined?( "FCGI" ) \ && ! FCGI.is_cgi? ) :fcgi else :cgi end end |
.trace_output_template ⇒ Object
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
# File 'lib/web/traceoutput.rb', line 46 def Connection.trace_output_template template = "<div>\n<h1>Request Details</h1><br>\n<table cellspacing=\"0\" cellpadding=\"0\" border=\"1\" style=\"width:100%;border-collapse:collapse;\">\n<tr>\n <th class=\"alt\" align=\"Left\" colspan=2><h3><b>Request Parameters</b></h3></th></tr>\n <narf:foreach from=parameters item=parameter>\n<tr><th width=150>{$parameter.key}</th><td>{$parameter.value}</td></tr>\n </narf:foreach>\n</table>\n<br>\n<table cellspacing=\"0\" cellpadding=\"0\" border=\"1\" style=\"width:100%;border-collapse:collapse;\">\n <tr><th class=\"alt\" align=\"Left\" colspan=2><h3><b>Cookies</b></h3></th></tr>\n <narf:foreach from=cookies item=cookie>\n<tr><th width=150>{$cookie.key}</th><td>{$cookie.value}</td></tr>\n </narf:foreach>\n</table>\n<br>\n<table cellspacing=\"0\" cellpadding=\"0\" border=\"1\" style=\"width:100%;border-collapse:collapse;\">\n <tr><th class=\"alt\" align=\"Left\" colspan=2><h3><b>Session</b></h3></th></tr>\n <narf:foreach from=session item=sessionitem>\n<tr><th width=150>{$sessionitem.key}</th><td>{$sessionitem.value}</td></tr>\n </table>\n</div>\n" end |
Instance Method Details
#[](key) ⇒ Object
access parameters. If the key is array-style, aka param[], return the array. Otherwise, return the joined string.
204 205 206 207 208 209 210 |
# File 'lib/web/connection.rb', line 204 def [] (key) if (MULTIPLE_KEY =~ key) self.request[key] else single_param(key) end end |
#[]=(key, value) ⇒ Object
set param at the given key. This is useful to change state in your app without asking the browser to redirect
214 215 216 217 218 219 |
# File 'lib/web/connection.rb', line 214 def []= (key, value) unless value.kind_of? Array value = [value] end request[key] = value end |
#add_header(name, value) ⇒ Object
There’s a bit of special casing in here, for the follow reasons:
-
some headers should only be sent once. If you add Content-Encoding, Location, or Status, it will overwrite the old headers instead of adding a second header
-
content-type is a strange header. It is a combination of the content-type and charset attributes. setting content-type will cause the content-type attribute to be set; setting charset will cause the charset attribute to be set.
I don’t know if this is the correct behavior. Should this method assume that the content-type set here is the full content type, and try to split the header into it’s two parts?
-
If the headers have been sent, this will throw a Web::Error
481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 |
# File 'lib/web/connection.rb', line 481 def add_header(name, value ) unless header_sent? if (/content-encoding/i =~ name ) header['Content-Encoding'] = [value] elsif( /location/i =~ name ) header['Location'] = [value] elsif( /status/i =~ name ) if /^\d*$/ =~ value.to_s self.status = value else header['Status'] = [value] end elsif(/content-type/i =~ name) header['Content-Type'] = [value] elsif(/charset/i =~ name) self.charset = value else header[name] ||= [] header[name].push value end else raise Web::Error.new( "Can't add_header after header have been sent to client" ) end end |
#apply_options(options = {}) ⇒ Object
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 120 121 122 123 124 125 126 |
# File 'lib/web/connection.rb', line 93 def ( = {} ) @closed = false @header_sent = false @templates = [ ] = [:buffered] = true unless .has_key? :buffered @raw_post_data = [:raw_post_data] || $stdin @output = [:out] || $stdout = [:cookie] @request = [:request] # start error handler if (.has_key? :error_handler) if ( [:error_handler] ) @error_handler = [:error_handler] end end # end error handler # start env @env ||= ENV @env = Connection::downcase_env(@env) if [:env] && [:env].kind_of?(Hash) && ![:env].keys.empty? @env = Connection::downcase_env( @env.merge( [:env] ) ) end Web::Connection::ENV_KEYS.each { |symbol| env[symbol.to_s.downcase] = [symbol] if [symbol] } # end env end |
#assert_content(expected, message = "") ⇒ Object
for testing: raises Test::Unit exception if content is not set to the provided string.
42 43 44 |
# File 'lib/web/testing.rb', line 42 def assert_content expected, ="" assert_equal( expected, get_content, ); end |
#assert_cookie(name, values, message = "") ⇒ Object
Throws Test::Unit::AssertionFailedException if cookie values are not present.
82 83 84 |
# File 'lib/web/testing.rb', line 82 def ( name, values, ="" ) assert_equal( [ values ].flatten, [ [name] ].flatten, ) end |
#assert_form_includes(formname, vars) ⇒ Object
assert output content contains a form that includes the given hash of values. See Web::Testing
70 71 72 |
# File 'lib/web/testing.rb', line 70 def assert_form_includes formname, vars assert_includes vars, get_form_fields(formname) end |
#assert_header(name, values, message = "") ⇒ Object
Raises Test::Unit::AssertionFailedError if the header has not been set to the provided value(s)
76 77 78 |
# File 'lib/web/testing.rb', line 76 def assert_header( name, values, ="" ) assert_equal( [values].flatten, get_header(name), ) end |
#assert_local_includes(expected) ⇒ Object
Check that these values were included in the output
108 109 110 |
# File 'lib/web/testing.rb', line 108 def assert_local_includes expected assert_includes expected, @local end |
#assert_template_not_used(expected, message = "") ⇒ Object
Check that a particluar template was not used
98 99 100 101 102 103 104 105 |
# File 'lib/web/testing.rb', line 98 def assert_template_not_used expected, ="" _wrap_assertion { if (@templates.kind_of?(Array) && @templates.include?(expected) ) msg = "template:<#{expected}> not supposed to be used in:<#{@templates.inspect}>" flunk(msg) end } end |
#assert_template_used(expected, message = "") ⇒ Object
Check that a particluar template was used
87 88 89 90 91 92 93 94 95 |
# File 'lib/web/testing.rb', line 87 def assert_template_used expected, ="" _wrap_assertion { flunk("No template used") if @templates == nil unless @templates.include? expected msg = "expected template:<#{expected}> but not one of:<#{@templates.inspect}>" flunk(msg) end } end |
#assert_vars_equals ⇒ Object
112 113 114 |
# File 'lib/web/testing.rb', line 112 def assert_vars_equals raise Exception.new("Not yet implemented") end |
#call_progress_hook(full, read) ⇒ Object
923 924 925 926 927 928 |
# File 'lib/web/connection.rb', line 923 def call_progress_hook(full, read) if (progress_hook) progress_hook.call( full, read ) end end |
#charset ⇒ Object
637 638 639 |
# File 'lib/web/connection.rb', line 637 def charset split_content_type[1] end |
#charset=(new_charset) ⇒ Object
641 642 643 |
# File 'lib/web/connection.rb', line 641 def charset= new_charset set_full_content_type( content_type, new_charset ) end |
#clear ⇒ Object
Reset output buffer. Fails if headers have been sent.
293 294 295 296 297 298 299 300 301 302 |
# File 'lib/web/connection.rb', line 293 def clear() if header_sent? raise( Exception.new( "Can't call Web::clear()" ) ) else unless unbuffered? @buffer = BufferSet.new @content = StringIO.new end end end |
#close ⇒ Object
TODO: at_close handlers flushes the output and, if applicable, saves the session
267 268 269 270 271 272 |
# File 'lib/web/connection.rb', line 267 def close flush @session ||= nil @session.save if (@session.respond_to? :save) @closed = true end |
#closed? ⇒ Boolean
274 275 276 |
# File 'lib/web/connection.rb', line 274 def closed? @closed end |
#content_type ⇒ Object
the default content-type is “text/html”
625 626 627 |
# File 'lib/web/connection.rb', line 625 def content_type split_content_type[0] end |
#content_type=(new_content_type) ⇒ Object
629 630 631 632 633 634 635 |
# File 'lib/web/connection.rb', line 629 def content_type= new_content_type content1, charset1 = split_content_type content2, charset2 = split_content_type( new_content_type ) set_full_content_type( content2 || content1, charset2 || charset1 ) end |
#cookies_sent ⇒ Object
returns a hash of all the cookie n/v pairs that have been set on the cgi
700 701 702 703 704 705 706 707 708 |
# File 'lib/web/connection.rb', line 700 def = {} get_header("Set-Cookie").each do || /\A(.*?)=([^;]*)/ =~ [$1] ||= [ ] [$1].push $2 end end |
#encoding ⇒ Object
602 603 604 |
# File 'lib/web/connection.rb', line 602 def encoding get_header( "Content-Encoding" ).first end |
#encoding=(new_encoding) ⇒ Object
606 607 608 |
# File 'lib/web/connection.rb', line 606 def encoding=( new_encoding ) add_header( "Content-Encoding", new_encoding ) end |
#flush ⇒ Object
send header to the client, and flush any buffered output
250 251 252 253 254 255 256 257 258 259 260 261 262 263 |
# File 'lib/web/connection.rb', line 250 def flush unless unbuffered? begin content = ob_flush send_header @output << content rescue Exception => e # protect against errors in output buffers @buffer = BufferSet.new Web::report_error(e) self.flush end end end |
#full_content_type ⇒ Object
The content type header is a combination of the content_type and the charset. This method returns that combination.
616 617 618 |
# File 'lib/web/connection.rb', line 616 def full_content_type get_header( "Content-Type" ).first end |
#get_content ⇒ Object
returns the body content of the response (sans headers).
325 326 327 328 |
# File 'lib/web/connection.rb', line 325 def get_content #flush_buffers # (do I need to flush the buffers?) @content.string end |
#get_cookie(key) ⇒ Object
returns an array of cookie values that have been set. path / expires / etc. info is currently not returned, should be added in?
690 691 692 693 694 695 696 |
# File 'lib/web/connection.rb', line 690 def key #get_header("Set-Cookie").collect{ |cookie| # /\A(#{ key })=([^;]*)/ =~ cookie # $2 #}.compact self.[key] end |
#get_form(name) ⇒ Object
:nodoc:
50 51 52 |
# File 'lib/web/testing.rb', line 50 def get_form( name ) #:nodoc: get_formreader[name] end |
#get_form_fields(name) ⇒ Object
:nodoc:
54 55 56 |
# File 'lib/web/testing.rb', line 54 def get_form_fields(name) #:nodoc: get_formreader.get_fields(name) end |
#get_form_value(formname, name) ⇒ Object
:nodoc:
58 59 60 61 62 63 64 65 66 |
# File 'lib/web/testing.rb', line 58 def get_form_value formname, name #:nodoc: form = get_form_fields(formname) if form == nil raise Web::Error.new("Form '#{formname}' does not exist") end value = form[name] value end |
#get_formreader ⇒ Object
:nodoc:
46 47 48 |
# File 'lib/web/testing.rb', line 46 def get_formreader #:nodoc: return @form_fields_cache ||= FormReader.new( get_content ) end |
#get_header(name) ⇒ Object
returns an array of header values set with the given name.
507 508 509 510 511 512 513 |
# File 'lib/web/connection.rb', line 507 def get_header name header.keys.find_all { |key| key.downcase == name.downcase }.collect{ |key| header[key].dup }.flatten end |
#header ⇒ Object
552 553 554 555 556 |
# File 'lib/web/connection.rb', line 552 def header @header ||= {"Content-Type" => ["text/html"], "Status" => ["200 OK"] } @header end |
#header_sent? ⇒ Boolean
548 549 550 |
# File 'lib/web/connection.rb', line 548 def header_sent? @header_sent end |
#key?(key) ⇒ Boolean
test whether a param was submitted
241 242 243 |
# File 'lib/web/connection.rb', line 241 def key? (key) request.has_key? key end |
#keys ⇒ Object
list the submitted params
236 237 238 |
# File 'lib/web/connection.rb', line 236 def keys request.keys end |
#location ⇒ Object
587 588 589 |
# File 'lib/web/connection.rb', line 587 def location get_header( "Location" ).first end |
#location=(location) ⇒ Object
see set redirect
592 593 594 |
# File 'lib/web/connection.rb', line 592 def location= location add_header( "Location", location ) end |
#merge_get_and_post ⇒ Object
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 |
# File 'lib/web/connection.rb', line 152 def merge_get_and_post var_order = [ :post, :get, :cookie ] if env["request_method"] == "POST" var_order = [ :get, :post, :cookie ] end @request = Hash.new( [ ] ) var_order.each do |namespace| variables = self.send( namespace ) if variables variables.each do |k,v| @request[k] = [ ] v.each do |e| @request[k].push(e.dup) if e end end end end @request end |
#mod_ruby_query_string ⇒ Object
this method solely exists b/c of difficulties setting MOD_RUBY dynamically. so this method exists so I can test the effect separately from the (currently untestable) cause
900 901 902 |
# File 'lib/web/connection.rb', line 900 def mod_ruby_query_string #:nodoc: Apache::request.args end |
#multipart? ⇒ Boolean
904 905 906 907 |
# File 'lib/web/connection.rb', line 904 def multipart? ("POST" == env['request_method']) && (/multipart\/form-data/.match(env['content_type'])) end |
#nph? ⇒ Boolean
Aside from when :nph is set in the options, scripts running in IIS always use nph mode. This code will probably be affected as cgi is re-organized to support multiple backends.
713 714 715 |
# File 'lib/web/connection.rb', line 713 def nph? @cgd.nph? end |
#ob_get_flush ⇒ Object
335 336 337 338 339 |
# File 'lib/web/connection.rb', line 335 def ob_get_flush result = @buffer.last.get_contents ob_flush result end |
#ob_start(&callback) ⇒ Object Also known as: filter
330 331 332 |
# File 'lib/web/connection.rb', line 330 def ob_start( &callback ) @buffer.ob_start(&callback) end |
#parse_multipart ⇒ Object
parse multipart/form-data
910 911 912 913 914 |
# File 'lib/web/connection.rb', line 910 def parse_multipart %r|\Amultipart/form-data.*boundary=\"?([^\";,]+)\"?|n.match(env['content_type']) boundary = $1.dup read_multipart(boundary, Integer(env['content_length'])) end |
#parse_request ⇒ Object
It will set @cookie, @get, @post, and @request
810 811 812 813 814 815 816 817 818 819 820 821 |
# File 'lib/web/connection.rb', line 810 def parse_request ||= CookieHash.new( env['http_cookie'] || env['cookie'] ) @get ||= Connection::parse_query_string(env["query_string"]) @post ||= if (multipart?) parse_multipart else raw_post_data.binmode query_string = raw_post_data.read(Integer(env['content_length'])) || '' @raw_post_data = StringIO.new(query_string) Connection::parse_query_string( query_string ) end end |
#progress_hook ⇒ Object
920 921 922 |
# File 'lib/web/connection.rb', line 920 def progress_hook Web::config::multipart_progress_hook end |
#read_multipart(boundary, content_length) ⇒ Object
930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 |
# File 'lib/web/connection.rb', line 930 def read_multipart(boundary, content_length) require 'tempfile' params = Hash.new([]) boundary = "--" + boundary buf = "" cached_raw_post_data = Tempfile.new("Web") bufsize = 10 * 1024 # start multipart/form-data raw_post_data.binmode boundary_size = boundary.size + EOL.size content_length -= boundary_size status = raw_post_data.read(boundary_size) if nil == status raise EOFError, "no content body" end cached_raw_post_data << status # ok... so what the hell does this do? # I promise never to denigrate the accomplishments # of my predecessors again :-) # ~ pat full_content_length = content_length until -1 == content_length call_progress_hook( full_content_length, full_content_length - content_length ) head = nil body = Tempfile.new("Web") body.binmode # until we have: # * a header # * and a buffer that has a boundary # so far, make sense to me. until head and /#{boundary}(?:#{EOL}|--)/n.match(buf) # if we have a header.... if head # !??!??!?!?! trim_size = (EOL + boundary + EOL).size if trim_size < buf.size body.write buf[0 ... (buf.size - trim_size)] buf[0 ... (buf.size - trim_size)] = "" end # If we have a double space (the smell of a header...) elsif /#{EOL}#{EOL}/n.match(buf) # extract the header, and erase it from the buffer buf = buf.sub(/\A((?:.|\n)*?#{EOL})#{EOL}/n) do head = $1.dup "" end next end # read a chunk from the raw_post_data c = if bufsize < content_length raw_post_data.read(bufsize) or '' else raw_post_data.read(content_length) or '' end # add it to the raw_post_data, reduce our countdown cached_raw_post_data << c buf.concat c ### debugging for making multipart_asserts work ~ pat #$defout.puts [bufsize, content_length, c.size].inspect, raw_post_data.read(bufsize).inspect content_length -= c.size end /Content-Disposition:.* filename="?([^\";]*)"?/ni.match(head) filename = ($1 or "").dup if /Mac/ni.match(env['http_user_agent']) and /Mozilla/ni.match(env['http_user_agent']) and (not /MSIE/ni.match(env['http_user_agent'])) filename = Web::unescape(filename) end /Content-Type: (.*)/ni.match(head) content_type = ($1 or "").strip # is this the part that is eating too much? #buf = buf.sub(/\A(.*?)(?:#{EOL})?#{boundary}(#{EOL}|--)/mn) do buf = buf.sub(/\A((?:.|\n)*?)(?:[\r\n]{1,2})?#{boundary}([\r\n]{1,2}|--)/n) do body.print $1 if "--" == $2 content_length = -1 end "" end body.rewind if (content_type.empty?) upload = body.read else upload = Web::Upload.new( body, content_type, filename ) end /Content-Disposition:.* name="?([^\";]*)"?/ni.match(head) name = $1.dup body.rewind if params.has_key?(name) params[name].push(upload) else params[name] = [upload] end end call_progress_hook( full_content_length, full_content_length - content_length - 1) @raw_post_data = cached_raw_post_data params end |
#report_error(error) ⇒ Object
implementation details, aka refactoring targets below
729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 |
# File 'lib/web/connection.rb', line 729 def report_error( error ) self.status = 500 unless self.header_sent? self.content_type = "text/html" Web::config::describe( :error_style => "Controls error reporting. One of three values: :development, :production, or :custom" ) Web::config[:error_style] ||= :development case Web::config::error_style when :development Web::( error.class.to_s, error.rbw_html + error.rbw_backtrace_html ) self.report_error2stderr( error ) when :production Web::( error.class.to_s, error.rbw_html ) self.report_error2stderr( error ) when :custom Web::config::error_handler.call( error ) else raise error end end |
#report_error2stderr(err) ⇒ Object
761 762 763 764 765 766 |
# File 'lib/web/connection.rb', line 761 def report_error2stderr( err ) unless Web::env['server_software'] =~ /Microsoft-IIS/ $stderr.binmode $stderr.puts err.rbw_to_s end end |
#send_file(filename) ⇒ Object
This method will replace the contents of the output buffer by reading from the given filename. If the content-type has not already been upset, it will try and guess an appropriate mime-type from the extension of the file.
310 311 312 313 314 315 316 317 |
# File 'lib/web/connection.rb', line 310 def send_file( filename ) clear() write( File.open( filename, 'rb' ) { |f| f.read } ) if self.content_type == "text/html" self.content_type = Web::Mime::get_mimetype(filename) end Web::close() end |
#send_header ⇒ Object
Send header to the client. No more header values can be sent after this method is called!
517 518 519 520 521 522 523 524 |
# File 'lib/web/connection.rb', line 517 def send_header unless header_sent? unless [:noheader] send_header_implementation end @header_sent = true end end |
#send_header_implementation ⇒ Object
526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 |
# File 'lib/web/connection.rb', line 526 def send_header_implementation if [:nph] || /IIS/.match(env["server_software"]) output << "#{ env['server_protocol'] || 'HTTP/1.0' }: " output << "#{ header['Status'] }\r\n" output << "Date: #{ Web::rfc1123_date(Time.now) }\r\n" header.delete("Status") unless header.has_key? "Server" header["Server"] = [ env["server_software"] || "" ] end end header.sort.each { |name, value| value.each { |v| output << "#{ name }: #{ v }\r\n" } } output << "\r\n" end |
#session ⇒ Object
178 179 180 181 182 183 184 185 186 |
# File 'lib/web/connection.rb', line 178 def session # start session @session ||= if (.has_key? :session) [:session] else Session.new( self, ) end # end session end |
#set_cookie(name, value, options = {}) ⇒ Object
Cookies require a name and a value. You can also use these optional keyword arguments:
- :path => <i>string<i>
-
path (need better description)
- :domain => string
-
domain (need better description)
- :expires => date
-
date this cookie should expire
- :secure => true || false
-
whether this cookie should be tagged as secure.
652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 |
# File 'lib/web/connection.rb', line 652 def ( name, value, ={} ) #self.cookie[name] = [ ] unless self.cookie.has_key? name #self.cookie[name].push value value = Array(value).collect{ |field| Web::escape(field) }.join("&") = "#{ name }=#{ value }" path = if ([:path]) [:path] else %r|^(.*/)|.match(env["script_name"]) ($1 or "") end += "; path=#{ path }" if ([:domain]) += "; domain=#{ options[:domain] }" end if ([:expires]) += "; expires=#{ Web::rfc1123_date( options[:expires] ) }" end if ([:secure]) += "; secure" end add_header( "Set-Cookie", ) end |
#set_full_content_type(new_content, new_charset) ⇒ Object
620 621 622 |
# File 'lib/web/connection.rb', line 620 def set_full_content_type( new_content, new_charset ) add_header( "Content-type", [ new_content, new_charset ].compact.join('; charset=') ) end |
#set_redirect(new_location) ⇒ Object
Sets the status and the location appropriately.
597 598 599 600 |
# File 'lib/web/connection.rb', line 597 def set_redirect( new_location ) self.status = "302" self.location = new_location end |
#setup_variables ⇒ Object
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 |
# File 'lib/web/connection.rb', line 128 def setup_variables @local = {} @application_loaded = false = Connection::normalize() @post = Connection::normalize(@post) @get = Connection::normalize(@get) @request = Connection::normalize(@request || merge_get_and_post ) raw_post_data.rewind # start output buffer @content = StringIO.new if (unbuffered?) @buffer = @output else @buffer = BufferSet.new end @buffer.binmode if @buffer.respond_to? :binmode # end output buffer end |
#single_param(key) ⇒ Object
223 224 225 226 227 228 229 |
# File 'lib/web/connection.rb', line 223 def single_param(key) if (request[key].first.kind_of? Web::Upload) request[key].first else request[key].join( "," ) end end |
#split_content_type(target = full_content_type) ⇒ Object
610 611 612 |
# File 'lib/web/connection.rb', line 610 def split_content_type( target = full_content_type ) target.split( Regexp.new('; charset=') ) end |
#split_params ⇒ Object
:nodoc:
231 232 233 |
# File 'lib/web/connection.rb', line 231 def split_params #:nodoc: Web::Testing::MultiHashTree.new(request).fields end |
#status ⇒ Object
the default status is 200
559 560 561 562 |
# File 'lib/web/connection.rb', line 559 def status get_header( "Status" ).first =~ /^(\d+)( .*)?$/ $1 end |
#status=(new_status) ⇒ Object
583 584 585 |
# File 'lib/web/connection.rb', line 583 def status= new_status add_header( "Status", "#{ new_status } #{ HTTP_STATUS[new_status.to_s] }" ) end |
#trace_output ⇒ Object
188 189 190 191 192 193 194 195 196 197 |
# File 'lib/web/connection.rb', line 188 def trace_output templater = Narflates.new(CGI.trace_output_template,{}) templater.parse(self,{ "parameters" => request.collect { |key,value| { "key" => key, "value" => value } }, "cookie" => .collect { |key,value| { "key" => key, "value" => value } }, "session" => session.collect { |key,value| { "key" => key, "value" => value } } }) flush end |
#unbuffered? ⇒ Boolean
319 320 321 |
# File 'lib/web/connection.rb', line 319 def unbuffered? ! [:buffered] end |