class Thin::Request

A request sent by the client to the server.

Constants

ASYNC_CALLBACK
ASYNC_CLOSE
BODY_TMPFILE
CLOSE_REGEXP
CONNECTION
CONTENT_LENGTH
HTTP_1_0
HTTP_VERSION
INITIAL_BODY
KEEP_ALIVE_REGEXP
LOCALHOST
MAX_BODY

Maximum request body size before it is moved out of memory and into a tempfile for reading.

MAX_HEADER
RACK_ERRORS
RACK_INPUT

Freeze some Rack header names

RACK_MULTIPROCESS
RACK_MULTITHREAD
RACK_RUN_ONCE
RACK_VERSION
REMOTE_ADDR
REQUEST_METHOD
SERVER_NAME
SERVER_SOFTWARE

Freeze some HTTP header names & values

Attributes

body[R]

Request body

data[R]

Unparsed data of the request

env[R]

CGI-like request environment variables

Public Class Methods

new() click to toggle source
# File lib/thin/request.rb, line 53
def initialize
  @parser   = Thin::HttpParser.new
  @data     = ''
  @nparsed  = 0
  @body     = StringIO.new(INITIAL_BODY.dup)
  @env      = {
    SERVER_SOFTWARE   => SERVER,
    SERVER_NAME       => LOCALHOST,

    # Rack stuff
    RACK_INPUT        => @body,

    RACK_VERSION      => VERSION::RACK,
    RACK_ERRORS       => STDERR,

    RACK_MULTITHREAD  => false,
    RACK_MULTIPROCESS => false,
    RACK_RUN_ONCE     => false
  }
end

Public Instance Methods

async_callback=(callback) click to toggle source
# File lib/thin/request.rb, line 134
def async_callback=(callback)
  @env[ASYNC_CALLBACK] = callback
  @env[ASYNC_CLOSE] = EventMachine::DefaultDeferrable.new
end
async_close() click to toggle source
# File lib/thin/request.rb, line 139
def async_close
  @async_close ||= @env[ASYNC_CLOSE]
end
close() click to toggle source

Close any resource used by the request

# File lib/thin/request.rb, line 148
def close
  @body.delete if @body.class == Tempfile
end
content_length() click to toggle source

Expected size of the body

# File lib/thin/request.rb, line 106
def content_length
  @env[CONTENT_LENGTH].to_i
end
finished?() click to toggle source

true if headers and body are finished parsing

# File lib/thin/request.rb, line 101
def finished?
  @parser.finished? && @body.size >= content_length
end
head?() click to toggle source
# File lib/thin/request.rb, line 143
def head?
  @env[REQUEST_METHOD] == HEAD
end
parse(data) click to toggle source

Parse a chunk of data into the request environment Raises an InvalidRequest if invalid. Returns true if the parsing is complete.

# File lib/thin/request.rb, line 77
def parse(data)
  if @parser.finished?  # Header finished, can only be some more body
    @body << data
  else                  # Parse more header using the super parser
    @data << data
    raise InvalidRequest, 'Header longer than allowed' if @data.size > MAX_HEADER

    @nparsed = @parser.execute(@env, @data, @nparsed)

    # Transfer to a tempfile if body is very big
    move_body_to_tempfile if @parser.finished? && content_length > MAX_BODY
  end


  if finished?   # Check if header and body are complete
    @data = nil
    @body.rewind
    true         # Request is fully parsed
  else
    false        # Not finished, need more data
  end
end
persistent?() click to toggle source

Returns true if the client expects the connection to be persistent.

# File lib/thin/request.rb, line 111
def persistent?
  # Clients and servers SHOULD NOT assume that a persistent connection
  # is maintained for HTTP versions less than 1.1 unless it is explicitly
  # signaled. (http://www.w3.org/Protocols/rfc2616/rfc2616-sec8.html)
  if @env[HTTP_VERSION] == HTTP_1_0
    @env[CONNECTION] =~ KEEP_ALIVE_REGEXP

  # HTTP/1.1 client intends to maintain a persistent connection unless
  # a Connection header including the connection-token "close" was sent
  # in the request
  else
    @env[CONNECTION].nil? || @env[CONNECTION] !~ CLOSE_REGEXP
  end
end
remote_address=(address) click to toggle source
# File lib/thin/request.rb, line 126
def remote_address=(address)
  @env[REMOTE_ADDR] = address
end
threaded=(value) click to toggle source
# File lib/thin/request.rb, line 130
def threaded=(value)
  @env[RACK_MULTITHREAD] = value
end

Private Instance Methods

move_body_to_tempfile() click to toggle source
# File lib/thin/request.rb, line 153
def move_body_to_tempfile
  current_body = @body
  current_body.rewind
  @body = Tempfile.new(BODY_TMPFILE)
  @body.binmode
  @body << current_body.read
  @env[RACK_INPUT] = @body
end