Class WEBrick::HTTPResponse
In: lib/webrick/httpresponse.rb
Parent: Object

Methods

Constants

BUFSIZE = 1024*4

Attributes

body  [RW] 
config  [R] 
cookies  [R] 
filename  [RW] 
header  [R] 
http_version  [R] 
keep_alive  [RW] 
reason_phrase  [RW] 
request_http_version  [RW] 
request_method  [RW] 
request_uri  [RW] 
sent_size  [R] 
status  [R] 

Public Class methods

[Source]

    # File lib/webrick/httpresponse.rb, line 31
31:     def initialize(config)
32:       @config = config
33:       @logger = config[:Logger]
34:       @header = Hash.new
35:       @status = HTTPStatus::RC_OK
36:       @reason_phrase = nil
37:       @http_version = HTTPVersion::convert(@config[:HTTPVersion])
38:       @body = ''
39:       @keep_alive = true
40:       @cookies = []
41:       @request_method = nil
42:       @request_uri = nil
43:       @request_http_version = @http_version  # temporary
44:       @chunked = false
45:       @filename = nil
46:       @sent_size = 0
47:     end

Public Instance methods

[Source]

    # File lib/webrick/httpresponse.rb, line 58
58:     def [](field)
59:       @header[field.downcase]
60:     end

[Source]

    # File lib/webrick/httpresponse.rb, line 62
62:     def []=(field, value)
63:       @header[field.downcase] = value.to_s
64:     end

[Source]

    # File lib/webrick/httpresponse.rb, line 92
92:     def chunked=(val)
93:       @chunked = val ? true : false
94:     end

[Source]

    # File lib/webrick/httpresponse.rb, line 88
88:     def chunked?
89:       @chunked
90:     end

[Source]

    # File lib/webrick/httpresponse.rb, line 66
66:     def content_length
67:       if len = self['content-length']
68:         return Integer(len)
69:       end
70:     end

[Source]

    # File lib/webrick/httpresponse.rb, line 72
72:     def content_length=(len)
73:       self['content-length'] = len.to_s
74:     end

[Source]

    # File lib/webrick/httpresponse.rb, line 76
76:     def content_type
77:       self['content-type']
78:     end

[Source]

    # File lib/webrick/httpresponse.rb, line 80
80:     def content_type=(type)
81:       self['content-type'] = type
82:     end

[Source]

    # File lib/webrick/httpresponse.rb, line 84
84:     def each
85:       @header.each{|k, v|  yield(k, v) }
86:     end

[Source]

    # File lib/webrick/httpresponse.rb, line 96
96:     def keep_alive?
97:       @keep_alive
98:     end

[Source]

     # File lib/webrick/httpresponse.rb, line 184
184:     def send_body(socket)
185:       case @body
186:       when IO then send_body_io(socket)
187:       else send_body_string(socket)
188:       end
189:     end

[Source]

     # File lib/webrick/httpresponse.rb, line 169
169:     def send_header(socket)
170:       if @http_version.major > 0
171:         data = status_line()
172:         @header.each{|key, value|
173:           tmp = key.gsub(/\bwww|^te$|\b\w/){|s| s.upcase }
174:           data << "#{tmp}: #{value}" << CRLF
175:         }
176:         @cookies.each{|cookie|
177:           data << "Set-Cookie: " << cookie.to_s << CRLF
178:         }
179:         data << CRLF
180:         _write_data(socket, data)
181:       end
182:     end

[Source]

     # File lib/webrick/httpresponse.rb, line 100
100:     def send_response(socket)
101:       begin
102:         setup_header()
103:         send_header(socket)
104:         send_body(socket)
105:       rescue Errno::EPIPE, Errno::ECONNRESET, Errno::ENOTCONN => ex
106:         @logger.debug(ex)
107:         @keep_alive = false
108:       rescue Exception => ex
109:         @logger.error(ex)
110:         @keep_alive = false
111:       end
112:     end

[Source]

     # File lib/webrick/httpresponse.rb, line 203
203:     def set_error(ex, backtrace=false)
204:       case ex
205:       when HTTPStatus::Status 
206:         @keep_alive = false if HTTPStatus::error?(ex.code)
207:         self.status = ex.code
208:       else 
209:         @keep_alive = false
210:         self.status = HTTPStatus::RC_INTERNAL_SERVER_ERROR
211:       end
212:       @header['content-type'] = "text/html"
213: 
214:       if respond_to?(:create_error_page)
215:         create_error_page()
216:         return
217:       end
218: 
219:       if @request_uri
220:         host, port = @request_uri.host, @request_uri.port
221:       else
222:         host, port = @config[:ServerName], @config[:Port]
223:       end
224: 
225:       @body = ''
226:       @body << "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\">\n<HTML>\n<HEAD><TITLE>\#{HTMLUtils::escape(@reason_phrase)}</TITLE></HEAD>\n<BODY>\n<H1>\#{HTMLUtils::escape(@reason_phrase)}</H1>\n\#{HTMLUtils::escape(ex.message)}\n<HR>\n"
227: 
228:       if backtrace && $DEBUG
229:         @body << "backtrace of `#{HTMLUtils::escape(ex.class.to_s)}' "
230:         @body << "#{HTMLUtils::escape(ex.message)}"
231:         @body << "<PRE>"
232:         ex.backtrace.each{|line| @body << "\t#{line}\n"}
233:         @body << "</PRE><HR>"
234:       end
235: 
236:       @body << "<ADDRESS>\n\#{HTMLUtils::escape(@config[:ServerSoftware])} at\n\#{host}:\#{port}\n</ADDRESS>\n</BODY>\n</HTML>\n"
237:     end

