yakischloba-http-parser 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile ADDED
@@ -0,0 +1,30 @@
1
+ require 'rubygems'
2
+ require 'ffi'
3
+
4
+ task :default => [:clean, :build, :test]
5
+
6
+ task :clean do
7
+ chdir "src/" do
8
+ sh "make clean"
9
+ sh "rm -rf http_parser.#{FFI::Platform::LIBSUFFIX}"
10
+ end
11
+ end
12
+
13
+ task :build do
14
+ dynamicflag = (FFI::Platform::OS == "darwin" ? "-dynamiclib" : "-fPIC -shared")
15
+ chdir "src/" do
16
+ sh "make"
17
+ sh "gcc #{dynamicflag} -o http_parser.#{FFI::Platform::LIBSUFFIX} http_parser.o"
18
+ end
19
+ end
20
+
21
+ task :test do
22
+ chdir "src/" do
23
+ sh "make test"
24
+ end
25
+ require 'lib/http-parser'
26
+ require 'bacon'
27
+ Bacon.summary_at_exit
28
+ require 'test/request.rb'
29
+ require 'test/response.rb'
30
+ end
@@ -0,0 +1,30 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = "http-parser"
3
+ s.version = "0.0.2"
4
+ s.date = "2009-08-07"
5
+ s.authors = ["Ryan Dahl", "Zed Shaw", "Jake Douglas"]
6
+ s.email = "jakecdouglas@gmail.com"
7
+ s.has_rdoc = true
8
+ # We have rake as a dependency because of a JRuby thing that
9
+ # requires the actual rake gem to be installed.
10
+ s.add_dependency('rake')
11
+ s.add_dependency('ffi')
12
+ s.add_dependency('bacon')
13
+ s.summary = "FFI binding to ry's http-parser"
14
+ s.homepage = "http://www.github.com/yakischloba/http-parser-ffi"
15
+ s.description = "FFI binding to ry's http-parser"
16
+ s.extensions = ["Rakefile"]
17
+ s.files =
18
+ ["http-parser.gemspec",
19
+ #"README.rdoc",
20
+ "Rakefile",
21
+ "lib/http-parser.rb",
22
+ "src/http_parser.h",
23
+ "src/http_parser.rl",
24
+ "src/LICENSE",
25
+ "src/Makefile",
26
+ "src/README.md",
27
+ "src/test.c",
28
+ "test/request.rb",
29
+ "test/response.rb"]
30
+ end
@@ -0,0 +1,193 @@
1
+ require 'ffi'
2
+
3
+ class HttpParser
4
+ extend FFI::Library
5
+ ffi_lib File.dirname(File.expand_path(__FILE__)) + "/../src/" + "http_parser.#{FFI::Platform::LIBSUFFIX}"
6
+
7
+ callback :http_data_cb, [:pointer, :pointer, :size_t], :int
8
+ callback :http_cb, [:pointer], :int
9
+
10
+ # Request methods
11
+ HTTP_COPY = 0x0001
12
+ HTTP_DELETE = 0x0002
13
+ HTTP_GET = 0x0004
14
+ HTTP_HEAD = 0x0008
15
+ HTTP_LOCK = 0x0010
16
+ HTTP_MKCOL = 0x0020
17
+ HTTP_MOVE = 0x0040
18
+ HTTP_OPTIONS = 0x0080
19
+ HTTP_POST = 0x0100
20
+ HTTP_PROPFIND = 0x0200
21
+ HTTP_PROPPATCH = 0x0400
22
+ HTTP_PUT = 0x0800
23
+ HTTP_TRACE = 0x1000
24
+ HTTP_UNLOCK = 0x2000
25
+
26
+ # Transfer encodings
27
+ HTTP_IDENTITY = 0x01
28
+ HTTP_CHUNKED = 0x02
29
+
30
+ enum :http_parser_type, [:HTTP_REQUEST, :HTTP_RESPONSE]
31
+
32
+ class HttpParserStruct < FFI::Struct
33
+ # PRIVATE
34
+ layout :cs, :int,
35
+ :http_parser_type, :int,
36
+ :chunk_size, :size_t,
37
+ :eating, :int,
38
+ :error, :int,
39
+ :body_read, :size_t,
40
+ :header_field_mark, :string,
41
+ :header_field_size, :size_t,
42
+ :header_value_mark, :string,
43
+ :header_value_size, :size_t,
44
+ :query_string_mark, :string,
45
+ :query_string_size, :size_t,
46
+ :path_mark, :string,
47
+ :path_size, :size_t,
48
+ :uri_mark, :string,
49
+ :uri_size, :size_t,
50
+ :fragment_mark, :string,
51
+ :fragment_size, :size_t,
52
+ # READ-ONLY
53
+ :status_code, :ushort, # responses only
54
+ :method, :ushort, # requests only
55
+ :transfer_encoding, :short,
56
+ :version_major, :ushort,
57
+ :version_minor, :ushort,
58
+ :keep_alive, :short,
59
+ :content_length, :size_t,
60
+ # PUBLIC
61
+ :data, :pointer, # A pointer to get hook to the "connection" or "socket" object
62
+ :on_message_begin, :http_cb,
63
+ :on_path, :http_data_cb,
64
+ :on_query_string, :http_data_cb,
65
+ :on_uri, :http_data_cb,
66
+ :on_fragment, :http_data_cb,
67
+ :on_header_field, :http_data_cb,
68
+ :on_header_value, :http_data_cb,
69
+ :on_headers_complete, :http_cb,
70
+ :on_body, :http_data_cb,
71
+ :on_message_complete, :http_cb
72
+ end
73
+
74
+ attach_function :http_parser_init, [:pointer, :http_parser_type], :void
75
+ attach_function :http_parser_execute, [:pointer, :string, :size_t], :size_t
76
+ attach_function :http_parser_has_error, [:pointer], :int
77
+ attach_function :http_parser_should_keep_alive, [:pointer], :int
78
+
79
+ def initialize(type)
80
+ @type = type
81
+ @parser = HttpParserStruct.new
82
+ HttpParser.http_parser_init(@parser, HttpParser.enum_value(@type))
83
+ end
84
+
85
+ def execute(data)
86
+ @abort = false
87
+ HttpParser.http_parser_execute(@parser, data, data.length)
88
+ end
89
+
90
+ def has_error?
91
+ HttpParser.http_parser_has_error(@parser).zero? ? false : true
92
+ end
93
+
94
+ def should_keep_alive?
95
+ HttpParser.http_parser_should_keep_alive(@parser).zero? ? false : true
96
+ end
97
+
98
+ # You can call abort! from inside your callbacks which will halt the processing.
99
+ def abort!
100
+ @abort = true
101
+ end
102
+
103
+ def on_message_begin(proc=nil, &blk)
104
+ proc ||= blk
105
+ @on_message_begin = Proc.new do |ptr|
106
+ proc.call
107
+ @abort ? 1 : 0
108
+ end
109
+ @parser[:on_message_begin] = @on_message_begin
110
+ end
111
+
112
+ def on_path(proc=nil, &blk)
113
+ proc ||= blk
114
+ @on_path = Proc.new do |ptr,data,len|
115
+ proc.call(data.get_string(0, len))
116
+ @abort ? 1 : 0
117
+ end
118
+ @parser[:on_path] = @on_path
119
+ end
120
+
121
+ def on_query_string(proc=nil, &blk)
122
+ proc ||= blk
123
+ @on_query_string = Proc.new do |ptr,data,len|
124
+ proc.call(data.get_string(0, len))
125
+ @abort ? 1 : 0
126
+ end
127
+ @parser[:on_query_string] = @on_query_string
128
+ end
129
+
130
+ def on_uri(proc=nil, &blk)
131
+ proc ||= blk
132
+ @on_uri = Proc.new do |ptr,data,len|
133
+ proc.call(data.get_string(0, len))
134
+ @abort ? 1 : 0
135
+ end
136
+ @parser[:on_uri] = @on_uri
137
+ end
138
+
139
+ def on_fragment(proc=nil, &blk)
140
+ proc ||= blk
141
+ @on_fragment = Proc.new do |ptr,data,len|
142
+ proc.call(data.get_string(0, len))
143
+ @abort ? 1 : 0
144
+ end
145
+ @parser[:on_fragment] = @on_fragment
146
+ end
147
+
148
+ def on_header_field(proc=nil, &blk)
149
+ proc ||= blk
150
+ @on_header_field = Proc.new do |ptr,data,len|
151
+ proc.call(data.get_string(0, len))
152
+ @abort ? 1 : 0
153
+ end
154
+ @parser[:on_header_field] = @on_header_field
155
+ end
156
+
157
+ def on_header_value(proc=nil, &blk)
158
+ proc ||= blk
159
+ @on_header_value= Proc.new do |ptr,data,len|
160
+ proc.call(data.get_string(0, len))
161
+ @abort ? 1 : 0
162
+ end
163
+ @parser[:on_header_value] = @on_header_value
164
+ end
165
+
166
+ def on_headers_complete(proc=nil, &blk)
167
+ proc ||= blk
168
+ @on_headers_complete = Proc.new do |ptr|
169
+ proc.call
170
+ @abort ? 1 : 0
171
+ end
172
+ @parser[:on_headers_complete] = @on_headers_complete
173
+ end
174
+
175
+ def on_body(proc=nil, &blk)
176
+ proc ||= blk
177
+ @on_body = Proc.new do |ptr,data,len|
178
+ proc.call(data.get_string(0, len))
179
+ @abort ? 1 : 0
180
+ end
181
+ @parser[:on_body] = @on_body
182
+ end
183
+
184
+ def on_message_complete(proc=nil, &blk)
185
+ proc ||= blk
186
+ @on_message_complete = Proc.new do |ptr|
187
+ proc.call
188
+ @abort ? 1 : 0
189
+ end
190
+ @parser[:on_message_complete] = @on_message_complete
191
+ end
192
+
193
+ end
data/src/LICENSE ADDED
@@ -0,0 +1,79 @@
1
+ Copyright 2009, Ryan Lienhart Dahl. All rights reserved.
2
+ Permission is hereby granted, free of charge, to any person obtaining a copy
3
+ of this software and associated documentation files (the "Software"), to
4
+ deal in the Software without restriction, including without limitation the
5
+ rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
6
+ sell copies of the Software, and to permit persons to whom the Software is
7
+ furnished to do so, subject to the following conditions:
8
+
9
+ The above copyright notice and this permission notice shall be included in
10
+ all copies or substantial portions of the Software.
11
+
12
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
13
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
14
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
15
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
16
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
17
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
18
+ IN THE SOFTWARE.
19
+
20
+
21
+
22
+
23
+ http_parser is based on Zed Shaw's Mongrel. Mongrel's license is as follows.
24
+
25
+ -- CUT ---- CUT ---- CUT ---- CUT ---- CUT ---- CUT ---- CUT ---- CUT --
26
+ Mongrel Web Server (Mongrel) is copyrighted free software by Zed A. Shaw
27
+ <zedshaw at zedshaw dot com> and contributors. You can redistribute it
28
+ and/or modify it under either the terms of the GPL2 or the conditions below:
29
+
30
+ 1. You may make and give away verbatim copies of the source form of the
31
+ software without restriction, provided that you duplicate all of the
32
+ original copyright notices and associated disclaimers.
33
+
34
+ 2. You may modify your copy of the software in any way, provided that
35
+ you do at least ONE of the following:
36
+
37
+ a) place your modifications in the Public Domain or otherwise make them
38
+ Freely Available, such as by posting said modifications to Usenet or an
39
+ equivalent medium, or by allowing the author to include your
40
+ modifications in the software.
41
+
42
+ b) use the modified software only within your corporation or
43
+ organization.
44
+
45
+ c) rename any non-standard executables so the names do not conflict with
46
+ standard executables, which must also be provided.
47
+
48
+ d) make other distribution arrangements with the author.
49
+
50
+ 3. You may distribute the software in object code or executable
51
+ form, provided that you do at least ONE of the following:
52
+
53
+ a) distribute the executables and library files of the software,
54
+ together with instructions (in the manual page or equivalent) on where
55
+ to get the original distribution.
56
+
57
+ b) accompany the distribution with the machine-readable source of the
58
+ software.
59
+
60
+ c) give non-standard executables non-standard names, with
61
+ instructions on where to get the original software distribution.
62
+
63
+ d) make other distribution arrangements with the author.
64
+
65
+ 4. You may modify and include the part of the software into any other
66
+ software (possibly commercial). But some files in the distribution
67
+ are not written by the author, so that they are not under this terms.
68
+
69
+ 5. The scripts and library files supplied as input to or produced as
70
+ output from the software do not automatically fall under the
71
+ copyright of the software, but belong to whomever generated them,
72
+ and may be sold commercially, and may be aggregated with this
73
+ software.
74
+
75
+ 6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
76
+ IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
77
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
78
+ PURPOSE.
79
+ -- CUT ---- CUT ---- CUT ---- CUT ---- CUT ---- CUT ---- CUT ---- CUT --
data/src/Makefile ADDED
@@ -0,0 +1,27 @@
1
+ #OPT=-O0 -g -Wall -Wextra -Werror
2
+ OPT=-O2
3
+
4
+ test: http_parser.o test.c
5
+ gcc $(OPT) http_parser.o test.c -o $@
6
+
7
+ http_parser.o: http_parser.c http_parser.h Makefile
8
+ gcc $(OPT) -c http_parser.c
9
+
10
+ http_parser.c: http_parser.rl Makefile
11
+ ragel -s -G2 http_parser.rl -o $@
12
+
13
+ tags: http_parser.rl http_parser.h test.c
14
+ ctags $^
15
+
16
+ clean:
17
+ rm -f *.o http_parser.c test http_parser.tar
18
+
19
+ package: http_parser.c
20
+ @rm -rf /tmp/http_parser && mkdir /tmp/http_parser && \
21
+ cp LICENSE README.md Makefile http_parser.c http_parser.rl \
22
+ http_parser.h test.c /tmp/http_parser && \
23
+ cd /tmp && \
24
+ tar -cf http_parser.tar http_parser/
25
+ @echo /tmp/http_parser.tar
26
+
27
+ .PHONY: clean package
data/src/README.md ADDED
@@ -0,0 +1,129 @@
1
+ HTTP Parser
2
+ ===========
3
+
4
+ This is a parser for HTTP messages written in C. It parses both requests
5
+ and responses. The parser is designed to be used in performance HTTP
6
+ applications. It does not make any allocations, it does not buffer data, and
7
+ it can be interrupted at anytime. It only requires about 128 bytes of data
8
+ per message stream (in a web server that is per connection).
9
+
10
+ Features:
11
+
12
+ * No dependencies
13
+ * Parses both requests and responses.
14
+ * Handles keep-alive streams.
15
+ * Decodes chunked encoding.
16
+ * Extracts the following data from a message
17
+ * header fields and values
18
+ * content-length
19
+ * request method
20
+ * response status code
21
+ * transfer-encoding
22
+ * http version
23
+ * request path, query string, fragment
24
+ * message body
25
+ * Defends against buffer overflow attacks.
26
+
27
+ Usage
28
+ -----
29
+
30
+ One `http_parser` object is used per TCP connection. Initialize the struct
31
+ using `http_parser_init()` and set the callbacks. That might look something
32
+ like this:
33
+
34
+ http_parser *parser = malloc(sizeof(http_parser));
35
+ http_parser_init(parser, HTTP_REQUEST);
36
+ parser->on_path = my_path_callback;
37
+ parser->on_header_field = my_header_field_callback;
38
+ parser->data = my_socket;
39
+
40
+ When data is received on the socket execute the parser and check for errors.
41
+
42
+ size_t len = 80*1024;
43
+ char buf[len];
44
+ ssize_t recved;
45
+
46
+ recved = read(fd, buf, len);
47
+ if (recved != 0) // handle error
48
+
49
+ http_parser_execute(parser, buf, recved);
50
+
51
+ if (http_parser_has_error(parser)) {
52
+ // handle error. usually just close the connection
53
+ }
54
+
55
+ Scalar valued message information such as `status_code`, `method`, and the
56
+ HTTP version are stored in the parser structure. This data is only
57
+ temporarlly stored in `http_parser` and gets reset on each new message. If
58
+ this information is needed later, copy it out of the structure during the
59
+ `headers_complete` callback.
60
+
61
+ The parser decodes the transfer-encoding for both requests and responses
62
+ transparently. That is, a chunked encoding is decoded before being sent to
63
+ the on_body callback.
64
+
65
+ It does not decode the content-encoding (gzip). Not all HTTP applications
66
+ need to inspect the body. Decoding gzip is non-neglagable amount of
67
+ processing (and requires making allocations). HTTP proxies using this
68
+ parser, for example, would not want such a feature.
69
+
70
+ Callbacks
71
+ ---------
72
+
73
+ During the `http_parser_execute()` call, the callbacks set in `http_parser`
74
+ will be executed. The parser maintains state and never looks behind, so
75
+ buffering the data is not necessary. If you need to save certain data for
76
+ later usage, you can do that from the callbacks.
77
+
78
+ There are two types of callbacks:
79
+
80
+ * notification `typedef int (*http_cb) (http_parser*);`
81
+ Callbacks: on_message_begin, on_headers_complete, on_message_complete.
82
+ * data `typedef int (*http_data_cb) (http_parser*, const char *at, size_t length);`
83
+ Callbacks: (requests only) on_path, on_query_string, on_uri, on_fragment,
84
+ (common) on_header_field, on_header_value, on_body;
85
+
86
+ In case you parse HTTP message in chunks (i.e. `read()` request line
87
+ from socket, parse, read half headers, parse, etc) your data callbacks
88
+ may be called more than once. Http-parser guarantees that data pointer is only
89
+ valid for the lifetime of callback. You can also `read()` into a heap allocated
90
+ buffer to avoid copying memory around if this fits your application.
91
+
92
+ Reading headers may be a tricky task if you read/parse headers partially.
93
+ Basically, you need to remember whether last header callback was field or value
94
+ and apply following logic:
95
+
96
+ /* on_header_field and on_header_value shortened to on_h_*
97
+ ------------------------ ------------ --------------------------------------------
98
+ | State (prev. callback) | Callback | Description/action |
99
+ ------------------------ ------------ --------------------------------------------
100
+ | nothing (first call) | on_h_field | Allocate new buffer and copy callback data |
101
+ | | | into it |
102
+ ------------------------ ------------ --------------------------------------------
103
+ | value | on_h_field | New header started. |
104
+ | | | Copy current name,value buffers to headers |
105
+ | | | list and allocate new buffer for new name |
106
+ ------------------------ ------------ --------------------------------------------
107
+ | field | on_h_field | Previous name continues. Reallocate name |
108
+ | | | buffer and append callback data to it |
109
+ ------------------------ ------------ --------------------------------------------
110
+ | field | on_h_value | Value for current header started. Allocate |
111
+ | | | new buffer and copy callback data to it |
112
+ ------------------------ ------------ --------------------------------------------
113
+ | value | on_h_value | Value continues. Reallocate value buffer |
114
+ | | | and append callback data to it |
115
+ ------------------------ ------------ --------------------------------------------
116
+ */
117
+
118
+ See examples of reading in headers:
119
+
120
+ * [partial example](http://gist.github.com/155877) in C
121
+ * [from http-parser tests](http://github.com/ry/http-parser/blob/37a0ff8928fb0d83cec0d0d8909c5a4abcd221af/test.c#L403) in C
122
+ * [from Node library](http://github.com/ry/node/blob/842eaf446d2fdcb33b296c67c911c32a0dabc747/src/http.js#L284) in Javascript
123
+
124
+ Releases
125
+ --------
126
+
127
+ * [0.1](http://s3.amazonaws.com/four.livejournal/20090427/http_parser-0.1.tar.gz)
128
+
129
+ The source repo is at [github](http://github.com/ry/http-parser).
data/src/http_parser.h ADDED
@@ -0,0 +1,133 @@
1
+ /* Copyright (c) 2008, 2009 Ryan Dahl (ry@tinyclouds.org)
2
+ * Based on Zed Shaw's Mongrel, copyright (c) Zed A. Shaw
3
+ *
4
+ * All rights reserved.
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person obtaining
7
+ * a copy of this software and associated documentation files (the
8
+ * "Software"), to deal in the Software without restriction, including
9
+ * without limitation the rights to use, copy, modify, merge, publish,
10
+ * distribute, sublicense, and/or sell copies of the Software, and to
11
+ * permit persons to whom the Software is furnished to do so, subject to
12
+ * the following conditions:
13
+ *
14
+ * The above copyright notice and this permission notice shall be
15
+ * included in all copies or substantial portions of the Software.
16
+ *
17
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
+ */
25
+ #ifndef http_parser_h
26
+ #define http_parser_h
27
+ #ifdef __cplusplus
28
+ extern "C" {
29
+ #endif
30
+
31
+ #include <sys/types.h>
32
+
33
+ typedef struct http_parser http_parser;
34
+
35
+ /* Callbacks should return non-zero to indicate an error. The parse will
36
+ * then halt execution.
37
+ *
38
+ * http_data_cb does not return data chunks. It will be call arbitrarally
39
+ * many times for each string. E.G. you might get 10 callbacks for "on_path"
40
+ * each providing just a few characters more data.
41
+ */
42
+ typedef int (*http_data_cb) (http_parser*, const char *at, size_t length);
43
+ typedef int (*http_cb) (http_parser*);
44
+
45
+ /* Request Methods */
46
+ #define HTTP_COPY 0x0001
47
+ #define HTTP_DELETE 0x0002
48
+ #define HTTP_GET 0x0004
49
+ #define HTTP_HEAD 0x0008
50
+ #define HTTP_LOCK 0x0010
51
+ #define HTTP_MKCOL 0x0020
52
+ #define HTTP_MOVE 0x0040
53
+ #define HTTP_OPTIONS 0x0080
54
+ #define HTTP_POST 0x0100
55
+ #define HTTP_PROPFIND 0x0200
56
+ #define HTTP_PROPPATCH 0x0400
57
+ #define HTTP_PUT 0x0800
58
+ #define HTTP_TRACE 0x1000
59
+ #define HTTP_UNLOCK 0x2000
60
+
61
+ /* Transfer Encodings */
62
+ #define HTTP_IDENTITY 0x01
63
+ #define HTTP_CHUNKED 0x02
64
+
65
+ enum http_parser_type { HTTP_REQUEST, HTTP_RESPONSE };
66
+
67
+ struct http_parser {
68
+ /** PRIVATE **/
69
+ int cs;
70
+ enum http_parser_type type;
71
+
72
+ size_t chunk_size;
73
+ int eating;
74
+ int error;
75
+ size_t body_read;
76
+
77
+ const char *header_field_mark;
78
+ size_t header_field_size;
79
+ const char *header_value_mark;
80
+ size_t header_value_size;
81
+ const char *query_string_mark;
82
+ size_t query_string_size;
83
+ const char *path_mark;
84
+ size_t path_size;
85
+ const char *uri_mark;
86
+ size_t uri_size;
87
+ const char *fragment_mark;
88
+ size_t fragment_size;
89
+
90
+ /** READ-ONLY **/
91
+ unsigned short status_code; /* responses only */
92
+ unsigned short method; /* requests only */
93
+ short transfer_encoding;
94
+ unsigned short version_major;
95
+ unsigned short version_minor;
96
+ short keep_alive;
97
+ size_t content_length;
98
+
99
+ /** PUBLIC **/
100
+ void *data; /* A pointer to get hook to the "connection" or "socket" object */
101
+
102
+ /* an ordered list of callbacks */
103
+
104
+ http_cb on_message_begin;
105
+
106
+ /* requests only */
107
+ http_data_cb on_path;
108
+ http_data_cb on_query_string;
109
+ http_data_cb on_uri;
110
+ http_data_cb on_fragment;
111
+
112
+ http_data_cb on_header_field;
113
+ http_data_cb on_header_value;
114
+ http_cb on_headers_complete;
115
+ http_data_cb on_body;
116
+ http_cb on_message_complete;
117
+ };
118
+
119
+ /* Initializes an http_parser structure. The second argument specifies if
120
+ * it will be parsing requests or responses.
121
+ */
122
+ void http_parser_init (http_parser *parser, enum http_parser_type);
123
+
124
+ size_t http_parser_execute (http_parser *parser, const char *data, size_t len);
125
+
126
+ int http_parser_has_error (http_parser *parser);
127
+
128
+ int http_parser_should_keep_alive (http_parser *parser);
129
+
130
+ #ifdef __cplusplus
131
+ }
132
+ #endif
133
+ #endif