Class: WEBrick::HTTPResponse

Inherits:
Object
  • Object
show all
Defined in:
lib/webrick/httpresponse.rb

Overview

An HTTP response.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(config) ⇒ HTTPResponse

Creates a new HTTP response object



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/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

Instance Attribute Details

#bodyObject

Body may be a String or IO subclass.



29
30
31
# File 'lib/webrick/httpresponse.rb', line 29

def body
  @body
end

#configObject (readonly)

Returns the value of attribute config.



34
35
36
# File 'lib/webrick/httpresponse.rb', line 34

def config
  @config
end

#cookiesObject (readonly)

Returns the value of attribute cookies.



23
24
25
# File 'lib/webrick/httpresponse.rb', line 23

def cookies
  @cookies
end

#filenameObject

Returns the value of attribute filename.



32
33
34
# File 'lib/webrick/httpresponse.rb', line 32

def filename
  @filename
end

#headerObject (readonly)

Returns the value of attribute header.



22
23
24
# File 'lib/webrick/httpresponse.rb', line 22

def header
  @header
end

#http_versionObject (readonly)

Returns the value of attribute http_version.



22
23
24
# File 'lib/webrick/httpresponse.rb', line 22

def http_version
  @http_version
end

#keep_aliveObject

Returns the value of attribute keep_alive.



33
34
35
# File 'lib/webrick/httpresponse.rb', line 33

def keep_alive
  @keep_alive
end

#reason_phraseObject

Returns the value of attribute reason_phrase.



24
25
26
# File 'lib/webrick/httpresponse.rb', line 24

def reason_phrase
  @reason_phrase
end

#request_http_versionObject

Returns the value of attribute request_http_version.



31
32
33
# File 'lib/webrick/httpresponse.rb', line 31

def request_http_version
  @request_http_version
end

#request_methodObject

Returns the value of attribute request_method.



31
32
33
# File 'lib/webrick/httpresponse.rb', line 31

def request_method
  @request_method
end

#request_uriObject

Returns the value of attribute request_uri.



31
32
33
# File 'lib/webrick/httpresponse.rb', line 31

def request_uri
  @request_uri
end

#sent_sizeObject (readonly)

Returns the value of attribute sent_size.



34
35
36
# File 'lib/webrick/httpresponse.rb', line 34

def sent_size
  @sent_size
end

#statusObject

Returns the value of attribute status.



22
23
24
# File 'lib/webrick/httpresponse.rb', line 22

def status
  @status
end

Instance Method Details

#[](field) ⇒ Object

Retrieves the response header field



76
77
78
# File 'lib/webrick/httpresponse.rb', line 76

def [](field)
  @header[field.downcase]
end

#[]=(field, value) ⇒ Object

Sets the response header field to value



83
84
85
# File 'lib/webrick/httpresponse.rb', line 83

def []=(field, value)
  @header[field.downcase] = value.to_s
end

#chunked=(val) ⇒ Object

Enables chunked transfer encoding.



134
135
136
# File 'lib/webrick/httpresponse.rb', line 134

def chunked=(val)
  @chunked = val ? true : false
end

#chunked?Boolean

Will this response body be returned using chunked transfer-encoding?

Returns:

  • (Boolean)


127
128
129
# File 'lib/webrick/httpresponse.rb', line 127

def chunked?
  @chunked
end

#content_lengthObject

The content-length header



90
91
92
93
94
# File 'lib/webrick/httpresponse.rb', line 90

def content_length
  if len = self['content-length']
    return Integer(len)
  end
end

#content_length=(len) ⇒ Object

Sets the content-length header to len



99
100
101
# File 'lib/webrick/httpresponse.rb', line 99

def content_length=(len)
  self['content-length'] = len.to_s
end

#content_typeObject

The content-type header



106
107
108
# File 'lib/webrick/httpresponse.rb', line 106

def content_type
  self['content-type']
end

#content_type=(type) ⇒ Object

Sets the content-type header to type



113
114
115
# File 'lib/webrick/httpresponse.rb', line 113

def content_type=(type)
  self['content-type'] = type
end

#eachObject

Iterates over each header in the resopnse



120
121
122
# File 'lib/webrick/httpresponse.rb', line 120

def each
  @header.each{|field, value|  yield(field, value) }
end

#keep_alive?Boolean

Will this response’s connection be kept alive?

Returns:

  • (Boolean)


141
142
143
# File 'lib/webrick/httpresponse.rb', line 141

def keep_alive?
  @keep_alive
end

#send_body(socket) ⇒ Object

Sends the body on socket



246
247
248
249
250
251
# File 'lib/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

#send_header(socket) ⇒ Object

Sends the headers on socket



228
229
230
231
232
233
234
235
236
237
238
239
240
241
# File 'lib/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

#send_response(socket) ⇒ Object

Sends the response on socket



148
149
150
151
152
153
154
155
156
157
158
159
160
# File 'lib/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

#set_error(ex, backtrace = false) ⇒ Object

Creates an error page for exception ex with an optional backtrace



275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
# File 'lib/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 << <<-_end_of_html_
<!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>
  _end_of_html_

  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 << <<-_end_of_html_
<ADDRESS>
 #{HTMLUtils::escape(@config[:ServerSoftware])} at
 #{host}:#{port}
</ADDRESS>
  </BODY>
</HTML>
  _end_of_html_
end

#set_redirect(status, url) ⇒ Object

Redirects to url with a WEBrick::HTTPStatus::Redirect status.

Example:

res.set_redirect WEBrick::HTTPStatus::TemporaryRedirect


266
267
268
269
270
# File 'lib/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

#setup_headerObject

Sets up the headers for sending



165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
# File 'lib/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'] || @status == 304 || @status == 204 || HTTPStatus.info?(@status)
      @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

#status_lineObject

The response’s HTTP status line



61
62
63
# File 'lib/webrick/httpresponse.rb', line 61

def status_line
  "HTTP/#@http_version #@status #@reason_phrase #{CRLF}"
end

#to_sObject

:nodoc:



253
254
255
256
257
# File 'lib/webrick/httpresponse.rb', line 253

def to_s # :nodoc:
  ret = ""
  send_response(ret)
  ret
end