An HTTP response.
Creates a new HTTP response object
# File webrick/httpresponse.rb, line 39
def initialize(config)
@config = config
@buffer_size = config[:OutputBufferSize]
@logger = config[:Logger]
@header = Hash.new
@status = HTTPStatus::RC_OK
@reason_phrase = nil
@http_version = HTTPVersion::convert(@config[:HTTPVersion])
@body = ''
@keep_alive = true
@cookies = []
@request_method = nil
@request_uri = nil
@request_http_version = @http_version # temporary
@chunked = false
@filename = nil
@sent_size = 0
end
Retrieves the response header field
# File webrick/httpresponse.rb, line 76
def [](field)
@header[field.downcase]
end
Sets the response header field to value
# File webrick/httpresponse.rb, line 83
def []=(field, value)
@header[field.downcase] = value.to_s
end
Enables chunked transfer encoding.
# File webrick/httpresponse.rb, line 134
def chunked=(val)
@chunked = val ? true : false
end
Will this response body be returned using chunked transfer-encoding?
# File webrick/httpresponse.rb, line 127
def chunked?
@chunked
end
The content-length header
# File webrick/httpresponse.rb, line 90
def content_length
if len = self['content-length']
return Integer(len)
end
end
Sets the content-length header to len
# File webrick/httpresponse.rb, line 99
def content_length=(len)
self['content-length'] = len.to_s
end
The content-type header
# File webrick/httpresponse.rb, line 106
def content_type
self['content-type']
end
Sets the content-type header to type
# File webrick/httpresponse.rb, line 113
def content_type=(type)
self['content-type'] = type
end
Iterates over each header in the resopnse
# File webrick/httpresponse.rb, line 120
def each
@header.each{|field, value| yield(field, value) }
end
Will this response’s connection be kept alive?
# File webrick/httpresponse.rb, line 141
def keep_alive?
@keep_alive
end
Sends the body on socket
# File webrick/httpresponse.rb, line 246
def send_body(socket)
case @body
when IO then send_body_io(socket)
else send_body_string(socket)
end
end
Sends the headers on socket
# File webrick/httpresponse.rb, line 228
def send_header(socket)
if @http_version.major > 0
data = status_line()
@header.each{|key, value|
tmp = key.gsub(/\bwww|^te$|\b\w/){ $&.upcase }
data << "#{tmp}: #{value}" << CRLF
}
@cookies.each{|cookie|
data << "Set-Cookie: " << cookie.to_s << CRLF
}
data << CRLF
_write_data(socket, data)
end
end
Sends the response on socket
# File webrick/httpresponse.rb, line 148
def send_response(socket)
begin
setup_header()
send_header(socket)
send_body(socket)
rescue Errno::EPIPE, Errno::ECONNRESET, Errno::ENOTCONN => ex
@logger.debug(ex)
@keep_alive = false
rescue Exception => ex
@logger.error(ex)
@keep_alive = false
end
end
Creates an error page for exception ex with an optional
backtrace
# File webrick/httpresponse.rb, line 275
def set_error(ex, backtrace=false)
case ex
when HTTPStatus::Status
@keep_alive = false if HTTPStatus::error?(ex.code)
self.status = ex.code
else
@keep_alive = false
self.status = HTTPStatus::RC_INTERNAL_SERVER_ERROR
end
@header['content-type'] = "text/html; charset=ISO-8859-1"
if respond_to?(:create_error_page)
create_error_page()
return
end
if @request_uri
host, port = @request_uri.host, @request_uri.port
else
host, port = @config[:ServerName], @config[:Port]
end
@body = ''
@body << "<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
<HTML>
<HEAD><TITLE>#{HTMLUtils::escape(@reason_phrase)}</TITLE></HEAD>
<BODY>
<H1>#{HTMLUtils::escape(@reason_phrase)}</H1>
#{HTMLUtils::escape(ex.message)}
<HR>
"
if backtrace && $DEBUG
@body << "backtrace of `#{HTMLUtils::escape(ex.class.to_s)}' "
@body << "#{HTMLUtils::escape(ex.message)}"
@body << "<PRE>"
ex.backtrace.each{|line| @body << "\t#{line}\n"}
@body << "</PRE><HR>"
end
@body << " <ADDRESS>
#{HTMLUtils::escape(@config[:ServerSoftware])} at
#{host}:#{port}
</ADDRESS>
</BODY>
</HTML>
"
end
Redirects to url with a WEBrick::HTTPStatus::Redirect
status.
Example:
res.set_redirect WEBrick::HTTPStatus::TemporaryRedirect
# File webrick/httpresponse.rb, line 266
def set_redirect(status, url)
@body = "<HTML><A HREF=\"#{url.to_s}\">#{url.to_s}</A>.</HTML>\n"
@header['location'] = url.to_s
raise status
end
Sets up the headers for sending
# File webrick/httpresponse.rb, line 165
def setup_header()
@reason_phrase ||= HTTPStatus::reason_phrase(@status)
@header['server'] ||= @config[:ServerSoftware]
@header['date'] ||= Time.now.httpdate
# HTTP/0.9 features
if @request_http_version < "1.0"
@http_version = HTTPVersion.new("0.9")
@keep_alive = false
end
# HTTP/1.0 features
if @request_http_version < "1.1"
if chunked?
@chunked = false
ver = @request_http_version.to_s
msg = "chunked is set for an HTTP/#{ver} request. (ignored)"
@logger.warn(msg)
end
end
# Determine the message length (RFC2616 -- 4.4 Message Length)
if @status == 304 || @status == 204 || HTTPStatus::info?(@status)
@header.delete('content-length')
@body = ""
elsif chunked?
@header["transfer-encoding"] = "chunked"
@header.delete('content-length')
elsif %r{^multipart/byteranges} =~ @header['content-type']
@header.delete('content-length')
elsif @header['content-length'].nil?
unless @body.is_a?(IO)
@header['content-length'] = @body ? @body.bytesize : 0
end
end
# Keep-Alive connection.
if @header['connection'] == "close"
@keep_alive = false
elsif keep_alive?
if chunked? || @header['content-length']
@header['connection'] = "Keep-Alive"
else
msg = "Could not determine content-length of response body. Set content-length of the response or set Response#chunked = true"
@logger.warn(msg)
@header['connection'] = "close"
@keep_alive = false
end
else
@header['connection'] = "close"
end
# Location is a single absoluteURI.
if location = @header['location']
if @request_uri
@header['location'] = @request_uri.merge(location)
end
end
end
Commenting is here to help enhance the documentation. For example, sample code, or clarification of the documentation.
If you have questions about Ruby or the documentation, please post to one of the Ruby mailing lists. You will get better, faster, help that way.
If you wish to post a correction of the docs, please do so, but also file bug report so that it can be corrected for the next release. Thank you.