CGI
The beginning of a complete wrapper around Unicorn'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 us if you see special warnings. This work is still very alpha so we need testers to help work out the various corner cases.
this maps CGI header names to HTTP header names
these are stripped out of any keys passed to CGIWrapper.header function
some of these are common strings, but this is the only module using them and the reason they're not in Unicorn::Const
Takes an a Rackable environment, plus any additional CGI.new arguments These are used internally to create a wrapper around the real CGI while maintaining Rack/Unicorn's view of the world. This this will NOT deal well with large responses that take up a lot of memory, but neither does the CGI nor the original CGIWrapper from Mongrel...
# File lib/unicorn/cgi_wrapper.rb, line 58 def initialize(rack_env, *args) @env_table = rack_env @status = nil @head = {} @headv = Hash.new { |hash,key| hash[key] = [] } @body = StringIO.new("") super(*args) end
The header is typically called to send back the header. In our case we collect it into a hash for later usage. This can be called multiple times to set different cookies.
# File lib/unicorn/cgi_wrapper.rb, line 84 def header(options = "text/html") # if they pass in a string then just write the Content-Type if String === options @head[CONTENT_TYPE] ||= options else HEADER_MAP.each_pair do |from, to| from = options.delete(from) or next @head[to] = from.to_s end @head[CONTENT_TYPE] ||= "text/html" if charset = options.delete(CHARSET) @head[CONTENT_TYPE] << "; charset=#{charset}" end # lots of ways to set cookies if cookie = options.delete(COOKIE) set_cookies = @headv[SET_COOKIE] case cookie when Array cookie.each { |c| set_cookies << c.to_s } when Hash cookie.each_value { |c| set_cookies << c.to_s } else set_cookies << cookie.to_s end end @status ||= options.delete(STATUS) # all lower-case # drop the keys we don't want anymore options.delete(NPH) options.delete(CONNECTION) # finally, set the rest of the headers as-is, allowing duplicates options.each_pair { |k,v| @headv[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. This will have no effect if called the second time if the first "outputted" anything.
# File lib/unicorn/cgi_wrapper.rb, line 130 def out(options = "text/html") header(options) @body.size == 0 or return @body << yield if block_given? end
finalizes the response in a way Rack applications would expect
# File lib/unicorn/cgi_wrapper.rb, line 68 def rack_response # @head[CONTENT_LENGTH] ||= @body.size @headv[SET_COOKIE].concat(@output_cookies) if @output_cookies @headv.each_pair do |key,value| @head[key] ||= value.join("\n") unless value.empty? end # Capitalized "Status:", with human-readable status code (e.g. "200 OK") @status ||= @head.delete(Status) [ @status || 500, @head, [ @body.string ] ] end
Generated with the Darkfish Rdoc Generator 2.