From 608e6243a2b15bfc28c3524ed45d5fc7598e8565 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Tue, 30 Jun 2009 13:47:41 -0700 Subject: Add trailer_parser for parsing trailers Eventually this (and ChunkedReader) may be done in C/Ragel along with the existing HttpParser. --- lib/unicorn/trailer_parser.rb | 52 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 lib/unicorn/trailer_parser.rb (limited to 'lib') diff --git a/lib/unicorn/trailer_parser.rb b/lib/unicorn/trailer_parser.rb new file mode 100644 index 0000000..c65dc8a --- /dev/null +++ b/lib/unicorn/trailer_parser.rb @@ -0,0 +1,52 @@ +# Copyright (c) 2009 Eric Wong +# You can redistribute it and/or modify it under the same terms as Ruby. +require 'unicorn' +require 'unicorn/http11' + +# Eventually I should integrate this into HttpParser... +module Unicorn + class TrailerParser + + TR_FR = 'a-z-'.freeze + TR_TO = 'A-Z_'.freeze + + # initializes HTTP trailer parser with acceptable +trailer+ + def initialize(http_trailer) + @trailers = http_trailer.split(/\s*,\s*/).inject({}) { |hash, key| + hash[key.tr(TR_FR, TR_TO)] = true + hash + } + end + + # Executes our TrailerParser on +data+ and modifies +env+ This will + # shrink +data+ as it is being consumed. Returns true if it has + # parsed all trailers, false if not. It raises HttpParserError on + # parse failure or unknown headers. It has slightly smaller limits + # than the C-based HTTP parser but should not be an issue in practice + # since Content-MD5 is probably the only legitimate use for it. + def execute!(env, data) + data.size > 0xffff and + raise HttpParserError, "trailer buffer too large: #{data.size} bytes" + + begin + data.sub!(/\A([^\r]+)\r\n/, Z) or return false # need more data + + key, val = $1.split(/:\s*/, 2) + + key.size > 256 and + raise HttpParserError, "trailer key #{key.inspect} is too long" + val.size > 8192 and + raise HttpParserError, "trailer value #{val.inspect} is too long" + + key.tr!(TR_FR, TR_TO) + + @trailers.delete(key.freeze) or + raise HttpParserError, "unknown trailer: #{key.inspect}" + env[key] = val + + @trailers.empty? and return true + end while true + end + + end +end -- cgit v1.2.3-24-ge0c7