mirror of
https://github.com/puma/puma.git
synced 2022-11-09 13:48:40 -05:00
A much better written CGIWrapper that actually processes the given header params correctly.
git-svn-id: svn+ssh://rubyforge.org/var/svn/mongrel/trunk@43 19e92222-5c0b-0410-8929-a290d50e31e9
This commit is contained in:
parent
f5262f2b6d
commit
00fa46db1b
1 changed files with 73 additions and 14 deletions
|
@ -597,29 +597,58 @@ module Mongrel
|
||||||
# to get existing CGI based systems working. It should handle everything, but please
|
# 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
|
# 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.
|
# testers to help work out the various corner cases.
|
||||||
|
|
||||||
class CGIWrapper < ::CGI
|
class CGIWrapper < ::CGI
|
||||||
public :env_table
|
public :env_table
|
||||||
attr_reader :options
|
attr_reader :options
|
||||||
|
|
||||||
|
# these are stripped out of any keys passed to CGIWrapper.header function
|
||||||
|
REMOVED_KEYS = [ "nph","status","server","connection","type",
|
||||||
|
"charset","length","language","expires"]
|
||||||
|
|
||||||
def initialize(request, response, *args)
|
def initialize(request, response, *args)
|
||||||
@request = request
|
@request = request
|
||||||
@response = response
|
@response = response
|
||||||
@args = *args
|
@args = *args
|
||||||
@input = StringIO.new(request.body)
|
@input = StringIO.new(request.body)
|
||||||
@options = {}
|
@head = {}
|
||||||
|
@out_called = false
|
||||||
super(*args)
|
super(*args)
|
||||||
end
|
end
|
||||||
|
|
||||||
# The header is typically called to send back the header. In our case we
|
# The header is typically called to send back the header. In our case we
|
||||||
# collect it into a hash for later usage. Options passed to this function
|
# collect it into a hash for later usage.
|
||||||
# are capitalized properly (unlike CGI), sanitized and then just stored.
|
#
|
||||||
|
# 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.
|
||||||
|
#
|
||||||
def header(options = "text/html")
|
def header(options = "text/html")
|
||||||
if options.class == Hash
|
|
||||||
# passing in a header so need to keep the status around and other options
|
# if they pass in a string then just write the Content-Type
|
||||||
@options = @options.merge(options)
|
if options.class == String
|
||||||
|
@head['Content-Type'] = options
|
||||||
else
|
else
|
||||||
@options["Content-Type"] = options
|
# 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
|
end
|
||||||
|
|
||||||
# doing this fakes out the cgi library to think the headers are empty
|
# doing this fakes out the cgi library to think the headers are empty
|
||||||
|
@ -627,14 +656,44 @@ module Mongrel
|
||||||
""
|
""
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# 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.
|
||||||
|
def send_cookies(to)
|
||||||
|
# convert the cookies based on the myriad of possible ways to set a cookie
|
||||||
|
if @head['cookie']
|
||||||
|
cookie = @head['cookie']
|
||||||
|
case cookie
|
||||||
|
when Array
|
||||||
|
cookie.each {|c| to['Set-Cookie'] = c.to_s }
|
||||||
|
when Hash
|
||||||
|
cookie.each_value {|c| to['Set-Cookie'] = c.to_s}
|
||||||
|
else
|
||||||
|
to['Set-Cookie'] = options['cookie'].to_s
|
||||||
|
end
|
||||||
|
|
||||||
|
@head.delete('cookie')
|
||||||
|
|
||||||
|
# @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
|
||||||
|
end
|
||||||
|
|
||||||
# The dumb thing is people can call header or this or both and in any order.
|
# 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.
|
# 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
|
# Status is taken from the various options and converted to what Mongrel needs
|
||||||
# via the CGIWrapper.status function.
|
# via the CGIWrapper.status function.
|
||||||
def out(options = "text/html")
|
def out(options = "text/html")
|
||||||
|
return if @out_called # don't do this more than once
|
||||||
|
|
||||||
header(options)
|
header(options)
|
||||||
|
|
||||||
@response.start status do |head, out|
|
@response.start status do |head, out|
|
||||||
@options.each {|k,v| head[k.capitalize] = v}
|
send_cookies(head)
|
||||||
|
|
||||||
|
@head.each {|k,v| head[k] = v}
|
||||||
out.write(yield || "")
|
out.write(yield || "")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -644,7 +703,7 @@ module Mongrel
|
||||||
# message in the status we have to do a bit of parsing.
|
# message in the status we have to do a bit of parsing.
|
||||||
def status
|
def status
|
||||||
if not @status
|
if not @status
|
||||||
@status = @options["Status"] || @options["status"]
|
@status = @head["Status"] || @head["status"]
|
||||||
|
|
||||||
if @status
|
if @status
|
||||||
@status[0 ... @status.index(' ')] || "200"
|
@status[0 ... @status.index(' ')] || "200"
|
||||||
|
|
Loading…
Reference in a new issue