Parent

Http::Parser

This is a native ruby implementation of the http parser. It is also the reference implementation for this library. Later there will be one written in C for performance reasons, and it will have to pass the same specs as this one.

Constants

AnyLineMatch

Used as a fallback in error detection for a malformed request line or header.

ChunkSizeLineMatch

Regex used to match a size specification for a chunked segment

DefaultOptions

The default set of parse options for the request.

EmptyLineMatch
HeaderContinueMatch
HeaderLineMatch

Regex used to match a header line. Lines suspected of being headers are also checked against the HeaderContinueMatch to deal with multiline headers

MethodInfo

Constants for method information

Methods
RequestLineMatch

Regex used to match the Request-Line

Attributes

body[R]

The body of the request as a stream object. May be either a StringIO or a TempFile, depending on request length.

headers[R]

A hash of headers passed to the server with the request. All headers will be normalized to ALLCAPS_WITH_UNDERSCORES for consistency's sake.

method[R]

The HTTP method string used. Will always be a string and all-capsed. Valid values are: "GET", "HEAD", "POST", "PUT", "DELETE". Other values will cause an exception since then we don't know whether the request has a body.

path[R]

The path given by the client as a string. No processing is done on this and nearly anything is considered valid.

version[R]

The HTTP version of the request as an array of two integers.

1,0

and [1,1] are the most likely values currently.

Public Class Methods

new(options = DefaultOptions) click to toggle source
# File lib/http/native_parser.rb, line 76
def initialize(options = DefaultOptions)
  @method = nil
  @path = nil
  @version = nil
  @headers = {}
  @body = nil
  @state = :request_line
  @options = DefaultOptions.merge(options)
end

Public Instance Methods

can_have_body?() click to toggle source

Returns true if the http method being parsed (if known at this point in the parse) can have a body. If the method hasn't been determined yet, returns false.

# File lib/http/native_parser.rb, line 96
def can_have_body?
  Methods[@method].can_have_body
end
done?() click to toggle source

Returns true if the request is completely done.

# File lib/http/native_parser.rb, line 317
def done?
  @state == :done
end
done_body?() click to toggle source

Returns true if the request's body has been consumed (really the same as done?)

# File lib/http/native_parser.rb, line 330
def done_body?
  done?
end
done_headers?() click to toggle source

Returns true if all the headers from the request have been consumed.

# File lib/http/native_parser.rb, line 326
def done_headers?
  [:body_identity, :body_chunked, :body_chunked_tail, :done].include?(@state)
end
done_request_line?() click to toggle source

Returns true if the request has parsed the request-line (GET / HTTP/1.1)

# File lib/http/native_parser.rb, line 322
def done_request_line?
  [:headers, :body_identity, :body_chunked, :body_chunked_tail, :done].include?(@state)
end
fill_rack_env(env = {}) click to toggle source

Given a basic rack environment, will properly fill it in with the information gleaned from the parsed request. Note that this only fills the subset that can be determined by the parser library. Namely, the only rack. variable set is rack.input. You should also have defaults in place for SERVER_NAME and SERVER_PORT, as they are required.

# File lib/http/native_parser.rb, line 295
def fill_rack_env(env = {})
  env["rack.input"] = @body || StringIO.new
  env["REQUEST_METHOD"] = @method
  env["SCRIPT_NAME"] = ""
  env["REQUEST_URI"] = @path
  env["PATH_INFO"], query = @path.split("?", 2)
  env["QUERY_STRING"] = query || ""
  if (@headers["HOST"] && !env["SERVER_NAME"])
    env["SERVER_NAME"], port = @headers["HOST"].split(":", 2)
    env["SERVER_PORT"] = port if port
  end
  @headers.each do |key, val|
    if (key == 'CONTENT_LENGTH' || key == 'CONTENT_TYPE')
      env[key] = val
    else
      env["HTTP_#{key}"] = val
    end
  end
  return env
end
has_body?() click to toggle source

Returns true if the request has a body.

# File lib/http/native_parser.rb, line 101
def has_body?
  @body
end
must_have_body?() click to toggle source

Returns true if the http method being parsed (if known at this point in the parse) must have a body. If the method hasn't been determined yet, returns false.

# File lib/http/native_parser.rb, line 89
def must_have_body?
  Methods[@method].must_have_body
end
parse(str) click to toggle source

Takes a string and runs it through the parser. Note that it does not consume anything it can't completely parse, so you should always pass complete request chunks (lines or body data) to this method. It's mostly for testing and convenience. In practical use, you want to use parse!, which will remove parsed data from the string you pass in.

# File lib/http/native_parser.rb, line 111
def parse(str)
  parse!(str.dup)
end
parse!(str) click to toggle source

Consumes as much of str as it can and then removes it from str. This allows you to iteratively pass data into the parser as it comes from the client.

# File lib/http/native_parser.rb, line 266
def parse!(str)
  scanner = StringScanner.new(str)
  begin
    while (!scanner.eos?)
      start_pos = scanner.pos
      send(:"parse_#{@state}", scanner)
      if (scanner.pos == start_pos)
        # if we didn't move forward, we've run out of useful string so throw it back.
        return str
      end
    end
  ensure
    # clear out whatever we managed to scan.
    str[0, scanner.pos] = ""
  end
end

[Validate]

Generated with the Darkfish Rdoc Generator 2.