[Source]

     # File lib/webrick/httpresponse.rb, line 197
197:     def set_redirect(status, url)
198:       @body = "<HTML><A HREF=\"#{url.to_s}\">#{url.to_s}</A>.</HTML>\n"
199:       @header['location'] = url.to_s
200:       raise status
201:     end

[Source]

     # File lib/webrick/httpresponse.rb, line 114
114:     def setup_header()
115:       @reason_phrase    ||= HTTPStatus::reason_phrase(@status)
116:       @header['server'] ||= @config[:ServerSoftware]
117:       @header['date']   ||= Time.now.httpdate
118: 
119:       # HTTP/0.9 features
120:       if @request_http_version < "1.0"
121:         @http_version = HTTPVersion.new("0.9")
122:         @keep_alive = false
123:       end
124: 
125:       # HTTP/1.0 features
126:       if @request_http_version < "1.1"
127:         if chunked?
128:           @chunked = false
129:           ver = @request_http_version.to_s
130:           msg = "chunked is set for an HTTP/#{ver} request. (ignored)"
131:           @logger.warn(msg)
132:         end
133:       end
134: 
135:       # Determine the message length (RFC2616 -- 4.4 Message Length)
136:       if @status == 304 || @status == 204 || HTTPStatus::info?(@status)
137:         @header.delete('content-length')
138:         @body = ""
139:       elsif chunked?
140:         @header["transfer-encoding"] = "chunked"
141:         @header.delete('content-length')
142:       elsif %r{^multipart/byteranges} =~ @header['content-type']
143:         @header.delete('content-length')
144:       elsif @header['content-length'].nil?
145:         unless @body.is_a?(IO)
146:           @header['content-length'] = @body ? @body.size : 0
147:         end
148:       end
149: 
150:       # Keep-Alive connection.
151:       if @header['connection'] == "close"
152:          @keep_alive = false
153:       elsif keep_alive?
154:         if chunked? || @header['content-length']
155:           @header['connection'] = "Keep-Alive"
156:         end
157:       else
158:         @header['connection'] = "close"
159:       end
160: 
161:       # Location is a single absoluteURI.
162:       if location = @header['location']
163:         if @request_uri
164:           @header['location'] = @request_uri.merge(location)
165:         end
166:       end
167:     end

[Source]

    # File lib/webrick/httpresponse.rb, line 53
53:     def status=(status)
54:       @status = status
55:       @reason_phrase = HTTPStatus::reason_phrase(status)
56:     end

[Source]

    # File lib/webrick/httpresponse.rb, line 49
49:     def status_line
50:       "HTTP/#@http_version #@status #@reason_phrase #{CRLF}"
51:     end

[Source]

     # File lib/webrick/httpresponse.rb, line 191
191:     def to_s
192:       ret = ""
193:       send_response(ret)
194:       ret
195:     end

Private Instance methods

[Source]

     # File lib/webrick/httpresponse.rb, line 304
304:     def _send_file(output, input, offset, size)
305:       while offset > 0
306:         sz = BUFSIZE < offset ? BUFSIZE : offset
307:         buf = input.read(sz)
308:         offset -= buf.size
309:       end
310: 
311:       if size == 0
312:         while buf = input.read(BUFSIZE)
313:           _write_data(output, buf)
314:         end
315:       else
316:         while size > 0
317:           sz = BUFSIZE < size ? BUFSIZE : size
318:           buf = input.read(sz)
319:           _write_data(output, buf)
320:           size -= buf.size
321:         end
322:       end
323:     end

[Source]

     # File lib/webrick/httpresponse.rb, line 325
325:     def _write_data(socket, data)
326:       socket << data
327:     end

[Source]

     # File lib/webrick/httpresponse.rb, line 258
258:     def send_body_io(socket)
259:       begin
260:         if @request_method == "HEAD"
261:           # do nothing
262:         elsif chunked?
263:           while buf = @body.read(BUFSIZE)
264:             next if buf.empty?
265:             data = ""
266:             data << format("%x", buf.size) << CRLF
267:             data << buf << CRLF
268:             _write_data(socket, data)
269:             @sent_size += buf.size
270:           end
271:           _write_data(socket, "0#{CRLF}#{CRLF}")
272:         else
273:           size = @header['content-length'].to_i
274:           _send_file(socket, @body, 0, size)
275:           @sent_size = size
276:         end
277:       ensure
278:         @body.close
279:       end
280:     end

[Source]

     # File lib/webrick/httpresponse.rb, line 282
282:     def send_body_string(socket)
283:       if @request_method == "HEAD"
284:         # do nothing
285:       elsif chunked?
286:         remain = body ? @body.size : 0
287:         while buf = @body[@sent_size, BUFSIZE]
288:           break if buf.empty?
289:           data = ""
290:           data << format("%x", buf.size) << CRLF
291:           data << buf << CRLF
292:           _write_data(socket, data)
293:           @sent_size += buf.size
294:         end
295:         _write_data(socket, "0#{CRLF}#{CRLF}")
296:       else
297:         if @body && @body.size > 0
298:           _write_data(socket, @body)
299:           @sent_size = @body.size
300:         end
301:       end
302:     end

[Validate]