Class: Thin::CGIWrapper
- Inherits:
-
CGI
- Object
- CGI
- Thin::CGIWrapper
- Defined in:
- lib/thin/cgi.rb
Overview
Class largely based on Mongrel::CGIWrapper mongrel.rubyforge.org by Zed A. Shaw <zedshaw at zedshaw dot com>
Constant Summary collapse
- REMOVED_KEYS =
these are stripped out of any keys passed to CGIWrapper.header function
[ "nph","status","server","connection","type", "charset","length","language","expires"]
Instance Attribute Summary collapse
-
#default_really_final ⇒ Object
Set this to false if you want calls to CGIWrapper.out to not actually send the response until you force it.
-
#options ⇒ Object
readonly
Returns the value of attribute options.
Instance Method Summary collapse
-
#args ⇒ Object
Used to wrap the normal args variable used inside CGI.
-
#env_table ⇒ Object
Used to wrap the normal env_table variable used inside CGI.
-
#header(options = "text/html") ⇒ Object
The header is typically called to send back the header.
-
#initialize(request, response, *args) ⇒ CGIWrapper
constructor
Takes an HttpRequest and HttpResponse object, plus any additional arguments normally passed to CGI.
-
#out(options = "text/html", really_final = @default_really_final) ⇒ Object
The dumb thing is people can call header or this or both and in any order.
-
#send_cookies(to) ⇒ Object
Takes any ‘cookie’ setting and sends it over the Mongrel header, then removes the setting from the options.
-
#status ⇒ Object
Computes the status once, but lazily so that people who call header twice don’t get penalized.
-
#stdinput ⇒ Object
Used to wrap the normal stdinput variable used inside CGI.
-
#stdoutput ⇒ Object
The stdoutput should be completely bypassed but we’ll drop a warning just in case.
Constructor Details
#initialize(request, response, *args) ⇒ CGIWrapper
Takes an HttpRequest and HttpResponse object, plus any additional arguments normally passed to CGI. These are used internally to create a wrapper around the real CGI while maintaining Mongrel’s view of the world.
20 21 22 23 24 25 26 27 28 29 |
# File 'lib/thin/cgi.rb', line 20 def initialize(request, response, *args) @request = request @response = response @args = *args @input = request.body @head = {} @out_called = false @default_really_final = true super(*args) end |
Instance Attribute Details
#default_really_final ⇒ Object
Set this to false if you want calls to CGIWrapper.out to not actually send the response until you force it.
11 12 13 |
# File 'lib/thin/cgi.rb', line 11 def default_really_final @default_really_final end |
#options ⇒ Object (readonly)
Returns the value of attribute options.
8 9 10 |
# File 'lib/thin/cgi.rb', line 8 def @options end |
Instance Method Details
#args ⇒ Object
Used to wrap the normal args variable used inside CGI.
138 139 140 |
# File 'lib/thin/cgi.rb', line 138 def args @args end |
#env_table ⇒ Object
Used to wrap the normal env_table variable used inside CGI.
143 144 145 |
# File 'lib/thin/cgi.rb', line 143 def env_table @request.params end |
#header(options = "text/html") ⇒ Object
The header is typically called to send back the header. In our case we collect it into a hash for later usage.
nph – Mostly ignored. It’ll output the date. connection – Completely ignored. Why is CGI doing this? length – Ignored since Mongrel figures this out from what you write to output.
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
# File 'lib/thin/cgi.rb', line 38 def header( = "text/html") # if they pass in a string then just write the Content-Type if .class == String @head['Content-Type'] = unless @head['Content-Type'] else # convert the given options into what Mongrel wants @head['Content-Type'] = ['type'] || "text/html" @head['Content-Type'] += "; charset=" + ['charset'] if .has_key? "charset" if ['charset'] # setup date only if they use nph @head['Date'] = CGI::rfc1123_date(Time.now) if ['nph'] # setup the server to use the default or what they set @head['Server'] = ['server'] || env_table['SERVER_SOFTWARE'] # remaining possible options they can give @head['Status'] = ['status'] if ['status'] @head['Content-Language'] = ['language'] if ['language'] @head['Expires'] = ['expires'] if ['expires'] # drop the keys we don't want anymore REMOVED_KEYS.each {|k| .delete(k) } # finally just convert the rest raw (which puts 'cookie' directly) # 'cookie' is translated later as we write the header out .each{|k,v| @head[k] = v} end # doing this fakes out the cgi library to think the headers are empty # we then do the real headers in the out function call later "" end |
#out(options = "text/html", really_final = @default_really_final) ⇒ Object
The dumb thing is people can call header or this or both and in any order. So, we just reuse header and then finalize the HttpResponse the right way. Status is taken from the various options and converted to what Mongrel needs via the CGIWrapper.status function.
We also prevent Rails from actually doing the final send by adding a second parameter “really_final”. Only Mongrel calls this after Rails is done. Since this will break other frameworks, it defaults to a different setting for rails (false) and (true) for others.
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 |
# File 'lib/thin/cgi.rb', line 105 def out( = "text/html", really_final=@default_really_final) if @out_called || !really_final # don't do it more than once or if it's not the really final call return end header() @response.start status do |head, body| (head) @head.each {|k,v| head[k] = v} body.write(yield || "") end @out_called = true end |
#send_cookies(to) ⇒ Object
Takes any ‘cookie’ setting and sends it over the Mongrel header, then removes the setting from the options. If cookie is an Array or Hash then it sends those on with .to_s, otherwise it just calls .to_s on it and hopefully your “cookie” can write itself correctly.
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 |
# File 'lib/thin/cgi.rb', line 76 def (to) # convert the cookies based on the myriad of possible ways to set a cookie if @head['cookie'] = @head['cookie'] case when Array .each {|c| to['Set-Cookie'] = c.to_s } when Hash .each_value {|c| to['Set-Cookie'] = c.to_s} else to['Set-Cookie'] = ['cookie'].to_s end @head.delete('cookie') end # @output_cookies seems to never be used, but we'll process it just in case @output_cookies.each {|c| to['Set-Cookie'] = c.to_s } if @output_cookies end |
#status ⇒ Object
Computes the status once, but lazily so that people who call header twice don’t get penalized. Because CGI insists on including the options status message in the status we have to do a bit of parsing.
126 127 128 129 130 131 132 133 134 135 |
# File 'lib/thin/cgi.rb', line 126 def status if not @status stat = @head["Status"] stat = stat.split(' ')[0] if stat @status = stat || "200" end @status end |
#stdinput ⇒ Object
Used to wrap the normal stdinput variable used inside CGI.
148 149 150 |
# File 'lib/thin/cgi.rb', line 148 def stdinput @input end |
#stdoutput ⇒ Object
The stdoutput should be completely bypassed but we’ll drop a warning just in case
153 154 155 156 |
# File 'lib/thin/cgi.rb', line 153 def stdoutput STDERR.puts "WARNING: Your program is doing something not expected. Please tell Zed that stdoutput was used and what software you are running. Thanks." @response.body end |