em-http-request 0.3.0 → 1.0.0.beta.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of em-http-request might be problematic. Click here for more details.
- data/.gitignore +1 -0
- data/Changelog.md +10 -0
- data/README.md +43 -160
- data/Rakefile +2 -73
- data/em-http-request.gemspec +7 -7
- data/examples/fetch.rb +30 -30
- data/examples/fibered-http.rb +38 -38
- data/examples/oauth-tweet.rb +49 -49
- data/lib/em-http.rb +4 -6
- data/lib/em-http/client.rb +101 -522
- data/lib/em-http/http_connection.rb +125 -0
- data/lib/em-http/http_encoding.rb +19 -12
- data/lib/em-http/http_header.rb +2 -17
- data/lib/em-http/http_options.rb +37 -19
- data/lib/em-http/request.rb +33 -66
- data/lib/em-http/version.rb +2 -2
- data/spec/client_spec.rb +575 -0
- data/spec/dns_spec.rb +41 -0
- data/spec/encoding_spec.rb +6 -6
- data/spec/external_spec.rb +99 -0
- data/spec/fixtures/google.ca +13 -17
- data/spec/helper.rb +17 -8
- data/spec/http_proxy_spec.rb +53 -0
- data/spec/middleware_spec.rb +114 -0
- data/spec/multi_spec.rb +11 -38
- data/spec/pipelining_spec.rb +38 -0
- data/spec/redirect_spec.rb +114 -0
- data/spec/socksify_proxy_spec.rb +24 -0
- data/spec/ssl_spec.rb +20 -0
- data/spec/stallion.rb +7 -63
- metadata +59 -39
- data/examples/websocket-handler.rb +0 -28
- data/examples/websocket-server.rb +0 -8
- data/ext/buffer/em_buffer.c +0 -639
- data/ext/buffer/extconf.rb +0 -53
- data/ext/http11_client/ext_help.h +0 -14
- data/ext/http11_client/extconf.rb +0 -6
- data/ext/http11_client/http11_client.c +0 -328
- data/ext/http11_client/http11_parser.c +0 -418
- data/ext/http11_client/http11_parser.h +0 -48
- data/ext/http11_client/http11_parser.rl +0 -170
- data/lib/em-http/mock.rb +0 -137
- data/spec/mock_spec.rb +0 -166
- data/spec/request_spec.rb +0 -1003
data/ext/buffer/extconf.rb
DELETED
@@ -1,53 +0,0 @@
|
|
1
|
-
require 'mkmf'
|
2
|
-
|
3
|
-
libs = []
|
4
|
-
|
5
|
-
$defs << "-DRUBY_VERSION_CODE=#{RUBY_VERSION.gsub(/\D/, '')}"
|
6
|
-
|
7
|
-
if have_func('rb_thread_blocking_region')
|
8
|
-
$defs << '-DHAVE_RB_THREAD_BLOCKING_REGION'
|
9
|
-
end
|
10
|
-
|
11
|
-
if have_func('rb_str_set_len')
|
12
|
-
$defs << '-DHAVE_RB_STR_SET_LEN'
|
13
|
-
end
|
14
|
-
|
15
|
-
if have_header('sys/select.h')
|
16
|
-
$defs << '-DEV_USE_SELECT'
|
17
|
-
end
|
18
|
-
|
19
|
-
if have_header('poll.h')
|
20
|
-
$defs << '-DEV_USE_POLL'
|
21
|
-
end
|
22
|
-
|
23
|
-
if have_header('sys/epoll.h')
|
24
|
-
$defs << '-DEV_USE_EPOLL'
|
25
|
-
end
|
26
|
-
|
27
|
-
if have_header('sys/event.h') and have_header('sys/queue.h')
|
28
|
-
$defs << '-DEV_USE_KQUEUE'
|
29
|
-
end
|
30
|
-
|
31
|
-
if have_header('port.h')
|
32
|
-
$defs << '-DEV_USE_PORT'
|
33
|
-
end
|
34
|
-
|
35
|
-
if have_header('openssl/ssl.h')
|
36
|
-
$defs << '-DHAVE_OPENSSL_SSL_H'
|
37
|
-
libs << '-lssl -lcrypto'
|
38
|
-
end
|
39
|
-
|
40
|
-
# ncpu detection specifics
|
41
|
-
case RUBY_PLATFORM
|
42
|
-
when /linux/
|
43
|
-
$defs << '-DHAVE_LINUX_PROCFS'
|
44
|
-
else
|
45
|
-
if have_func('sysctlbyname', ['sys/param.h', 'sys/sysctl.h'])
|
46
|
-
$defs << '-DHAVE_SYSCTLBYNAME'
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
$LIBS << ' ' << libs.join(' ')
|
51
|
-
|
52
|
-
dir_config('em_buffer')
|
53
|
-
create_makefile('em_buffer')
|
@@ -1,14 +0,0 @@
|
|
1
|
-
#ifndef ext_help_h
|
2
|
-
#define ext_help_h
|
3
|
-
|
4
|
-
#define RAISE_NOT_NULL(T) if(T == NULL) rb_raise(rb_eArgError, "NULL found for " # T " when shouldn't be.");
|
5
|
-
#define DATA_GET(from,type,name) Data_Get_Struct(from,type,name); RAISE_NOT_NULL(name);
|
6
|
-
#define REQUIRE_TYPE(V, T) if(TYPE(V) != T) rb_raise(rb_eTypeError, "Wrong argument type for " # V " required " # T);
|
7
|
-
|
8
|
-
#ifdef DEBUG
|
9
|
-
#define TRACE() fprintf(stderr, "> %s:%d:%s\n", __FILE__, __LINE__, __FUNCTION__)
|
10
|
-
#else
|
11
|
-
#define TRACE()
|
12
|
-
#endif
|
13
|
-
|
14
|
-
#endif
|
@@ -1,328 +0,0 @@
|
|
1
|
-
/**
|
2
|
-
* Copyright (c) 2005 Zed A. Shaw
|
3
|
-
* You can redistribute it and/or modify it under the same terms as Ruby.
|
4
|
-
*/
|
5
|
-
|
6
|
-
#include "ruby.h"
|
7
|
-
#include "ext_help.h"
|
8
|
-
#include <assert.h>
|
9
|
-
#include <string.h>
|
10
|
-
#include "http11_parser.h"
|
11
|
-
#include <ctype.h>
|
12
|
-
|
13
|
-
static VALUE mEm;
|
14
|
-
static VALUE cHttpClientParser;
|
15
|
-
static VALUE eHttpClientParserError;
|
16
|
-
|
17
|
-
#define id_reason rb_intern("@http_reason")
|
18
|
-
#define id_status rb_intern("@http_status")
|
19
|
-
#define id_version rb_intern("@http_version")
|
20
|
-
#define id_body rb_intern("@http_body")
|
21
|
-
#define id_chunk_size rb_intern("@http_chunk_size")
|
22
|
-
#define id_last_chunk rb_intern("@last_chunk")
|
23
|
-
|
24
|
-
#ifndef RHASH_TBL
|
25
|
-
/* rb_hash_lookup() is only in Ruby 1.8.7 */
|
26
|
-
static VALUE rb_hash_lookup(VALUE hash, VALUE key)
|
27
|
-
{
|
28
|
-
VALUE val;
|
29
|
-
|
30
|
-
if (!st_lookup(RHASH(hash)->tbl, key, &val)) {
|
31
|
-
return Qnil; /* without Hash#default */
|
32
|
-
}
|
33
|
-
|
34
|
-
return val;
|
35
|
-
}
|
36
|
-
#endif
|
37
|
-
|
38
|
-
void client_http_field(void *data, const char *field, size_t flen, const char *value, size_t vlen)
|
39
|
-
{
|
40
|
-
char *ch, *end;
|
41
|
-
VALUE req = (VALUE)data;
|
42
|
-
VALUE v = Qnil;
|
43
|
-
VALUE f = Qnil;
|
44
|
-
VALUE el = Qnil;
|
45
|
-
|
46
|
-
v = rb_str_new(value, vlen);
|
47
|
-
f = rb_str_new(field, flen);
|
48
|
-
|
49
|
-
/* Yes Children, rb_str_upcase_bang isn't even available as an intern.h function.
|
50
|
-
* how incredibly handy to not have that. Nope, I have to do it by hand.*/
|
51
|
-
for(ch = RSTRING_PTR(f), end = ch + RSTRING_LEN(f); ch < end; ch++) {
|
52
|
-
if(*ch == '-') {
|
53
|
-
*ch = '_';
|
54
|
-
} else {
|
55
|
-
*ch = toupper(*ch);
|
56
|
-
}
|
57
|
-
}
|
58
|
-
|
59
|
-
el = rb_hash_lookup(req, f);
|
60
|
-
switch(TYPE(el)) {
|
61
|
-
case T_ARRAY:
|
62
|
-
rb_ary_push(el, v);
|
63
|
-
break;
|
64
|
-
case T_STRING:
|
65
|
-
rb_hash_aset(req, f, rb_ary_new3(2, el, v));
|
66
|
-
break;
|
67
|
-
default:
|
68
|
-
rb_hash_aset(req, f, v);
|
69
|
-
break;
|
70
|
-
}
|
71
|
-
}
|
72
|
-
|
73
|
-
void client_reason_phrase(void *data, const char *at, size_t length)
|
74
|
-
{
|
75
|
-
VALUE req = (VALUE)data;
|
76
|
-
VALUE v = Qnil;
|
77
|
-
|
78
|
-
v = rb_str_new(at, length);
|
79
|
-
|
80
|
-
rb_ivar_set(req, id_reason, v);
|
81
|
-
}
|
82
|
-
|
83
|
-
void client_status_code(void *data, const char *at, size_t length)
|
84
|
-
{
|
85
|
-
VALUE req = (VALUE)data;
|
86
|
-
VALUE v = Qnil;
|
87
|
-
|
88
|
-
v = rb_str_new(at, length);
|
89
|
-
|
90
|
-
rb_ivar_set(req, id_status, v);
|
91
|
-
}
|
92
|
-
|
93
|
-
void client_http_version(void *data, const char *at, size_t length)
|
94
|
-
{
|
95
|
-
VALUE req = (VALUE)data;
|
96
|
-
VALUE v = Qnil;
|
97
|
-
|
98
|
-
v = rb_str_new(at, length);
|
99
|
-
|
100
|
-
rb_ivar_set(req, id_version, v);
|
101
|
-
}
|
102
|
-
|
103
|
-
/** Finalizes the request header to have a bunch of stuff that's
|
104
|
-
needed. */
|
105
|
-
void client_header_done(void *data, const char *at, size_t length)
|
106
|
-
{
|
107
|
-
VALUE req = (VALUE)data;
|
108
|
-
VALUE v = Qnil;
|
109
|
-
|
110
|
-
v = rb_str_new(at, length);
|
111
|
-
rb_ivar_set(req, id_body, v);
|
112
|
-
}
|
113
|
-
|
114
|
-
void client_chunk_size(void *data, const char *at, size_t length)
|
115
|
-
{
|
116
|
-
VALUE req = (VALUE)data;
|
117
|
-
VALUE v = Qnil;
|
118
|
-
|
119
|
-
if(length <= 0) {
|
120
|
-
rb_raise(eHttpClientParserError, "Chunked Encoding gave <= 0 chunk size.");
|
121
|
-
}
|
122
|
-
|
123
|
-
v = rb_str_new(at, length);
|
124
|
-
|
125
|
-
rb_ivar_set(req, id_chunk_size, v);
|
126
|
-
}
|
127
|
-
|
128
|
-
void client_last_chunk(void *data, const char *at, size_t length) {
|
129
|
-
VALUE req = (VALUE)data;
|
130
|
-
rb_ivar_set(req, id_last_chunk,Qtrue);
|
131
|
-
}
|
132
|
-
|
133
|
-
|
134
|
-
void HttpClientParser_free(void *data) {
|
135
|
-
TRACE();
|
136
|
-
|
137
|
-
if(data) {
|
138
|
-
free(data);
|
139
|
-
}
|
140
|
-
}
|
141
|
-
|
142
|
-
|
143
|
-
VALUE HttpClientParser_alloc(VALUE klass)
|
144
|
-
{
|
145
|
-
VALUE obj;
|
146
|
-
httpclient_parser *hp = ALLOC_N(httpclient_parser, 1);
|
147
|
-
TRACE();
|
148
|
-
hp->http_field = client_http_field;
|
149
|
-
hp->status_code = client_status_code;
|
150
|
-
hp->reason_phrase = client_reason_phrase;
|
151
|
-
hp->http_version = client_http_version;
|
152
|
-
hp->header_done = client_header_done;
|
153
|
-
hp->chunk_size = client_chunk_size;
|
154
|
-
hp->last_chunk = client_last_chunk;
|
155
|
-
httpclient_parser_init(hp);
|
156
|
-
|
157
|
-
obj = Data_Wrap_Struct(klass, NULL, HttpClientParser_free, hp);
|
158
|
-
|
159
|
-
return obj;
|
160
|
-
}
|
161
|
-
|
162
|
-
|
163
|
-
/**
|
164
|
-
* call-seq:
|
165
|
-
* parser.new -> parser
|
166
|
-
*
|
167
|
-
* Creates a new parser.
|
168
|
-
*/
|
169
|
-
VALUE HttpClientParser_init(VALUE self)
|
170
|
-
{
|
171
|
-
httpclient_parser *http = NULL;
|
172
|
-
DATA_GET(self, httpclient_parser, http);
|
173
|
-
httpclient_parser_init(http);
|
174
|
-
|
175
|
-
return self;
|
176
|
-
}
|
177
|
-
|
178
|
-
|
179
|
-
/**
|
180
|
-
* call-seq:
|
181
|
-
* parser.reset -> nil
|
182
|
-
*
|
183
|
-
* Resets the parser to it's initial state so that you can reuse it
|
184
|
-
* rather than making new ones.
|
185
|
-
*/
|
186
|
-
VALUE HttpClientParser_reset(VALUE self)
|
187
|
-
{
|
188
|
-
httpclient_parser *http = NULL;
|
189
|
-
DATA_GET(self, httpclient_parser, http);
|
190
|
-
httpclient_parser_init(http);
|
191
|
-
|
192
|
-
return Qnil;
|
193
|
-
}
|
194
|
-
|
195
|
-
|
196
|
-
/**
|
197
|
-
* call-seq:
|
198
|
-
* parser.finish -> true/false
|
199
|
-
*
|
200
|
-
* Finishes a parser early which could put in a "good" or bad state.
|
201
|
-
* You should call reset after finish it or bad things will happen.
|
202
|
-
*/
|
203
|
-
VALUE HttpClientParser_finish(VALUE self)
|
204
|
-
{
|
205
|
-
httpclient_parser *http = NULL;
|
206
|
-
DATA_GET(self, httpclient_parser, http);
|
207
|
-
httpclient_parser_finish(http);
|
208
|
-
|
209
|
-
return httpclient_parser_is_finished(http) ? Qtrue : Qfalse;
|
210
|
-
}
|
211
|
-
|
212
|
-
|
213
|
-
/**
|
214
|
-
* call-seq:
|
215
|
-
* parser.execute(req_hash, data, start) -> Integer
|
216
|
-
*
|
217
|
-
* Takes a Hash and a String of data, parses the String of data filling in the Hash
|
218
|
-
* returning an Integer to indicate how much of the data has been read. No matter
|
219
|
-
* what the return value, you should call HttpClientParser#finished? and HttpClientParser#error?
|
220
|
-
* to figure out if it's done parsing or there was an error.
|
221
|
-
*
|
222
|
-
* This function now throws an exception when there is a parsing error. This makes
|
223
|
-
* the logic for working with the parser much easier. You can still test for an
|
224
|
-
* error, but now you need to wrap the parser with an exception handling block.
|
225
|
-
*
|
226
|
-
* The third argument allows for parsing a partial request and then continuing
|
227
|
-
* the parsing from that position. It needs all of the original data as well
|
228
|
-
* so you have to append to the data buffer as you read.
|
229
|
-
*/
|
230
|
-
VALUE HttpClientParser_execute(VALUE self, VALUE req_hash, VALUE data, VALUE start)
|
231
|
-
{
|
232
|
-
httpclient_parser *http = NULL;
|
233
|
-
int from = 0;
|
234
|
-
char *dptr = NULL;
|
235
|
-
long dlen = 0;
|
236
|
-
|
237
|
-
REQUIRE_TYPE(req_hash, T_HASH);
|
238
|
-
REQUIRE_TYPE(data, T_STRING);
|
239
|
-
REQUIRE_TYPE(start, T_FIXNUM);
|
240
|
-
|
241
|
-
DATA_GET(self, httpclient_parser, http);
|
242
|
-
|
243
|
-
from = FIX2INT(start);
|
244
|
-
dptr = RSTRING_PTR(data);
|
245
|
-
dlen = RSTRING_LEN(data);
|
246
|
-
|
247
|
-
if(from >= dlen) {
|
248
|
-
rb_raise(eHttpClientParserError, "Requested start is after data buffer end.");
|
249
|
-
} else {
|
250
|
-
http->data = (void *)req_hash;
|
251
|
-
httpclient_parser_execute(http, dptr, dlen, from);
|
252
|
-
|
253
|
-
if(httpclient_parser_has_error(http)) {
|
254
|
-
rb_raise(eHttpClientParserError, "Invalid HTTP format, parsing fails.");
|
255
|
-
} else {
|
256
|
-
return INT2FIX(httpclient_parser_nread(http));
|
257
|
-
}
|
258
|
-
}
|
259
|
-
}
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
/**
|
264
|
-
* call-seq:
|
265
|
-
* parser.error? -> true/false
|
266
|
-
*
|
267
|
-
* Tells you whether the parser is in an error state.
|
268
|
-
*/
|
269
|
-
VALUE HttpClientParser_has_error(VALUE self)
|
270
|
-
{
|
271
|
-
httpclient_parser *http = NULL;
|
272
|
-
DATA_GET(self, httpclient_parser, http);
|
273
|
-
|
274
|
-
return httpclient_parser_has_error(http) ? Qtrue : Qfalse;
|
275
|
-
}
|
276
|
-
|
277
|
-
|
278
|
-
/**
|
279
|
-
* call-seq:
|
280
|
-
* parser.finished? -> true/false
|
281
|
-
*
|
282
|
-
* Tells you whether the parser is finished or not and in a good state.
|
283
|
-
*/
|
284
|
-
VALUE HttpClientParser_is_finished(VALUE self)
|
285
|
-
{
|
286
|
-
httpclient_parser *http = NULL;
|
287
|
-
DATA_GET(self, httpclient_parser, http);
|
288
|
-
|
289
|
-
return httpclient_parser_is_finished(http) ? Qtrue : Qfalse;
|
290
|
-
}
|
291
|
-
|
292
|
-
|
293
|
-
/**
|
294
|
-
* call-seq:
|
295
|
-
* parser.nread -> Integer
|
296
|
-
*
|
297
|
-
* Returns the amount of data processed so far during this processing cycle. It is
|
298
|
-
* set to 0 on initialize or reset calls and is incremented each time execute is called.
|
299
|
-
*/
|
300
|
-
VALUE HttpClientParser_nread(VALUE self)
|
301
|
-
{
|
302
|
-
httpclient_parser *http = NULL;
|
303
|
-
DATA_GET(self, httpclient_parser, http);
|
304
|
-
|
305
|
-
return INT2FIX(http->nread);
|
306
|
-
}
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
void Init_http11_client()
|
311
|
-
{
|
312
|
-
|
313
|
-
mEm = rb_define_module("EventMachine");
|
314
|
-
|
315
|
-
eHttpClientParserError = rb_define_class_under(mEm, "HttpClientParserError", rb_eIOError);
|
316
|
-
|
317
|
-
cHttpClientParser = rb_define_class_under(mEm, "HttpClientParser", rb_cObject);
|
318
|
-
rb_define_alloc_func(cHttpClientParser, HttpClientParser_alloc);
|
319
|
-
rb_define_method(cHttpClientParser, "initialize", HttpClientParser_init,0);
|
320
|
-
rb_define_method(cHttpClientParser, "reset", HttpClientParser_reset,0);
|
321
|
-
rb_define_method(cHttpClientParser, "finish", HttpClientParser_finish,0);
|
322
|
-
rb_define_method(cHttpClientParser, "execute", HttpClientParser_execute,3);
|
323
|
-
rb_define_method(cHttpClientParser, "error?", HttpClientParser_has_error,0);
|
324
|
-
rb_define_method(cHttpClientParser, "finished?", HttpClientParser_is_finished,0);
|
325
|
-
rb_define_method(cHttpClientParser, "nread", HttpClientParser_nread,0);
|
326
|
-
}
|
327
|
-
|
328
|
-
|
@@ -1,418 +0,0 @@
|
|
1
|
-
|
2
|
-
#line 1 "http11_parser.rl"
|
3
|
-
/**
|
4
|
-
* Copyright (c) 2005 Zed A. Shaw
|
5
|
-
* You can redistribute it and/or modify it under the same terms as Ruby.
|
6
|
-
*/
|
7
|
-
|
8
|
-
#include "http11_parser.h"
|
9
|
-
#include <stdio.h>
|
10
|
-
#include <assert.h>
|
11
|
-
#include <stdlib.h>
|
12
|
-
#include <ctype.h>
|
13
|
-
#include <string.h>
|
14
|
-
|
15
|
-
#define LEN(AT, FPC) (FPC - buffer - parser->AT)
|
16
|
-
#define MARK(M,FPC) (parser->M = (FPC) - buffer)
|
17
|
-
#define PTR_TO(F) (buffer + parser->F)
|
18
|
-
#define L(M) fprintf(stderr, "" # M "\n");
|
19
|
-
|
20
|
-
|
21
|
-
/** machine **/
|
22
|
-
|
23
|
-
#line 95 "http11_parser.rl"
|
24
|
-
|
25
|
-
|
26
|
-
/** Data **/
|
27
|
-
|
28
|
-
#line 29 "http11_parser.c"
|
29
|
-
static const char _httpclient_parser_actions[] = {
|
30
|
-
0, 1, 0, 1, 1, 1, 2, 1,
|
31
|
-
3, 1, 4, 1, 5, 1, 7, 1,
|
32
|
-
8, 1, 10, 2, 0, 5, 2, 2,
|
33
|
-
3, 2, 3, 4, 2, 4, 10, 2,
|
34
|
-
6, 0, 2, 8, 10, 2, 9, 10,
|
35
|
-
2, 10, 9, 3, 2, 3, 4, 3,
|
36
|
-
4, 9, 10, 3, 4, 10, 9, 3,
|
37
|
-
6, 0, 5, 3, 8, 10, 9, 4,
|
38
|
-
2, 3, 4, 10, 5, 2, 3, 4,
|
39
|
-
9, 10, 5, 2, 3, 4, 10, 9
|
40
|
-
|
41
|
-
};
|
42
|
-
|
43
|
-
static const short _httpclient_parser_key_offsets[] = {
|
44
|
-
0, 0, 11, 12, 24, 29, 30, 31,
|
45
|
-
43, 58, 80, 95, 116, 131, 153, 168,
|
46
|
-
189, 204, 223, 238, 256, 257, 258, 259,
|
47
|
-
260, 262, 265, 267, 270, 272, 274, 276,
|
48
|
-
279, 281, 298, 314, 317, 319, 320, 322
|
49
|
-
};
|
50
|
-
|
51
|
-
static const char _httpclient_parser_trans_keys[] = {
|
52
|
-
10, 13, 48, 59, 72, 49, 57, 65,
|
53
|
-
70, 97, 102, 10, 10, 13, 32, 59,
|
54
|
-
9, 12, 48, 57, 65, 70, 97, 102,
|
55
|
-
10, 13, 32, 9, 12, 10, 10, 10,
|
56
|
-
13, 32, 59, 9, 12, 48, 57, 65,
|
57
|
-
70, 97, 102, 33, 124, 126, 35, 39,
|
58
|
-
42, 43, 45, 46, 48, 57, 65, 90,
|
59
|
-
94, 122, 10, 13, 32, 33, 59, 61,
|
60
|
-
124, 126, 9, 12, 35, 39, 42, 43,
|
61
|
-
45, 46, 48, 57, 65, 90, 94, 122,
|
62
|
-
33, 124, 126, 35, 39, 42, 43, 45,
|
63
|
-
46, 48, 57, 65, 90, 94, 122, 10,
|
64
|
-
13, 32, 33, 59, 124, 126, 9, 12,
|
65
|
-
35, 39, 42, 43, 45, 46, 48, 57,
|
66
|
-
65, 90, 94, 122, 33, 124, 126, 35,
|
67
|
-
39, 42, 43, 45, 46, 48, 57, 65,
|
68
|
-
90, 94, 122, 10, 13, 32, 33, 59,
|
69
|
-
61, 124, 126, 9, 12, 35, 39, 42,
|
70
|
-
43, 45, 46, 48, 57, 65, 90, 94,
|
71
|
-
122, 33, 124, 126, 35, 39, 42, 43,
|
72
|
-
45, 46, 48, 57, 65, 90, 94, 122,
|
73
|
-
10, 13, 32, 33, 59, 124, 126, 9,
|
74
|
-
12, 35, 39, 42, 43, 45, 46, 48,
|
75
|
-
57, 65, 90, 94, 122, 33, 124, 126,
|
76
|
-
35, 39, 42, 43, 45, 46, 48, 57,
|
77
|
-
65, 90, 94, 122, 10, 13, 33, 59,
|
78
|
-
61, 124, 126, 35, 39, 42, 43, 45,
|
79
|
-
46, 48, 57, 65, 90, 94, 122, 33,
|
80
|
-
124, 126, 35, 39, 42, 43, 45, 46,
|
81
|
-
48, 57, 65, 90, 94, 122, 10, 13,
|
82
|
-
33, 59, 124, 126, 35, 39, 42, 43,
|
83
|
-
45, 46, 48, 57, 65, 90, 94, 122,
|
84
|
-
84, 84, 80, 47, 48, 57, 46, 48,
|
85
|
-
57, 48, 57, 32, 48, 57, 48, 57,
|
86
|
-
48, 57, 48, 57, 10, 13, 32, 10,
|
87
|
-
13, 10, 13, 33, 124, 126, 35, 39,
|
88
|
-
42, 43, 45, 46, 48, 57, 65, 90,
|
89
|
-
94, 122, 33, 58, 124, 126, 35, 39,
|
90
|
-
42, 43, 45, 46, 48, 57, 65, 90,
|
91
|
-
94, 122, 10, 13, 32, 10, 13, 10,
|
92
|
-
10, 13, 0
|
93
|
-
};
|
94
|
-
|
95
|
-
static const char _httpclient_parser_single_lengths[] = {
|
96
|
-
0, 5, 1, 4, 3, 1, 1, 4,
|
97
|
-
3, 8, 3, 7, 3, 8, 3, 7,
|
98
|
-
3, 7, 3, 6, 1, 1, 1, 1,
|
99
|
-
0, 1, 0, 1, 0, 0, 0, 3,
|
100
|
-
2, 5, 4, 3, 2, 1, 2, 0
|
101
|
-
};
|
102
|
-
|
103
|
-
static const char _httpclient_parser_range_lengths[] = {
|
104
|
-
0, 3, 0, 4, 1, 0, 0, 4,
|
105
|
-
6, 7, 6, 7, 6, 7, 6, 7,
|
106
|
-
6, 6, 6, 6, 0, 0, 0, 0,
|
107
|
-
1, 1, 1, 1, 1, 1, 1, 0,
|
108
|
-
0, 6, 6, 0, 0, 0, 0, 0
|
109
|
-
};
|
110
|
-
|
111
|
-
static const short _httpclient_parser_index_offsets[] = {
|
112
|
-
0, 0, 9, 11, 20, 25, 27, 29,
|
113
|
-
38, 48, 64, 74, 89, 99, 115, 125,
|
114
|
-
140, 150, 164, 174, 187, 189, 191, 193,
|
115
|
-
195, 197, 200, 202, 205, 207, 209, 211,
|
116
|
-
215, 218, 230, 241, 245, 248, 250, 253
|
117
|
-
};
|
118
|
-
|
119
|
-
static const char _httpclient_parser_indicies[] = {
|
120
|
-
0, 2, 3, 5, 6, 4, 4, 4,
|
121
|
-
1, 0, 1, 8, 9, 7, 11, 7,
|
122
|
-
10, 10, 10, 1, 13, 14, 12, 12,
|
123
|
-
1, 13, 1, 15, 1, 16, 17, 7,
|
124
|
-
18, 7, 10, 10, 10, 1, 19, 19,
|
125
|
-
19, 19, 19, 19, 19, 19, 19, 1,
|
126
|
-
21, 22, 20, 23, 24, 25, 23, 23,
|
127
|
-
20, 23, 23, 23, 23, 23, 23, 1,
|
128
|
-
26, 26, 26, 26, 26, 26, 26, 26,
|
129
|
-
26, 1, 28, 29, 27, 30, 31, 30,
|
130
|
-
30, 27, 30, 30, 30, 30, 30, 30,
|
131
|
-
1, 32, 32, 32, 32, 32, 32, 32,
|
132
|
-
32, 32, 1, 33, 34, 20, 35, 36,
|
133
|
-
37, 35, 35, 20, 35, 35, 35, 35,
|
134
|
-
35, 35, 1, 38, 38, 38, 38, 38,
|
135
|
-
38, 38, 38, 38, 1, 39, 40, 27,
|
136
|
-
41, 42, 41, 41, 27, 41, 41, 41,
|
137
|
-
41, 41, 41, 1, 43, 43, 43, 43,
|
138
|
-
43, 43, 43, 43, 43, 1, 44, 45,
|
139
|
-
46, 47, 48, 46, 46, 46, 46, 46,
|
140
|
-
46, 46, 46, 1, 49, 49, 49, 49,
|
141
|
-
49, 49, 49, 49, 49, 1, 50, 51,
|
142
|
-
52, 53, 52, 52, 52, 52, 52, 52,
|
143
|
-
52, 52, 1, 54, 1, 55, 1, 56,
|
144
|
-
1, 57, 1, 58, 1, 59, 58, 1,
|
145
|
-
60, 1, 61, 60, 1, 62, 1, 63,
|
146
|
-
1, 64, 1, 66, 67, 68, 65, 70,
|
147
|
-
71, 69, 13, 14, 72, 72, 72, 72,
|
148
|
-
72, 72, 72, 72, 72, 1, 73, 74,
|
149
|
-
73, 73, 73, 73, 73, 73, 73, 73,
|
150
|
-
1, 76, 77, 78, 75, 80, 81, 79,
|
151
|
-
82, 1, 84, 85, 83, 1, 0
|
152
|
-
};
|
153
|
-
|
154
|
-
static const char _httpclient_parser_trans_targs[] = {
|
155
|
-
39, 0, 2, 3, 7, 16, 20, 4,
|
156
|
-
39, 6, 7, 12, 4, 39, 5, 39,
|
157
|
-
39, 5, 8, 9, 4, 39, 5, 9,
|
158
|
-
8, 10, 11, 4, 39, 5, 11, 8,
|
159
|
-
13, 39, 6, 13, 12, 14, 15, 39,
|
160
|
-
6, 15, 12, 17, 39, 2, 17, 16,
|
161
|
-
18, 19, 39, 2, 19, 16, 21, 22,
|
162
|
-
23, 24, 25, 26, 27, 28, 29, 30,
|
163
|
-
31, 32, 33, 37, 38, 32, 33, 37,
|
164
|
-
34, 34, 35, 36, 33, 37, 35, 36,
|
165
|
-
33, 37, 33, 32, 33, 37
|
166
|
-
};
|
167
|
-
|
168
|
-
static const char _httpclient_parser_trans_actions[] = {
|
169
|
-
37, 0, 0, 1, 1, 0, 1, 15,
|
170
|
-
59, 15, 0, 15, 0, 17, 0, 40,
|
171
|
-
34, 15, 15, 3, 43, 63, 43, 0,
|
172
|
-
43, 22, 7, 9, 28, 9, 0, 9,
|
173
|
-
3, 74, 43, 0, 43, 22, 7, 51,
|
174
|
-
9, 0, 9, 3, 68, 43, 0, 43,
|
175
|
-
22, 7, 47, 9, 0, 9, 0, 0,
|
176
|
-
0, 0, 0, 0, 0, 13, 1, 0,
|
177
|
-
0, 31, 55, 55, 31, 0, 11, 11,
|
178
|
-
3, 0, 5, 7, 25, 25, 7, 0,
|
179
|
-
9, 9, 0, 1, 19, 19
|
180
|
-
};
|
181
|
-
|
182
|
-
static const int httpclient_parser_start = 1;
|
183
|
-
static const int httpclient_parser_first_final = 39;
|
184
|
-
static const int httpclient_parser_error = 0;
|
185
|
-
|
186
|
-
static const int httpclient_parser_en_main = 1;
|
187
|
-
|
188
|
-
|
189
|
-
#line 99 "http11_parser.rl"
|
190
|
-
|
191
|
-
int httpclient_parser_init(httpclient_parser *parser) {
|
192
|
-
int cs = 0;
|
193
|
-
|
194
|
-
#line 195 "http11_parser.c"
|
195
|
-
{
|
196
|
-
cs = httpclient_parser_start;
|
197
|
-
}
|
198
|
-
|
199
|
-
#line 103 "http11_parser.rl"
|
200
|
-
parser->cs = cs;
|
201
|
-
parser->body_start = 0;
|
202
|
-
parser->content_len = 0;
|
203
|
-
parser->mark = 0;
|
204
|
-
parser->nread = 0;
|
205
|
-
parser->field_len = 0;
|
206
|
-
parser->field_start = 0;
|
207
|
-
|
208
|
-
return(1);
|
209
|
-
}
|
210
|
-
|
211
|
-
|
212
|
-
/** exec **/
|
213
|
-
size_t httpclient_parser_execute(httpclient_parser *parser, const char *buffer, size_t len, size_t off) {
|
214
|
-
const char *p, *pe;
|
215
|
-
int cs = parser->cs;
|
216
|
-
|
217
|
-
assert(off <= len && "offset past end of buffer");
|
218
|
-
|
219
|
-
p = buffer+off;
|
220
|
-
pe = buffer+len;
|
221
|
-
|
222
|
-
assert(*pe == '\0' && "pointer does not end on NUL");
|
223
|
-
assert(pe - p == len - off && "pointers aren't same distance");
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
#line 228 "http11_parser.c"
|
228
|
-
{
|
229
|
-
int _klen;
|
230
|
-
unsigned int _trans;
|
231
|
-
const char *_acts;
|
232
|
-
unsigned int _nacts;
|
233
|
-
const char *_keys;
|
234
|
-
|
235
|
-
if ( p == pe )
|
236
|
-
goto _test_eof;
|
237
|
-
if ( cs == 0 )
|
238
|
-
goto _out;
|
239
|
-
_resume:
|
240
|
-
_keys = _httpclient_parser_trans_keys + _httpclient_parser_key_offsets[cs];
|
241
|
-
_trans = _httpclient_parser_index_offsets[cs];
|
242
|
-
|
243
|
-
_klen = _httpclient_parser_single_lengths[cs];
|
244
|
-
if ( _klen > 0 ) {
|
245
|
-
const char *_lower = _keys;
|
246
|
-
const char *_mid;
|
247
|
-
const char *_upper = _keys + _klen - 1;
|
248
|
-
while (1) {
|
249
|
-
if ( _upper < _lower )
|
250
|
-
break;
|
251
|
-
|
252
|
-
_mid = _lower + ((_upper-_lower) >> 1);
|
253
|
-
if ( (*p) < *_mid )
|
254
|
-
_upper = _mid - 1;
|
255
|
-
else if ( (*p) > *_mid )
|
256
|
-
_lower = _mid + 1;
|
257
|
-
else {
|
258
|
-
_trans += (_mid - _keys);
|
259
|
-
goto _match;
|
260
|
-
}
|
261
|
-
}
|
262
|
-
_keys += _klen;
|
263
|
-
_trans += _klen;
|
264
|
-
}
|
265
|
-
|
266
|
-
_klen = _httpclient_parser_range_lengths[cs];
|
267
|
-
if ( _klen > 0 ) {
|
268
|
-
const char *_lower = _keys;
|
269
|
-
const char *_mid;
|
270
|
-
const char *_upper = _keys + (_klen<<1) - 2;
|
271
|
-
while (1) {
|
272
|
-
if ( _upper < _lower )
|
273
|
-
break;
|
274
|
-
|
275
|
-
_mid = _lower + (((_upper-_lower) >> 1) & ~1);
|
276
|
-
if ( (*p) < _mid[0] )
|
277
|
-
_upper = _mid - 2;
|
278
|
-
else if ( (*p) > _mid[1] )
|
279
|
-
_lower = _mid + 2;
|
280
|
-
else {
|
281
|
-
_trans += ((_mid - _keys)>>1);
|
282
|
-
goto _match;
|
283
|
-
}
|
284
|
-
}
|
285
|
-
_trans += _klen;
|
286
|
-
}
|
287
|
-
|
288
|
-
_match:
|
289
|
-
_trans = _httpclient_parser_indicies[_trans];
|
290
|
-
cs = _httpclient_parser_trans_targs[_trans];
|
291
|
-
|
292
|
-
if ( _httpclient_parser_trans_actions[_trans] == 0 )
|
293
|
-
goto _again;
|
294
|
-
|
295
|
-
_acts = _httpclient_parser_actions + _httpclient_parser_trans_actions[_trans];
|
296
|
-
_nacts = (unsigned int) *_acts++;
|
297
|
-
while ( _nacts-- > 0 )
|
298
|
-
{
|
299
|
-
switch ( *_acts++ )
|
300
|
-
{
|
301
|
-
case 0:
|
302
|
-
#line 23 "http11_parser.rl"
|
303
|
-
{MARK(mark, p); }
|
304
|
-
break;
|
305
|
-
case 1:
|
306
|
-
#line 25 "http11_parser.rl"
|
307
|
-
{ MARK(field_start, p); }
|
308
|
-
break;
|
309
|
-
case 2:
|
310
|
-
#line 27 "http11_parser.rl"
|
311
|
-
{
|
312
|
-
parser->field_len = LEN(field_start, p);
|
313
|
-
}
|
314
|
-
break;
|
315
|
-
case 3:
|
316
|
-
#line 31 "http11_parser.rl"
|
317
|
-
{ MARK(mark, p); }
|
318
|
-
break;
|
319
|
-
case 4:
|
320
|
-
#line 33 "http11_parser.rl"
|
321
|
-
{
|
322
|
-
parser->http_field(parser->data, PTR_TO(field_start), parser->field_len, PTR_TO(mark), LEN(mark, p));
|
323
|
-
}
|
324
|
-
break;
|
325
|
-
case 5:
|
326
|
-
#line 37 "http11_parser.rl"
|
327
|
-
{
|
328
|
-
parser->reason_phrase(parser->data, PTR_TO(mark), LEN(mark, p));
|
329
|
-
}
|
330
|
-
break;
|
331
|
-
case 6:
|
332
|
-
#line 41 "http11_parser.rl"
|
333
|
-
{
|
334
|
-
parser->status_code(parser->data, PTR_TO(mark), LEN(mark, p));
|
335
|
-
}
|
336
|
-
break;
|
337
|
-
case 7:
|
338
|
-
#line 45 "http11_parser.rl"
|
339
|
-
{
|
340
|
-
parser->http_version(parser->data, PTR_TO(mark), LEN(mark, p));
|
341
|
-
}
|
342
|
-
break;
|
343
|
-
case 8:
|
344
|
-
#line 49 "http11_parser.rl"
|
345
|
-
{
|
346
|
-
parser->chunk_size(parser->data, PTR_TO(mark), LEN(mark, p));
|
347
|
-
}
|
348
|
-
break;
|
349
|
-
case 9:
|
350
|
-
#line 53 "http11_parser.rl"
|
351
|
-
{
|
352
|
-
parser->last_chunk(parser->data, NULL, 0);
|
353
|
-
}
|
354
|
-
break;
|
355
|
-
case 10:
|
356
|
-
#line 57 "http11_parser.rl"
|
357
|
-
{
|
358
|
-
parser->body_start = p - buffer + 1;
|
359
|
-
if(parser->header_done != NULL)
|
360
|
-
parser->header_done(parser->data, p + 1, pe - p - 1);
|
361
|
-
{p++; goto _out; }
|
362
|
-
}
|
363
|
-
break;
|
364
|
-
#line 365 "http11_parser.c"
|
365
|
-
}
|
366
|
-
}
|
367
|
-
|
368
|
-
_again:
|
369
|
-
if ( cs == 0 )
|
370
|
-
goto _out;
|
371
|
-
if ( ++p != pe )
|
372
|
-
goto _resume;
|
373
|
-
_test_eof: {}
|
374
|
-
_out: {}
|
375
|
-
}
|
376
|
-
|
377
|
-
#line 130 "http11_parser.rl"
|
378
|
-
|
379
|
-
parser->cs = cs;
|
380
|
-
parser->nread += p - (buffer + off);
|
381
|
-
|
382
|
-
assert(p <= pe && "buffer overflow after parsing execute");
|
383
|
-
assert(parser->nread <= len && "nread longer than length");
|
384
|
-
assert(parser->body_start <= len && "body starts after buffer end");
|
385
|
-
assert(parser->mark < len && "mark is after buffer end");
|
386
|
-
assert(parser->field_len <= len && "field has length longer than whole buffer");
|
387
|
-
assert(parser->field_start < len && "field starts after buffer end");
|
388
|
-
|
389
|
-
if(parser->body_start) {
|
390
|
-
/* final \r\n combo encountered so stop right here */
|
391
|
-
parser->nread = parser->body_start;
|
392
|
-
}
|
393
|
-
|
394
|
-
return(parser->nread);
|
395
|
-
}
|
396
|
-
|
397
|
-
int httpclient_parser_finish(httpclient_parser *parser)
|
398
|
-
{
|
399
|
-
int cs = parser->cs;
|
400
|
-
|
401
|
-
parser->cs = cs;
|
402
|
-
|
403
|
-
if (httpclient_parser_has_error(parser) ) {
|
404
|
-
return -1;
|
405
|
-
} else if (httpclient_parser_is_finished(parser) ) {
|
406
|
-
return 1;
|
407
|
-
} else {
|
408
|
-
return 0;
|
409
|
-
}
|
410
|
-
}
|
411
|
-
|
412
|
-
int httpclient_parser_has_error(httpclient_parser *parser) {
|
413
|
-
return parser->cs == httpclient_parser_error;
|
414
|
-
}
|
415
|
-
|
416
|
-
int httpclient_parser_is_finished(httpclient_parser *parser) {
|
417
|
-
return parser->cs == httpclient_parser_first_final;
|
418
|
-
}
|