********************************************************************** * Author : Brian Maher <maherb at brimworks dot com> * Library : lua-http-parser - Lua 5.1 interface to ry's http-parser * * The MIT License * * Copyright (c) 2009-1010 Brian Maher * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. ********************************************************************** To use this library, you need joyent's http-parser, get it here: git clone git://github.com/joyent/http-parser.git To build this library, you need luarocks, get it here: http://www.luarocks.org/en/Download Then build it like this: luarocks make CFLAGS=-g Loading the library: If you built the library as a loadable package [local] lhp = require 'http.parser' If you compiled the package statically into your application, call the function "luaopen_http_parser(L)". It will create a table with the http parser functions and leave it on the top of the stack. To test the library run: ./test.lua ...assuming that the `lua` on your PATH properly uses the luarocks installed module. API: parser = lhp.request { on_url = function(url) ... end on_header = function(hkey, hval) ... end on_body = function(body) ... end on_message_begin = function() ... end on_message_complete = function() ... end on_headers_complete = function() ... end } parser = lhp.response { ... } Create a new HTTP parser to handle either an HTTP request or HTTP response respectively. Pass in a table of callbacks that are ran when the parser encounters the various fields. All callbacks will be ran with the full value for that field with on_body being the notible exception. You can treat the on_body handler as an LTN12 "source" since it is always garanteed to send a terminating on_body(nil) event when the complete body has been read. Note that the on_body(nil) event will even be sent if there is an empty body. NOTE: Ry's http parser may call any of these callbacks with a partial value if the input_bytes are split on a "token" boundary. At this point we always assume that you will want everything except the body to be buffered, but if you have a valid use case for manually setting which callbacks are buffered, please send an email to the author. bytes_read = parser:execute(input_bytes) Feed the parser some partial input. Returns how many bytes where read. A short read may happen if a request is being "upgraded" or was an invalid format. See parser:is_upgrade() below to differentiate between these two events (if you want to support an upgraded protocol). NOTE: If the input_bytes causes more than about 2000 event callbacks to be executed a short read will occur and any attempt to continue the parse will fail. If this is a problem, restrict your input to < 8K input_bytes at a time, although in general this is probaly more of a symptom of a DDoS attack and therefore returning status 400 (Bad Request) is probably the best thing to do anyways. parser:should_keep_alive() Returns true if this TCP connection should be "kept alive" so that it can be re-used for a future request/response. If this returns false and you are the server, then respond with the "Connection: close" header. If you are the client, then simply close the connection. parser:is_upgrade() Returns true if the input request wants to "upgrade" to a different protocol. parser:version() Returns HTTP version as two numbers (major, minor). parser:method() Returns the name of the request method. This is only valid on HTTP requests. parser:error() Returns errno(number), error name(string), error description(string). parser:status_code() Returns the HTTP status code of a response. This is only valid on HTTP responses.