Object
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.
Used as a fallback in error detection for a malformed request line or header.
Regex used to match a size specification for a chunked segment
The default set of parse options for the request.
Regex used to match a header line. Lines suspected of being headers are also checked against the HeaderContinueMatch to deal with multiline headers
Constants for method information
Regex used to match the Request-Line
The body of the request as a stream object. May be either a StringIO or a TempFile, depending on request length.
A hash of headers passed to the server with the request. All headers will be normalized to ALLCAPS_WITH_UNDERSCORES for consistency's sake.
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.
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
Returns true if the request is completely done.
# File lib/http/native_parser.rb, line 317 def done? @state == :done end
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
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
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
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
Returns true if the request has a body.
# File lib/http/native_parser.rb, line 101 def has_body? @body end
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
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
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
Generated with the Darkfish Rdoc Generator 2.