class Mongrel::CGIWrapper
The beginning of a complete wrapper around Mongrel's internal HTTP processing system but maintaining the original Ruby CGI module. Use this only as a crutch to get existing CGI based systems working. It should handle everything, but please notify me if you see special warnings. This work is still very alpha so I need testers to help work out the various corner cases.
The CGIWrapper.handler
attribute is normally not set and is available for frameworks that need to get back to the handler. Rails
uses this to give people access to the RailsHandler#files (DirHandler really) so they can look-up paths and do other things with the files managed there.
In Rails
you can get the real file for a request with:
path = @request.cgi.handler.files.can_serve(@request['PATH_INFO'])
Which is ugly but does the job. Feel free to write a Rails
helper for that. Refer to DirHandler#can_serve
for more information on this.
Constants
- REMOVED_KEYS
these are stripped out of any keys passed to
CGIWrapper.header
function
Attributes
Set this to false if you want calls to CGIWrapper.out
to not actually send the response until you force it.
Public Class Methods
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.
# File lib/mongrel/cgi.rb, line 42 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
Public Instance Methods
Used to wrap the normal args variable used inside CGI.
# File lib/mongrel/cgi.rb, line 160 def args @args end
Used to wrap the normal env_table
variable used inside CGI.
# File lib/mongrel/cgi.rb, line 165 def env_table @request.params end
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.
# File lib/mongrel/cgi.rb, line 60 def header(options = "text/html") # if they pass in a string then just write the Content-Type if options.class == String @head['Content-Type'] = options unless @head['Content-Type'] else # convert the given options into what Mongrel wants @head['Content-Type'] = options['type'] || "text/html" @head['Content-Type'] += "; charset=" + options['charset'] if options.has_key? "charset" if options['charset'] # setup date only if they use nph @head['Date'] = CGI::rfc1123_date(Time.now) if options['nph'] # setup the server to use the default or what they set @head['Server'] = options['server'] || env_table['SERVER_SOFTWARE'] # remaining possible options they can give @head['Status'] = options['status'] if options['status'] @head['Content-Language'] = options['language'] if options['language'] @head['Expires'] = options['expires'] if options['expires'] # drop the keys we don't want anymore REMOVED_KEYS.each {|k| options.delete(k) } # finally just convert the rest raw (which puts 'cookie' directly) # 'cookie' is translated later as we write the header out options.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
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.
# File lib/mongrel/cgi.rb, line 127 def out(options = "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(options) @response.start status do |head, body| send_cookies(head) @head.each {|k,v| head[k] = v} body.write(yield || "") end @out_called = true end
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.
# File lib/mongrel/cgi.rb, line 148 def status if not @status stat = @head["Status"] stat = stat.split(' ')[0] if stat @status = stat || "200" end @status end
Used to wrap the normal stdinput variable used inside CGI.
# File lib/mongrel/cgi.rb, line 170 def stdinput @input end
The stdoutput should be completely bypassed but we'll drop a warning just in case
# File lib/mongrel/cgi.rb, line 175 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