mirror of
https://github.com/puma/puma.git
synced 2022-11-09 13:48:40 -05:00
Start cleanup and modernization
This commit is contained in:
parent
812ce631df
commit
f748edfade
11 changed files with 293 additions and 324 deletions
2
Rakefile
2
Rakefile
|
@ -4,5 +4,7 @@
|
|||
# Thank You.
|
||||
#
|
||||
|
||||
require 'rubygems'
|
||||
|
||||
# load rakefile extensions (tasks)
|
||||
Dir['tasks/*.rake'].sort.each { |f| load f }
|
||||
|
|
|
@ -8,12 +8,7 @@
|
|||
#include <string.h>
|
||||
#include "http11_parser.h"
|
||||
|
||||
#ifndef RSTRING_PTR
|
||||
#define RSTRING_PTR(s) (RSTRING(s)->ptr)
|
||||
#endif
|
||||
#ifndef RSTRING_LEN
|
||||
#define RSTRING_LEN(s) (RSTRING(s)->len)
|
||||
#endif
|
||||
#ifndef MANAGED_STRINGS
|
||||
|
||||
#ifndef RSTRING_PTR
|
||||
#define RSTRING_PTR(s) (RSTRING(s)->ptr)
|
||||
|
@ -22,8 +17,11 @@
|
|||
#define RSTRING_LEN(s) (RSTRING(s)->len)
|
||||
#endif
|
||||
|
||||
static VALUE mMongrel;
|
||||
static VALUE cHttpParser;
|
||||
#define rb_extract_chars(e, sz) (*sz = RSTRING_LEN(e), RSTRING_PTR(e))
|
||||
#define rb_free_chars(e) /* nothing */
|
||||
|
||||
#endif
|
||||
|
||||
static VALUE eHttpParserError;
|
||||
|
||||
#define id_handler_map rb_intern("@handler_map")
|
||||
|
@ -36,21 +34,7 @@ static VALUE global_request_uri;
|
|||
static VALUE global_fragment;
|
||||
static VALUE global_query_string;
|
||||
static VALUE global_http_version;
|
||||
static VALUE global_content_length;
|
||||
static VALUE global_http_content_length;
|
||||
static VALUE global_request_path;
|
||||
static VALUE global_content_type;
|
||||
static VALUE global_http_content_type;
|
||||
static VALUE global_gateway_interface;
|
||||
static VALUE global_gateway_interface_value;
|
||||
static VALUE global_server_name;
|
||||
static VALUE global_server_port;
|
||||
static VALUE global_server_protocol;
|
||||
static VALUE global_server_protocol_value;
|
||||
static VALUE global_http_host;
|
||||
static VALUE global_mongrel_version;
|
||||
static VALUE global_server_software;
|
||||
static VALUE global_port_80;
|
||||
|
||||
#define TRIE_INCREASE 30
|
||||
|
||||
|
@ -61,7 +45,7 @@ static VALUE global_port_80;
|
|||
#define VALIDATE_MAX_LENGTH(len, N) if(len > MAX_##N##_LENGTH) { rb_raise(eHttpParserError, MAX_##N##_LENGTH_ERR); }
|
||||
|
||||
/** Defines global strings in the init method. */
|
||||
#define DEF_GLOBAL(N, val) global_##N = rb_obj_freeze(rb_str_new2(val)); rb_global_variable(&global_##N)
|
||||
#define DEF_GLOBAL(N, val) global_##N = rb_str_new2(val); rb_global_variable(&global_##N)
|
||||
|
||||
|
||||
/* Defines the maximum allowed lengths for various input elements.*/
|
||||
|
@ -149,7 +133,7 @@ static void init_common_fields(void)
|
|||
|
||||
for(i = 0; i < ARRAY_SIZE(common_http_fields); cf++, i++) {
|
||||
memcpy(tmp + HTTP_PREFIX_LEN, cf->name, cf->len + 1);
|
||||
cf->value = rb_obj_freeze(rb_str_new(tmp, HTTP_PREFIX_LEN + cf->len));
|
||||
cf->value = rb_str_new(tmp, HTTP_PREFIX_LEN + cf->len);
|
||||
rb_global_variable(&cf->value);
|
||||
}
|
||||
|
||||
|
@ -184,9 +168,9 @@ static VALUE find_common_field_value(const char *field, size_t flen)
|
|||
#endif /* !HAVE_QSORT_BSEARCH */
|
||||
}
|
||||
|
||||
void http_field(void *data, const char *field, size_t flen, const char *value, size_t vlen)
|
||||
void http_field(http_parser* hp, const char *field, size_t flen,
|
||||
const char *value, size_t vlen)
|
||||
{
|
||||
VALUE req = (VALUE)data;
|
||||
VALUE v = Qnil;
|
||||
VALUE f = Qnil;
|
||||
|
||||
|
@ -201,122 +185,83 @@ void http_field(void *data, const char *field, size_t flen, const char *value, s
|
|||
/*
|
||||
* We got a strange header that we don't have a memoized value for.
|
||||
* Fallback to creating a new string to use as a hash key.
|
||||
*
|
||||
* using rb_str_new(NULL, len) here is faster than rb_str_buf_new(len)
|
||||
* in my testing, because: there's no minimum allocation length (and
|
||||
* no check for it, either), RSTRING_LEN(f) does not need to be
|
||||
* written twice, and and RSTRING_PTR(f) will already be
|
||||
* null-terminated for us.
|
||||
*/
|
||||
f = rb_str_new(NULL, HTTP_PREFIX_LEN + flen);
|
||||
memcpy(RSTRING_PTR(f), HTTP_PREFIX, HTTP_PREFIX_LEN);
|
||||
memcpy(RSTRING_PTR(f) + HTTP_PREFIX_LEN, field, flen);
|
||||
assert(*(RSTRING_PTR(f) + RSTRING_LEN(f)) == '\0'); /* paranoia */
|
||||
/* fprintf(stderr, "UNKNOWN HEADER <%s>\n", RSTRING_PTR(f)); */
|
||||
|
||||
size_t new_size = HTTP_PREFIX_LEN + flen;
|
||||
assert(new_size < BUFFER_LEN);
|
||||
|
||||
memcpy(hp->buf, HTTP_PREFIX, HTTP_PREFIX_LEN);
|
||||
memcpy(hp->buf + HTTP_PREFIX_LEN, field, flen);
|
||||
|
||||
f = rb_str_new(hp->buf, new_size);
|
||||
}
|
||||
|
||||
rb_hash_aset(req, f, v);
|
||||
rb_hash_aset(hp->request, f, v);
|
||||
}
|
||||
|
||||
void request_method(void *data, const char *at, size_t length)
|
||||
void request_method(http_parser* hp, const char *at, size_t length)
|
||||
{
|
||||
VALUE req = (VALUE)data;
|
||||
VALUE val = Qnil;
|
||||
|
||||
val = rb_str_new(at, length);
|
||||
rb_hash_aset(req, global_request_method, val);
|
||||
rb_hash_aset(hp->request, global_request_method, val);
|
||||
}
|
||||
|
||||
void request_uri(void *data, const char *at, size_t length)
|
||||
void request_uri(http_parser* hp, const char *at, size_t length)
|
||||
{
|
||||
VALUE req = (VALUE)data;
|
||||
VALUE val = Qnil;
|
||||
|
||||
VALIDATE_MAX_LENGTH(length, REQUEST_URI);
|
||||
|
||||
val = rb_str_new(at, length);
|
||||
rb_hash_aset(req, global_request_uri, val);
|
||||
rb_hash_aset(hp->request, global_request_uri, val);
|
||||
}
|
||||
|
||||
void fragment(void *data, const char *at, size_t length)
|
||||
void fragment(http_parser* hp, const char *at, size_t length)
|
||||
{
|
||||
VALUE req = (VALUE)data;
|
||||
VALUE val = Qnil;
|
||||
|
||||
VALIDATE_MAX_LENGTH(length, FRAGMENT);
|
||||
|
||||
val = rb_str_new(at, length);
|
||||
rb_hash_aset(req, global_fragment, val);
|
||||
rb_hash_aset(hp->request, global_fragment, val);
|
||||
}
|
||||
|
||||
void request_path(void *data, const char *at, size_t length)
|
||||
void request_path(http_parser* hp, const char *at, size_t length)
|
||||
{
|
||||
VALUE req = (VALUE)data;
|
||||
VALUE val = Qnil;
|
||||
|
||||
VALIDATE_MAX_LENGTH(length, REQUEST_PATH);
|
||||
|
||||
val = rb_str_new(at, length);
|
||||
rb_hash_aset(req, global_request_path, val);
|
||||
rb_hash_aset(hp->request, global_request_path, val);
|
||||
}
|
||||
|
||||
void query_string(void *data, const char *at, size_t length)
|
||||
void query_string(http_parser* hp, const char *at, size_t length)
|
||||
{
|
||||
VALUE req = (VALUE)data;
|
||||
VALUE val = Qnil;
|
||||
|
||||
VALIDATE_MAX_LENGTH(length, QUERY_STRING);
|
||||
|
||||
val = rb_str_new(at, length);
|
||||
rb_hash_aset(req, global_query_string, val);
|
||||
rb_hash_aset(hp->request, global_query_string, val);
|
||||
}
|
||||
|
||||
void http_version(void *data, const char *at, size_t length)
|
||||
void http_version(http_parser* hp, const char *at, size_t length)
|
||||
{
|
||||
VALUE req = (VALUE)data;
|
||||
VALUE val = rb_str_new(at, length);
|
||||
rb_hash_aset(req, global_http_version, val);
|
||||
rb_hash_aset(hp->request, global_http_version, val);
|
||||
}
|
||||
|
||||
/** Finalizes the request header to have a bunch of stuff that's
|
||||
needed. */
|
||||
|
||||
void header_done(void *data, const char *at, size_t length)
|
||||
void header_done(http_parser* hp, const char *at, size_t length)
|
||||
{
|
||||
VALUE req = (VALUE)data;
|
||||
VALUE temp = Qnil;
|
||||
VALUE ctype = Qnil;
|
||||
VALUE clen = Qnil;
|
||||
char *colon = NULL;
|
||||
|
||||
clen = rb_hash_aref(req, global_http_content_length);
|
||||
if(clen != Qnil) {
|
||||
rb_hash_aset(req, global_content_length, clen);
|
||||
}
|
||||
|
||||
ctype = rb_hash_aref(req, global_http_content_type);
|
||||
if(ctype != Qnil) {
|
||||
rb_hash_aset(req, global_content_type, ctype);
|
||||
}
|
||||
|
||||
rb_hash_aset(req, global_gateway_interface, global_gateway_interface_value);
|
||||
if((temp = rb_hash_aref(req, global_http_host)) != Qnil) {
|
||||
colon = memchr(RSTRING_PTR(temp), ':', RSTRING_LEN(temp));
|
||||
if(colon != NULL) {
|
||||
rb_hash_aset(req, global_server_name, rb_str_substr(temp, 0, colon - RSTRING_PTR(temp)));
|
||||
rb_hash_aset(req, global_server_port,
|
||||
rb_str_substr(temp, colon - RSTRING_PTR(temp)+1,
|
||||
RSTRING_LEN(temp)));
|
||||
} else {
|
||||
rb_hash_aset(req, global_server_name, temp);
|
||||
rb_hash_aset(req, global_server_port, global_port_80);
|
||||
}
|
||||
}
|
||||
VALUE req = hp->request;
|
||||
|
||||
/* grab the initial body and stuff it into an ivar */
|
||||
rb_ivar_set(req, id_http_body, rb_str_new(at, length));
|
||||
rb_hash_aset(req, global_server_protocol, global_server_protocol_value);
|
||||
rb_hash_aset(req, global_server_software, global_mongrel_version);
|
||||
}
|
||||
|
||||
|
||||
|
@ -328,10 +273,12 @@ void HttpParser_free(void *data) {
|
|||
}
|
||||
}
|
||||
|
||||
void HttpParser_mark(http_parser* hp) {
|
||||
if(hp->request) rb_gc_mark(hp->request);
|
||||
}
|
||||
|
||||
VALUE HttpParser_alloc(VALUE klass)
|
||||
{
|
||||
VALUE obj;
|
||||
http_parser *hp = ALLOC_N(http_parser, 1);
|
||||
TRACE();
|
||||
hp->http_field = http_field;
|
||||
|
@ -342,14 +289,13 @@ VALUE HttpParser_alloc(VALUE klass)
|
|||
hp->query_string = query_string;
|
||||
hp->http_version = http_version;
|
||||
hp->header_done = header_done;
|
||||
hp->request = Qnil;
|
||||
|
||||
http_parser_init(hp);
|
||||
|
||||
obj = Data_Wrap_Struct(klass, NULL, HttpParser_free, hp);
|
||||
|
||||
return obj;
|
||||
return Data_Wrap_Struct(klass, HttpParser_mark, HttpParser_free, hp);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* call-seq:
|
||||
* parser.new -> parser
|
||||
|
@ -427,15 +373,16 @@ VALUE HttpParser_execute(VALUE self, VALUE req_hash, VALUE data, VALUE start)
|
|||
DATA_GET(self, http_parser, http);
|
||||
|
||||
from = FIX2INT(start);
|
||||
dptr = RSTRING_PTR(data);
|
||||
dlen = RSTRING_LEN(data);
|
||||
dptr = rb_extract_chars(data, &dlen);
|
||||
|
||||
if(from >= dlen) {
|
||||
rb_free_chars(dptr);
|
||||
rb_raise(eHttpParserError, "Requested start is after data buffer end.");
|
||||
} else {
|
||||
http->data = (void *)req_hash;
|
||||
http->request = req_hash;
|
||||
http_parser_execute(http, dptr, dlen, from);
|
||||
|
||||
rb_free_chars(dptr);
|
||||
VALIDATE_MAX_LENGTH(http_parser_nread(http), HEADER);
|
||||
|
||||
if(http_parser_has_error(http)) {
|
||||
|
@ -496,7 +443,7 @@ VALUE HttpParser_nread(VALUE self)
|
|||
void Init_http11()
|
||||
{
|
||||
|
||||
mMongrel = rb_define_module("Mongrel");
|
||||
VALUE mMongrel = rb_define_module("Mongrel");
|
||||
|
||||
DEF_GLOBAL(request_method, "REQUEST_METHOD");
|
||||
DEF_GLOBAL(request_uri, "REQUEST_URI");
|
||||
|
@ -504,24 +451,11 @@ void Init_http11()
|
|||
DEF_GLOBAL(query_string, "QUERY_STRING");
|
||||
DEF_GLOBAL(http_version, "HTTP_VERSION");
|
||||
DEF_GLOBAL(request_path, "REQUEST_PATH");
|
||||
DEF_GLOBAL(content_length, "CONTENT_LENGTH");
|
||||
DEF_GLOBAL(http_content_length, "HTTP_CONTENT_LENGTH");
|
||||
DEF_GLOBAL(content_type, "CONTENT_TYPE");
|
||||
DEF_GLOBAL(http_content_type, "HTTP_CONTENT_TYPE");
|
||||
DEF_GLOBAL(gateway_interface, "GATEWAY_INTERFACE");
|
||||
DEF_GLOBAL(gateway_interface_value, "CGI/1.2");
|
||||
DEF_GLOBAL(server_name, "SERVER_NAME");
|
||||
DEF_GLOBAL(server_port, "SERVER_PORT");
|
||||
DEF_GLOBAL(server_protocol, "SERVER_PROTOCOL");
|
||||
DEF_GLOBAL(server_protocol_value, "HTTP/1.1");
|
||||
DEF_GLOBAL(http_host, "HTTP_HOST");
|
||||
DEF_GLOBAL(mongrel_version, "Mongrel 1.2.0.beta.1"); /* XXX Why is this defined here? */
|
||||
DEF_GLOBAL(server_software, "SERVER_SOFTWARE");
|
||||
DEF_GLOBAL(port_80, "80");
|
||||
|
||||
eHttpParserError = rb_define_class_under(mMongrel, "HttpParserError", rb_eIOError);
|
||||
rb_global_variable(&eHttpParserError);
|
||||
|
||||
cHttpParser = rb_define_class_under(mMongrel, "HttpParser", rb_cObject);
|
||||
VALUE cHttpParser = rb_define_class_under(mMongrel, "HttpParser", rb_cObject);
|
||||
rb_define_alloc_func(cHttpParser, HttpParser_alloc);
|
||||
rb_define_method(cHttpParser, "initialize", HttpParser_init,0);
|
||||
rb_define_method(cHttpParser, "reset", HttpParser_reset,0);
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
|
||||
#line 1 "ext/http11/http11_parser.rl"
|
||||
/**
|
||||
* Copyright (c) 2005 Zed A. Shaw
|
||||
|
@ -28,37 +29,41 @@ static void snake_upcase_char(char *c)
|
|||
|
||||
/** Machine **/
|
||||
|
||||
#line 87 "ext/http11/http11_parser.rl"
|
||||
|
||||
#line 78 "ext/http11/http11_parser.rl"
|
||||
|
||||
|
||||
/** Data **/
|
||||
|
||||
#line 37 "ext/http11/http11_parser.c"
|
||||
#line 39 "ext/http11/http11_parser.c"
|
||||
static const int http_parser_start = 1;
|
||||
static const int http_parser_first_final = 57;
|
||||
static const int http_parser_error = 0;
|
||||
|
||||
static const int http_parser_en_main = 1;
|
||||
|
||||
#line 91 "ext/http11/http11_parser.rl"
|
||||
|
||||
#line 82 "ext/http11/http11_parser.rl"
|
||||
|
||||
int http_parser_init(http_parser *parser) {
|
||||
int cs = 0;
|
||||
|
||||
#line 49 "ext/http11/http11_parser.c"
|
||||
#line 52 "ext/http11/http11_parser.c"
|
||||
{
|
||||
cs = http_parser_start;
|
||||
}
|
||||
#line 95 "ext/http11/http11_parser.rl"
|
||||
|
||||
#line 86 "ext/http11/http11_parser.rl"
|
||||
parser->cs = cs;
|
||||
parser->body_start = 0;
|
||||
parser->content_len = 0;
|
||||
parser->mark = 0;
|
||||
parser->nread = 0;
|
||||
parser->field_len = 0;
|
||||
parser->field_start = 0;
|
||||
parser->field_start = 0;
|
||||
parser->request = Qnil;
|
||||
|
||||
return(1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
@ -76,7 +81,7 @@ size_t http_parser_execute(http_parser *parser, const char *buffer, size_t len,
|
|||
assert(pe - p == len - off && "pointers aren't same distance");
|
||||
|
||||
|
||||
#line 80 "ext/http11/http11_parser.c"
|
||||
#line 85 "ext/http11/http11_parser.c"
|
||||
{
|
||||
if ( p == pe )
|
||||
goto _test_eof;
|
||||
|
@ -101,13 +106,13 @@ cs = 0;
|
|||
goto _out;
|
||||
tr0:
|
||||
#line 34 "ext/http11/http11_parser.rl"
|
||||
{MARK(mark, p); }
|
||||
{ MARK(mark, p); }
|
||||
goto st2;
|
||||
st2:
|
||||
if ( ++p == pe )
|
||||
goto _test_eof2;
|
||||
case 2:
|
||||
#line 111 "ext/http11/http11_parser.c"
|
||||
#line 116 "ext/http11/http11_parser.c"
|
||||
switch( (*p) ) {
|
||||
case 32: goto tr2;
|
||||
case 36: goto st38;
|
||||
|
@ -123,17 +128,16 @@ case 2:
|
|||
goto st38;
|
||||
goto st0;
|
||||
tr2:
|
||||
#line 49 "ext/http11/http11_parser.rl"
|
||||
#line 47 "ext/http11/http11_parser.rl"
|
||||
{
|
||||
if(parser->request_method != NULL)
|
||||
parser->request_method(parser->data, PTR_TO(mark), LEN(mark, p));
|
||||
parser->request_method(parser, PTR_TO(mark), LEN(mark, p));
|
||||
}
|
||||
goto st3;
|
||||
st3:
|
||||
if ( ++p == pe )
|
||||
goto _test_eof3;
|
||||
case 3:
|
||||
#line 137 "ext/http11/http11_parser.c"
|
||||
#line 141 "ext/http11/http11_parser.c"
|
||||
switch( (*p) ) {
|
||||
case 42: goto tr4;
|
||||
case 43: goto tr5;
|
||||
|
@ -151,96 +155,87 @@ case 3:
|
|||
goto st0;
|
||||
tr4:
|
||||
#line 34 "ext/http11/http11_parser.rl"
|
||||
{MARK(mark, p); }
|
||||
{ MARK(mark, p); }
|
||||
goto st4;
|
||||
st4:
|
||||
if ( ++p == pe )
|
||||
goto _test_eof4;
|
||||
case 4:
|
||||
#line 161 "ext/http11/http11_parser.c"
|
||||
#line 165 "ext/http11/http11_parser.c"
|
||||
switch( (*p) ) {
|
||||
case 32: goto tr8;
|
||||
case 35: goto tr9;
|
||||
}
|
||||
goto st0;
|
||||
tr8:
|
||||
#line 53 "ext/http11/http11_parser.rl"
|
||||
#line 50 "ext/http11/http11_parser.rl"
|
||||
{
|
||||
if(parser->request_uri != NULL)
|
||||
parser->request_uri(parser->data, PTR_TO(mark), LEN(mark, p));
|
||||
parser->request_uri(parser, PTR_TO(mark), LEN(mark, p));
|
||||
}
|
||||
goto st5;
|
||||
tr31:
|
||||
#line 34 "ext/http11/http11_parser.rl"
|
||||
{MARK(mark, p); }
|
||||
#line 57 "ext/http11/http11_parser.rl"
|
||||
{ MARK(mark, p); }
|
||||
#line 53 "ext/http11/http11_parser.rl"
|
||||
{
|
||||
if(parser->fragment != NULL)
|
||||
parser->fragment(parser->data, PTR_TO(mark), LEN(mark, p));
|
||||
parser->fragment(parser, PTR_TO(mark), LEN(mark, p));
|
||||
}
|
||||
goto st5;
|
||||
tr34:
|
||||
#line 57 "ext/http11/http11_parser.rl"
|
||||
#line 53 "ext/http11/http11_parser.rl"
|
||||
{
|
||||
if(parser->fragment != NULL)
|
||||
parser->fragment(parser->data, PTR_TO(mark), LEN(mark, p));
|
||||
parser->fragment(parser, PTR_TO(mark), LEN(mark, p));
|
||||
}
|
||||
goto st5;
|
||||
tr42:
|
||||
#line 73 "ext/http11/http11_parser.rl"
|
||||
#line 66 "ext/http11/http11_parser.rl"
|
||||
{
|
||||
if(parser->request_path != NULL)
|
||||
parser->request_path(parser->data, PTR_TO(mark), LEN(mark,p));
|
||||
parser->request_path(parser, PTR_TO(mark), LEN(mark,p));
|
||||
}
|
||||
#line 53 "ext/http11/http11_parser.rl"
|
||||
#line 50 "ext/http11/http11_parser.rl"
|
||||
{
|
||||
if(parser->request_uri != NULL)
|
||||
parser->request_uri(parser->data, PTR_TO(mark), LEN(mark, p));
|
||||
parser->request_uri(parser, PTR_TO(mark), LEN(mark, p));
|
||||
}
|
||||
goto st5;
|
||||
tr53:
|
||||
#line 62 "ext/http11/http11_parser.rl"
|
||||
{MARK(query_start, p); }
|
||||
#line 63 "ext/http11/http11_parser.rl"
|
||||
#line 57 "ext/http11/http11_parser.rl"
|
||||
{ MARK(query_start, p); }
|
||||
#line 58 "ext/http11/http11_parser.rl"
|
||||
{
|
||||
if(parser->query_string != NULL)
|
||||
parser->query_string(parser->data, PTR_TO(query_start), LEN(query_start, p));
|
||||
parser->query_string(parser, PTR_TO(query_start), LEN(query_start, p));
|
||||
}
|
||||
#line 53 "ext/http11/http11_parser.rl"
|
||||
#line 50 "ext/http11/http11_parser.rl"
|
||||
{
|
||||
if(parser->request_uri != NULL)
|
||||
parser->request_uri(parser->data, PTR_TO(mark), LEN(mark, p));
|
||||
parser->request_uri(parser, PTR_TO(mark), LEN(mark, p));
|
||||
}
|
||||
goto st5;
|
||||
tr57:
|
||||
#line 63 "ext/http11/http11_parser.rl"
|
||||
#line 58 "ext/http11/http11_parser.rl"
|
||||
{
|
||||
if(parser->query_string != NULL)
|
||||
parser->query_string(parser->data, PTR_TO(query_start), LEN(query_start, p));
|
||||
parser->query_string(parser, PTR_TO(query_start), LEN(query_start, p));
|
||||
}
|
||||
#line 53 "ext/http11/http11_parser.rl"
|
||||
#line 50 "ext/http11/http11_parser.rl"
|
||||
{
|
||||
if(parser->request_uri != NULL)
|
||||
parser->request_uri(parser->data, PTR_TO(mark), LEN(mark, p));
|
||||
parser->request_uri(parser, PTR_TO(mark), LEN(mark, p));
|
||||
}
|
||||
goto st5;
|
||||
st5:
|
||||
if ( ++p == pe )
|
||||
goto _test_eof5;
|
||||
case 5:
|
||||
#line 232 "ext/http11/http11_parser.c"
|
||||
#line 227 "ext/http11/http11_parser.c"
|
||||
if ( (*p) == 72 )
|
||||
goto tr10;
|
||||
goto st0;
|
||||
tr10:
|
||||
#line 34 "ext/http11/http11_parser.rl"
|
||||
{MARK(mark, p); }
|
||||
{ MARK(mark, p); }
|
||||
goto st6;
|
||||
st6:
|
||||
if ( ++p == pe )
|
||||
goto _test_eof6;
|
||||
case 6:
|
||||
#line 244 "ext/http11/http11_parser.c"
|
||||
#line 239 "ext/http11/http11_parser.c"
|
||||
if ( (*p) == 84 )
|
||||
goto st7;
|
||||
goto st0;
|
||||
|
@ -298,10 +293,9 @@ case 13:
|
|||
goto st13;
|
||||
goto st0;
|
||||
tr18:
|
||||
#line 68 "ext/http11/http11_parser.rl"
|
||||
#line 62 "ext/http11/http11_parser.rl"
|
||||
{
|
||||
if(parser->http_version != NULL)
|
||||
parser->http_version(parser->data, PTR_TO(mark), LEN(mark, p));
|
||||
parser->http_version(parser, PTR_TO(mark), LEN(mark, p));
|
||||
}
|
||||
goto st14;
|
||||
tr26:
|
||||
|
@ -309,24 +303,20 @@ tr26:
|
|||
{ MARK(mark, p); }
|
||||
#line 44 "ext/http11/http11_parser.rl"
|
||||
{
|
||||
if(parser->http_field != NULL) {
|
||||
parser->http_field(parser->data, PTR_TO(field_start), parser->field_len, PTR_TO(mark), LEN(mark, p));
|
||||
}
|
||||
parser->http_field(parser, PTR_TO(field_start), parser->field_len, PTR_TO(mark), LEN(mark, p));
|
||||
}
|
||||
goto st14;
|
||||
tr29:
|
||||
#line 44 "ext/http11/http11_parser.rl"
|
||||
{
|
||||
if(parser->http_field != NULL) {
|
||||
parser->http_field(parser->data, PTR_TO(field_start), parser->field_len, PTR_TO(mark), LEN(mark, p));
|
||||
}
|
||||
parser->http_field(parser, PTR_TO(field_start), parser->field_len, PTR_TO(mark), LEN(mark, p));
|
||||
}
|
||||
goto st14;
|
||||
st14:
|
||||
if ( ++p == pe )
|
||||
goto _test_eof14;
|
||||
case 14:
|
||||
#line 330 "ext/http11/http11_parser.c"
|
||||
#line 320 "ext/http11/http11_parser.c"
|
||||
if ( (*p) == 10 )
|
||||
goto st15;
|
||||
goto st0;
|
||||
|
@ -366,11 +356,10 @@ case 16:
|
|||
goto tr22;
|
||||
goto st0;
|
||||
tr22:
|
||||
#line 78 "ext/http11/http11_parser.rl"
|
||||
#line 70 "ext/http11/http11_parser.rl"
|
||||
{
|
||||
parser->body_start = p - buffer + 1;
|
||||
if(parser->header_done != NULL)
|
||||
parser->header_done(parser->data, p + 1, pe - p - 1);
|
||||
parser->header_done(parser, p + 1, pe - p - 1);
|
||||
{p++; cs = 57; goto _out;}
|
||||
}
|
||||
goto st57;
|
||||
|
@ -378,7 +367,7 @@ st57:
|
|||
if ( ++p == pe )
|
||||
goto _test_eof57;
|
||||
case 57:
|
||||
#line 382 "ext/http11/http11_parser.c"
|
||||
#line 371 "ext/http11/http11_parser.c"
|
||||
goto st0;
|
||||
tr21:
|
||||
#line 37 "ext/http11/http11_parser.rl"
|
||||
|
@ -394,7 +383,7 @@ st17:
|
|||
if ( ++p == pe )
|
||||
goto _test_eof17;
|
||||
case 17:
|
||||
#line 398 "ext/http11/http11_parser.c"
|
||||
#line 387 "ext/http11/http11_parser.c"
|
||||
switch( (*p) ) {
|
||||
case 33: goto tr23;
|
||||
case 58: goto tr24;
|
||||
|
@ -433,7 +422,7 @@ st18:
|
|||
if ( ++p == pe )
|
||||
goto _test_eof18;
|
||||
case 18:
|
||||
#line 437 "ext/http11/http11_parser.c"
|
||||
#line 426 "ext/http11/http11_parser.c"
|
||||
switch( (*p) ) {
|
||||
case 13: goto tr26;
|
||||
case 32: goto tr27;
|
||||
|
@ -447,60 +436,53 @@ st19:
|
|||
if ( ++p == pe )
|
||||
goto _test_eof19;
|
||||
case 19:
|
||||
#line 451 "ext/http11/http11_parser.c"
|
||||
#line 440 "ext/http11/http11_parser.c"
|
||||
if ( (*p) == 13 )
|
||||
goto tr29;
|
||||
goto st19;
|
||||
tr9:
|
||||
#line 53 "ext/http11/http11_parser.rl"
|
||||
#line 50 "ext/http11/http11_parser.rl"
|
||||
{
|
||||
if(parser->request_uri != NULL)
|
||||
parser->request_uri(parser->data, PTR_TO(mark), LEN(mark, p));
|
||||
parser->request_uri(parser, PTR_TO(mark), LEN(mark, p));
|
||||
}
|
||||
goto st20;
|
||||
tr43:
|
||||
#line 73 "ext/http11/http11_parser.rl"
|
||||
#line 66 "ext/http11/http11_parser.rl"
|
||||
{
|
||||
if(parser->request_path != NULL)
|
||||
parser->request_path(parser->data, PTR_TO(mark), LEN(mark,p));
|
||||
parser->request_path(parser, PTR_TO(mark), LEN(mark,p));
|
||||
}
|
||||
#line 53 "ext/http11/http11_parser.rl"
|
||||
#line 50 "ext/http11/http11_parser.rl"
|
||||
{
|
||||
if(parser->request_uri != NULL)
|
||||
parser->request_uri(parser->data, PTR_TO(mark), LEN(mark, p));
|
||||
parser->request_uri(parser, PTR_TO(mark), LEN(mark, p));
|
||||
}
|
||||
goto st20;
|
||||
tr54:
|
||||
#line 62 "ext/http11/http11_parser.rl"
|
||||
{MARK(query_start, p); }
|
||||
#line 63 "ext/http11/http11_parser.rl"
|
||||
#line 57 "ext/http11/http11_parser.rl"
|
||||
{ MARK(query_start, p); }
|
||||
#line 58 "ext/http11/http11_parser.rl"
|
||||
{
|
||||
if(parser->query_string != NULL)
|
||||
parser->query_string(parser->data, PTR_TO(query_start), LEN(query_start, p));
|
||||
parser->query_string(parser, PTR_TO(query_start), LEN(query_start, p));
|
||||
}
|
||||
#line 53 "ext/http11/http11_parser.rl"
|
||||
#line 50 "ext/http11/http11_parser.rl"
|
||||
{
|
||||
if(parser->request_uri != NULL)
|
||||
parser->request_uri(parser->data, PTR_TO(mark), LEN(mark, p));
|
||||
parser->request_uri(parser, PTR_TO(mark), LEN(mark, p));
|
||||
}
|
||||
goto st20;
|
||||
tr58:
|
||||
#line 63 "ext/http11/http11_parser.rl"
|
||||
#line 58 "ext/http11/http11_parser.rl"
|
||||
{
|
||||
if(parser->query_string != NULL)
|
||||
parser->query_string(parser->data, PTR_TO(query_start), LEN(query_start, p));
|
||||
parser->query_string(parser, PTR_TO(query_start), LEN(query_start, p));
|
||||
}
|
||||
#line 53 "ext/http11/http11_parser.rl"
|
||||
#line 50 "ext/http11/http11_parser.rl"
|
||||
{
|
||||
if(parser->request_uri != NULL)
|
||||
parser->request_uri(parser->data, PTR_TO(mark), LEN(mark, p));
|
||||
parser->request_uri(parser, PTR_TO(mark), LEN(mark, p));
|
||||
}
|
||||
goto st20;
|
||||
st20:
|
||||
if ( ++p == pe )
|
||||
goto _test_eof20;
|
||||
case 20:
|
||||
#line 504 "ext/http11/http11_parser.c"
|
||||
#line 486 "ext/http11/http11_parser.c"
|
||||
switch( (*p) ) {
|
||||
case 32: goto tr31;
|
||||
case 37: goto tr32;
|
||||
|
@ -516,13 +498,13 @@ case 20:
|
|||
goto tr30;
|
||||
tr30:
|
||||
#line 34 "ext/http11/http11_parser.rl"
|
||||
{MARK(mark, p); }
|
||||
{ MARK(mark, p); }
|
||||
goto st21;
|
||||
st21:
|
||||
if ( ++p == pe )
|
||||
goto _test_eof21;
|
||||
case 21:
|
||||
#line 526 "ext/http11/http11_parser.c"
|
||||
#line 508 "ext/http11/http11_parser.c"
|
||||
switch( (*p) ) {
|
||||
case 32: goto tr34;
|
||||
case 37: goto st22;
|
||||
|
@ -538,13 +520,13 @@ case 21:
|
|||
goto st21;
|
||||
tr32:
|
||||
#line 34 "ext/http11/http11_parser.rl"
|
||||
{MARK(mark, p); }
|
||||
{ MARK(mark, p); }
|
||||
goto st22;
|
||||
st22:
|
||||
if ( ++p == pe )
|
||||
goto _test_eof22;
|
||||
case 22:
|
||||
#line 548 "ext/http11/http11_parser.c"
|
||||
#line 530 "ext/http11/http11_parser.c"
|
||||
if ( (*p) < 65 ) {
|
||||
if ( 48 <= (*p) && (*p) <= 57 )
|
||||
goto st23;
|
||||
|
@ -569,13 +551,13 @@ case 23:
|
|||
goto st0;
|
||||
tr5:
|
||||
#line 34 "ext/http11/http11_parser.rl"
|
||||
{MARK(mark, p); }
|
||||
{ MARK(mark, p); }
|
||||
goto st24;
|
||||
st24:
|
||||
if ( ++p == pe )
|
||||
goto _test_eof24;
|
||||
case 24:
|
||||
#line 579 "ext/http11/http11_parser.c"
|
||||
#line 561 "ext/http11/http11_parser.c"
|
||||
switch( (*p) ) {
|
||||
case 43: goto st24;
|
||||
case 58: goto st25;
|
||||
|
@ -594,13 +576,13 @@ case 24:
|
|||
goto st0;
|
||||
tr7:
|
||||
#line 34 "ext/http11/http11_parser.rl"
|
||||
{MARK(mark, p); }
|
||||
{ MARK(mark, p); }
|
||||
goto st25;
|
||||
st25:
|
||||
if ( ++p == pe )
|
||||
goto _test_eof25;
|
||||
case 25:
|
||||
#line 604 "ext/http11/http11_parser.c"
|
||||
#line 586 "ext/http11/http11_parser.c"
|
||||
switch( (*p) ) {
|
||||
case 32: goto tr8;
|
||||
case 34: goto st0;
|
||||
|
@ -641,13 +623,13 @@ case 27:
|
|||
goto st0;
|
||||
tr6:
|
||||
#line 34 "ext/http11/http11_parser.rl"
|
||||
{MARK(mark, p); }
|
||||
{ MARK(mark, p); }
|
||||
goto st28;
|
||||
st28:
|
||||
if ( ++p == pe )
|
||||
goto _test_eof28;
|
||||
case 28:
|
||||
#line 651 "ext/http11/http11_parser.c"
|
||||
#line 633 "ext/http11/http11_parser.c"
|
||||
switch( (*p) ) {
|
||||
case 32: goto tr42;
|
||||
case 34: goto st0;
|
||||
|
@ -689,17 +671,16 @@ case 30:
|
|||
goto st28;
|
||||
goto st0;
|
||||
tr45:
|
||||
#line 73 "ext/http11/http11_parser.rl"
|
||||
#line 66 "ext/http11/http11_parser.rl"
|
||||
{
|
||||
if(parser->request_path != NULL)
|
||||
parser->request_path(parser->data, PTR_TO(mark), LEN(mark,p));
|
||||
parser->request_path(parser, PTR_TO(mark), LEN(mark,p));
|
||||
}
|
||||
goto st31;
|
||||
st31:
|
||||
if ( ++p == pe )
|
||||
goto _test_eof31;
|
||||
case 31:
|
||||
#line 703 "ext/http11/http11_parser.c"
|
||||
#line 684 "ext/http11/http11_parser.c"
|
||||
switch( (*p) ) {
|
||||
case 32: goto tr8;
|
||||
case 34: goto st0;
|
||||
|
@ -740,17 +721,16 @@ case 33:
|
|||
goto st31;
|
||||
goto st0;
|
||||
tr46:
|
||||
#line 73 "ext/http11/http11_parser.rl"
|
||||
#line 66 "ext/http11/http11_parser.rl"
|
||||
{
|
||||
if(parser->request_path != NULL)
|
||||
parser->request_path(parser->data, PTR_TO(mark), LEN(mark,p));
|
||||
parser->request_path(parser, PTR_TO(mark), LEN(mark,p));
|
||||
}
|
||||
goto st34;
|
||||
st34:
|
||||
if ( ++p == pe )
|
||||
goto _test_eof34;
|
||||
case 34:
|
||||
#line 754 "ext/http11/http11_parser.c"
|
||||
#line 734 "ext/http11/http11_parser.c"
|
||||
switch( (*p) ) {
|
||||
case 32: goto tr53;
|
||||
case 34: goto st0;
|
||||
|
@ -764,14 +744,14 @@ case 34:
|
|||
goto st0;
|
||||
goto tr52;
|
||||
tr52:
|
||||
#line 62 "ext/http11/http11_parser.rl"
|
||||
{MARK(query_start, p); }
|
||||
#line 57 "ext/http11/http11_parser.rl"
|
||||
{ MARK(query_start, p); }
|
||||
goto st35;
|
||||
st35:
|
||||
if ( ++p == pe )
|
||||
goto _test_eof35;
|
||||
case 35:
|
||||
#line 775 "ext/http11/http11_parser.c"
|
||||
#line 755 "ext/http11/http11_parser.c"
|
||||
switch( (*p) ) {
|
||||
case 32: goto tr57;
|
||||
case 34: goto st0;
|
||||
|
@ -785,14 +765,14 @@ case 35:
|
|||
goto st0;
|
||||
goto st35;
|
||||
tr55:
|
||||
#line 62 "ext/http11/http11_parser.rl"
|
||||
{MARK(query_start, p); }
|
||||
#line 57 "ext/http11/http11_parser.rl"
|
||||
{ MARK(query_start, p); }
|
||||
goto st36;
|
||||
st36:
|
||||
if ( ++p == pe )
|
||||
goto _test_eof36;
|
||||
case 36:
|
||||
#line 796 "ext/http11/http11_parser.c"
|
||||
#line 776 "ext/http11/http11_parser.c"
|
||||
if ( (*p) < 65 ) {
|
||||
if ( 48 <= (*p) && (*p) <= 57 )
|
||||
goto st37;
|
||||
|
@ -1207,7 +1187,8 @@ case 56:
|
|||
_test_eof: {}
|
||||
_out: {}
|
||||
}
|
||||
#line 121 "ext/http11/http11_parser.rl"
|
||||
|
||||
#line 113 "ext/http11/http11_parser.rl"
|
||||
|
||||
if (!http_parser_has_error(parser))
|
||||
parser->cs = cs;
|
||||
|
|
|
@ -6,14 +6,24 @@
|
|||
#ifndef http11_parser_h
|
||||
#define http11_parser_h
|
||||
|
||||
#include "ruby.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#if defined(_WIN32)
|
||||
#include <stddef.h>
|
||||
#endif
|
||||
|
||||
typedef void (*element_cb)(void *data, const char *at, size_t length);
|
||||
typedef void (*field_cb)(void *data, const char *field, size_t flen, const char *value, size_t vlen);
|
||||
#define BUFFER_LEN 1024
|
||||
|
||||
struct http_parser;
|
||||
|
||||
typedef void (*element_cb)(struct http_parser* hp,
|
||||
const char *at, size_t length);
|
||||
|
||||
typedef void (*field_cb)(struct http_parser* hp,
|
||||
const char *field, size_t flen,
|
||||
const char *value, size_t vlen);
|
||||
|
||||
typedef struct http_parser {
|
||||
int cs;
|
||||
|
@ -25,7 +35,7 @@ typedef struct http_parser {
|
|||
size_t field_len;
|
||||
size_t query_start;
|
||||
|
||||
void *data;
|
||||
VALUE request;
|
||||
|
||||
field_cb http_field;
|
||||
element_cb request_method;
|
||||
|
@ -35,12 +45,15 @@ typedef struct http_parser {
|
|||
element_cb query_string;
|
||||
element_cb http_version;
|
||||
element_cb header_done;
|
||||
|
||||
char buf[BUFFER_LEN];
|
||||
|
||||
} http_parser;
|
||||
|
||||
int http_parser_init(http_parser *parser);
|
||||
int http_parser_finish(http_parser *parser);
|
||||
size_t http_parser_execute(http_parser *parser, const char *data, size_t len, size_t off);
|
||||
size_t http_parser_execute(http_parser *parser, const char *data,
|
||||
size_t len, size_t off);
|
||||
int http_parser_has_error(http_parser *parser);
|
||||
int http_parser_is_finished(http_parser *parser);
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ static void snake_upcase_char(char *c)
|
|||
|
||||
machine http_parser;
|
||||
|
||||
action mark {MARK(mark, fpc); }
|
||||
action mark { MARK(mark, fpc); }
|
||||
|
||||
|
||||
action start_field { MARK(field_start, fpc); }
|
||||
|
@ -42,43 +42,34 @@ static void snake_upcase_char(char *c)
|
|||
|
||||
action start_value { MARK(mark, fpc); }
|
||||
action write_value {
|
||||
if(parser->http_field != NULL) {
|
||||
parser->http_field(parser->data, PTR_TO(field_start), parser->field_len, PTR_TO(mark), LEN(mark, fpc));
|
||||
}
|
||||
parser->http_field(parser, PTR_TO(field_start), parser->field_len, PTR_TO(mark), LEN(mark, fpc));
|
||||
}
|
||||
action request_method {
|
||||
if(parser->request_method != NULL)
|
||||
parser->request_method(parser->data, PTR_TO(mark), LEN(mark, fpc));
|
||||
parser->request_method(parser, PTR_TO(mark), LEN(mark, fpc));
|
||||
}
|
||||
action request_uri {
|
||||
if(parser->request_uri != NULL)
|
||||
parser->request_uri(parser->data, PTR_TO(mark), LEN(mark, fpc));
|
||||
parser->request_uri(parser, PTR_TO(mark), LEN(mark, fpc));
|
||||
}
|
||||
action fragment {
|
||||
if(parser->fragment != NULL)
|
||||
parser->fragment(parser->data, PTR_TO(mark), LEN(mark, fpc));
|
||||
parser->fragment(parser, PTR_TO(mark), LEN(mark, fpc));
|
||||
}
|
||||
|
||||
action start_query {MARK(query_start, fpc); }
|
||||
action start_query { MARK(query_start, fpc); }
|
||||
action query_string {
|
||||
if(parser->query_string != NULL)
|
||||
parser->query_string(parser->data, PTR_TO(query_start), LEN(query_start, fpc));
|
||||
parser->query_string(parser, PTR_TO(query_start), LEN(query_start, fpc));
|
||||
}
|
||||
|
||||
action http_version {
|
||||
if(parser->http_version != NULL)
|
||||
parser->http_version(parser->data, PTR_TO(mark), LEN(mark, fpc));
|
||||
parser->http_version(parser, PTR_TO(mark), LEN(mark, fpc));
|
||||
}
|
||||
|
||||
action request_path {
|
||||
if(parser->request_path != NULL)
|
||||
parser->request_path(parser->data, PTR_TO(mark), LEN(mark,fpc));
|
||||
parser->request_path(parser, PTR_TO(mark), LEN(mark,fpc));
|
||||
}
|
||||
|
||||
action done {
|
||||
parser->body_start = fpc - buffer + 1;
|
||||
if(parser->header_done != NULL)
|
||||
parser->header_done(parser->data, fpc + 1, pe - fpc - 1);
|
||||
parser->header_done(parser, fpc + 1, pe - fpc - 1);
|
||||
fbreak;
|
||||
}
|
||||
|
||||
|
@ -98,9 +89,10 @@ int http_parser_init(http_parser *parser) {
|
|||
parser->mark = 0;
|
||||
parser->nread = 0;
|
||||
parser->field_len = 0;
|
||||
parser->field_start = 0;
|
||||
parser->field_start = 0;
|
||||
parser->request = Qnil;
|
||||
|
||||
return(1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -19,8 +19,6 @@ end
|
|||
|
||||
# Gem conditional loader
|
||||
require 'mongrel/gems'
|
||||
Mongrel::Gems.require 'cgi_multipart_eof_fix'
|
||||
Mongrel::Gems.require 'fastthread'
|
||||
require 'thread'
|
||||
|
||||
# Ruby Mongrel
|
||||
|
@ -71,6 +69,9 @@ module Mongrel
|
|||
# releases of Mongrel will find other creative ways to make threads faster, but don't
|
||||
# hold your breath until Ruby 1.9 is actually finally useful.
|
||||
class HttpServer
|
||||
|
||||
include Mongrel::Const
|
||||
|
||||
attr_reader :acceptor
|
||||
attr_reader :workers
|
||||
attr_reader :classifier
|
||||
|
@ -117,7 +118,7 @@ module Mongrel
|
|||
parser = HttpParser.new
|
||||
params = HttpParams.new
|
||||
request = nil
|
||||
data = client.readpartial(Const::CHUNK_SIZE)
|
||||
data = client.readpartial(CHUNK_SIZE)
|
||||
nparsed = 0
|
||||
|
||||
# Assumption: nparsed will always be less since data will get filled with more
|
||||
|
@ -128,19 +129,42 @@ module Mongrel
|
|||
nparsed = parser.execute(params, data, nparsed)
|
||||
|
||||
if parser.finished?
|
||||
if not params[Const::REQUEST_PATH]
|
||||
# it might be a dumbass full host request header
|
||||
uri = URI.parse(params[Const::REQUEST_URI])
|
||||
params[Const::REQUEST_PATH] = uri.path
|
||||
|
||||
if host = params[HTTP_HOST]
|
||||
if colon = host.index(":")
|
||||
params[SERVER_NAME] = host[0, colon]
|
||||
params[SERVER_PORT] = host[colon+1, host.size]
|
||||
else
|
||||
params[SERVER_NAME] = host
|
||||
params[SERVER_PORT] = PORT_80
|
||||
end
|
||||
end
|
||||
|
||||
raise "No REQUEST PATH" if not params[Const::REQUEST_PATH]
|
||||
if len = params[HTTP_CONTENT_LENGTH]
|
||||
params[CONTENT_LENGTH] = len
|
||||
end
|
||||
|
||||
script_name, path_info, handlers = @classifier.resolve(params[Const::REQUEST_PATH])
|
||||
if type = params[HTTP_CONTENT_TYPE]
|
||||
params[RAW_CONTENT_TYPE] = type
|
||||
end
|
||||
|
||||
params[SERVER_PROTOCOL] = HTTP_11
|
||||
params[SERVER_SOFTWARE] = MONGREL_VERSION
|
||||
params[GATEWAY_INTERFACE] = CGI_VER
|
||||
|
||||
if not params[REQUEST_PATH]
|
||||
# it might be a dumbass full host request header
|
||||
uri = URI.parse(params[REQUEST_URI])
|
||||
params[REQUEST_PATH] = uri.path
|
||||
end
|
||||
|
||||
raise "No REQUEST PATH" if not params[REQUEST_PATH]
|
||||
|
||||
script_name, path_info, handlers = @classifier.resolve(params[REQUEST_PATH])
|
||||
|
||||
if handlers
|
||||
params[Const::PATH_INFO] = path_info
|
||||
params[Const::SCRIPT_NAME] = script_name
|
||||
params[PATH_INFO] = path_info
|
||||
params[SCRIPT_NAME] = script_name
|
||||
|
||||
# From http://www.ietf.org/rfc/rfc3875 :
|
||||
# "Script authors should be aware that the REMOTE_ADDR and REMOTE_HOST
|
||||
|
@ -148,7 +172,7 @@ module Mongrel
|
|||
# ultimate source of the request. They identify the client for the
|
||||
# immediate request to the server; that client may be a proxy, gateway,
|
||||
# or other intermediary acting on behalf of the actual source client."
|
||||
params[Const::REMOTE_ADDR] = client.peeraddr.last
|
||||
params[REMOTE_ADDR] = client.peeraddr.last
|
||||
|
||||
# select handlers that want more detailed request notification
|
||||
notifiers = handlers.select { |h| h.request_notify }
|
||||
|
@ -172,17 +196,17 @@ module Mongrel
|
|||
end
|
||||
else
|
||||
# Didn't find it, return a stock 404 response.
|
||||
client.write(Const::ERROR_404_RESPONSE)
|
||||
client.write(ERROR_404_RESPONSE)
|
||||
end
|
||||
|
||||
break #done
|
||||
else
|
||||
# Parser is not done, queue up more data to read and continue parsing
|
||||
chunk = client.readpartial(Const::CHUNK_SIZE)
|
||||
chunk = client.readpartial(CHUNK_SIZE)
|
||||
break if !chunk or chunk.length == 0 # read failed, stop processing
|
||||
|
||||
data << chunk
|
||||
if data.length >= Const::MAX_HEADER
|
||||
if data.length >= MAX_HEADER
|
||||
raise HttpParserError.new("HEADER is longer than allowed, aborting client early.")
|
||||
end
|
||||
end
|
||||
|
@ -190,7 +214,7 @@ module Mongrel
|
|||
rescue EOFError,Errno::ECONNRESET,Errno::EPIPE,Errno::EINVAL,Errno::EBADF
|
||||
client.close rescue nil
|
||||
rescue HttpParserError => e
|
||||
STDERR.puts "#{Time.now}: HTTP parse error, malformed request (#{params[Const::HTTP_X_FORWARDED_FOR] || client.peeraddr.last}): #{e.inspect}"
|
||||
STDERR.puts "#{Time.now}: HTTP parse error, malformed request (#{params[HTTP_X_FORWARDED_FOR] || client.peeraddr.last}): #{e.inspect}"
|
||||
STDERR.puts "#{Time.now}: REQUEST DATA: #{data.inspect}\n---\nPARAMS: #{params.inspect}\n---\n"
|
||||
rescue Errno::EMFILE
|
||||
reap_dead_workers('too many files')
|
||||
|
@ -244,18 +268,22 @@ module Mongrel
|
|||
end
|
||||
|
||||
def configure_socket_options
|
||||
@tcp_defer_accept_opts = nil
|
||||
@tcp_cork_opts = nil
|
||||
|
||||
case RUBY_PLATFORM
|
||||
when /linux/
|
||||
# 9 is currently TCP_DEFER_ACCEPT
|
||||
$tcp_defer_accept_opts = [Socket::SOL_TCP, 9, 1]
|
||||
$tcp_cork_opts = [Socket::SOL_TCP, 3, 1]
|
||||
@tcp_defer_accept_opts = [Socket::SOL_TCP, 9, 1]
|
||||
@tcp_cork_opts = [Socket::SOL_TCP, 3, 1]
|
||||
|
||||
when /freebsd(([1-4]\..{1,2})|5\.[0-4])/
|
||||
# Do nothing, just closing a bug when freebsd <= 5.4
|
||||
when /freebsd/
|
||||
# Use the HTTP accept filter if available.
|
||||
# The struct made by pack() is defined in /usr/include/sys/socket.h as accept_filter_arg
|
||||
unless `/sbin/sysctl -nq net.inet.accf.http`.empty?
|
||||
$tcp_defer_accept_opts = [Socket::SOL_SOCKET, Socket::SO_ACCEPTFILTER, ['httpready', nil].pack('a16a240')]
|
||||
@tcp_defer_accept_opts = [Socket::SOL_SOCKET, Socket::SO_ACCEPTFILTER, ['httpready', nil].pack('a16a240')]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -267,19 +295,19 @@ module Mongrel
|
|||
|
||||
configure_socket_options
|
||||
|
||||
if defined?($tcp_defer_accept_opts) and $tcp_defer_accept_opts
|
||||
@socket.setsockopt(*$tcp_defer_accept_opts) rescue nil
|
||||
if @tcp_defer_accept_opts
|
||||
@socket.setsockopt(*@tcp_defer_accept_opts)
|
||||
end
|
||||
|
||||
tcp_cork_opts = @tcp_cork_opts
|
||||
|
||||
@acceptor = Thread.new do
|
||||
begin
|
||||
while true
|
||||
begin
|
||||
client = @socket.accept
|
||||
|
||||
if defined?($tcp_cork_opts) and $tcp_cork_opts
|
||||
client.setsockopt(*$tcp_cork_opts) rescue nil
|
||||
end
|
||||
client.setsockopt(*tcp_cork_opts) if tcp_cork_opts
|
||||
|
||||
worker_list = @workers.list
|
||||
|
||||
|
@ -288,7 +316,7 @@ module Mongrel
|
|||
client.close rescue nil
|
||||
reap_dead_workers("max processors")
|
||||
else
|
||||
thread = Thread.new(client) {|c| process_client(c) }
|
||||
thread = Thread.new(client) { |c| process_client(c) }
|
||||
thread[:started_on] = Time.now
|
||||
@workers.add(thread)
|
||||
|
||||
|
@ -359,8 +387,4 @@ module Mongrel
|
|||
end
|
||||
end
|
||||
|
||||
# Load experimental library, if present. We put it here so it can override anything
|
||||
# in regular Mongrel.
|
||||
|
||||
$LOAD_PATH.unshift 'projects/mongrel_experimental/lib/'
|
||||
Mongrel::Gems.require 'mongrel_experimental', ">=#{Mongrel::Const::MONGREL_VERSION}"
|
||||
|
|
|
@ -53,29 +53,29 @@ module Mongrel
|
|||
# REMOTE_USER, or REMOTE_HOST parameters since those are either a security problem or
|
||||
# too taxing on performance.
|
||||
module Const
|
||||
DATE = "Date".freeze
|
||||
DATE = "Date"
|
||||
|
||||
# This is the part of the path after the SCRIPT_NAME. URIClassifier will determine this.
|
||||
PATH_INFO="PATH_INFO".freeze
|
||||
PATH_INFO="PATH_INFO"
|
||||
|
||||
# This is the initial part that your handler is identified as by URIClassifier.
|
||||
SCRIPT_NAME="SCRIPT_NAME".freeze
|
||||
SCRIPT_NAME="SCRIPT_NAME"
|
||||
|
||||
# The original URI requested by the client. Passed to URIClassifier to build PATH_INFO and SCRIPT_NAME.
|
||||
REQUEST_URI='REQUEST_URI'.freeze
|
||||
REQUEST_PATH='REQUEST_PATH'.freeze
|
||||
REQUEST_URI='REQUEST_URI'
|
||||
REQUEST_PATH='REQUEST_PATH'
|
||||
|
||||
MONGREL_VERSION = VERSION = "1.2.0.beta.1".freeze
|
||||
MONGREL_VERSION = VERSION = "1.3.0"
|
||||
|
||||
MONGREL_TMP_BASE="mongrel".freeze
|
||||
MONGREL_TMP_BASE="mongrel"
|
||||
|
||||
# The standard empty 404 response for bad requests. Use Error4040Handler for custom stuff.
|
||||
ERROR_404_RESPONSE="HTTP/1.1 404 Not Found\r\nConnection: close\r\nServer: Mongrel #{MONGREL_VERSION}\r\n\r\nNOT FOUND".freeze
|
||||
ERROR_404_RESPONSE="HTTP/1.1 404 Not Found\r\nConnection: close\r\nServer: Mongrel #{MONGREL_VERSION}\r\n\r\nNOT FOUND"
|
||||
|
||||
CONTENT_LENGTH="CONTENT_LENGTH".freeze
|
||||
CONTENT_LENGTH="CONTENT_LENGTH"
|
||||
|
||||
# A common header for indicating the server is too busy. Not used yet.
|
||||
ERROR_503_RESPONSE="HTTP/1.1 503 Service Unavailable\r\n\r\nBUSY".freeze
|
||||
ERROR_503_RESPONSE="HTTP/1.1 503 Service Unavailable\r\n\r\nBUSY"
|
||||
|
||||
# The basic max request size we'll try to read.
|
||||
CHUNK_SIZE=(16 * 1024)
|
||||
|
@ -88,23 +88,40 @@ module Mongrel
|
|||
MAX_BODY=MAX_HEADER
|
||||
|
||||
# A frozen format for this is about 15% faster
|
||||
STATUS_FORMAT = "HTTP/1.1 %d %s\r\nConnection: close\r\n".freeze
|
||||
CONTENT_TYPE = "Content-Type".freeze
|
||||
LAST_MODIFIED = "Last-Modified".freeze
|
||||
ETAG = "ETag".freeze
|
||||
SLASH = "/".freeze
|
||||
REQUEST_METHOD="REQUEST_METHOD".freeze
|
||||
GET="GET".freeze
|
||||
HEAD="HEAD".freeze
|
||||
STATUS_FORMAT = "HTTP/1.1 %d %s\r\nConnection: close\r\n"
|
||||
CONTENT_TYPE = "Content-Type"
|
||||
LAST_MODIFIED = "Last-Modified"
|
||||
ETAG = "ETag"
|
||||
SLASH = "/"
|
||||
REQUEST_METHOD="REQUEST_METHOD"
|
||||
GET="GET"
|
||||
HEAD="HEAD"
|
||||
# ETag is based on the apache standard of hex mtime-size-inode (inode is 0 on win32)
|
||||
ETAG_FORMAT="\"%x-%x-%x\"".freeze
|
||||
HEADER_FORMAT="%s: %s\r\n".freeze
|
||||
LINE_END="\r\n".freeze
|
||||
REMOTE_ADDR="REMOTE_ADDR".freeze
|
||||
HTTP_X_FORWARDED_FOR="HTTP_X_FORWARDED_FOR".freeze
|
||||
HTTP_IF_MODIFIED_SINCE="HTTP_IF_MODIFIED_SINCE".freeze
|
||||
HTTP_IF_NONE_MATCH="HTTP_IF_NONE_MATCH".freeze
|
||||
REDIRECT = "HTTP/1.1 302 Found\r\nLocation: %s\r\nConnection: close\r\n\r\n".freeze
|
||||
HOST = "HOST".freeze
|
||||
ETAG_FORMAT="\"%x-%x-%x\""
|
||||
HEADER_FORMAT="%s: %s\r\n"
|
||||
LINE_END="\r\n"
|
||||
REMOTE_ADDR="REMOTE_ADDR"
|
||||
HTTP_X_FORWARDED_FOR="HTTP_X_FORWARDED_FOR"
|
||||
HTTP_IF_MODIFIED_SINCE="HTTP_IF_MODIFIED_SINCE"
|
||||
HTTP_IF_NONE_MATCH="HTTP_IF_NONE_MATCH"
|
||||
REDIRECT = "HTTP/1.1 302 Found\r\nLocation: %s\r\nConnection: close\r\n\r\n"
|
||||
HOST = "HOST"
|
||||
|
||||
SERVER_NAME = "SERVER_NAME"
|
||||
SERVER_PORT = "SERVER_PORT"
|
||||
HTTP_HOST = "HTTP_HOST"
|
||||
PORT_80 = "80"
|
||||
|
||||
SERVER_PROTOCOL = "SERVER_PROTOCOL"
|
||||
HTTP_11 = "HTTP/1.1"
|
||||
|
||||
SERVER_SOFTWARE = "SERVER_SOFTWARE"
|
||||
GATEWAY_INTERFACE = "GATEWAY_INTERFACE"
|
||||
CGI_VER = "CGI/1.2"
|
||||
|
||||
HTTP_CONTENT_LENGTH = "HTTP_CONTENT_LENGTH"
|
||||
|
||||
HTTP_CONTENT_TYPE = "HTTP_CONTENT_TYPE"
|
||||
RAW_CONTENT_TYPE = "CONTENT_TYPE"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -119,7 +119,7 @@ module Mongrel
|
|||
|
||||
# You give it the path to the directory root and and optional listing_allowed and index_html
|
||||
def initialize(path, listing_allowed=true, index_html="index.html")
|
||||
@path = File.expand_path(path) if path
|
||||
@path = (File.expand_path(path) if path)
|
||||
@listing_allowed = listing_allowed
|
||||
@index_html = index_html
|
||||
@default_content_type = "application/octet-stream".freeze
|
||||
|
|
|
@ -4,6 +4,7 @@ module Mongrel
|
|||
|
||||
class RegistrationError < RuntimeError
|
||||
end
|
||||
|
||||
class UsageError < RuntimeError
|
||||
end
|
||||
|
||||
|
@ -56,8 +57,6 @@ module Mongrel
|
|||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def rebuild
|
||||
if @handler_map.size == 1 and @handler_map[Const::SLASH]
|
||||
@root_handler = @handler_map.values.first
|
||||
|
@ -66,11 +65,16 @@ module Mongrel
|
|||
routes = @handler_map.keys.sort.sort_by do |uri|
|
||||
-uri.length
|
||||
end
|
||||
@matcher = Regexp.new(routes.map do |uri|
|
||||
Regexp.new('^' + Regexp.escape(uri))
|
||||
end.join('|'))
|
||||
|
||||
all_possibles = routes.map do |uri|
|
||||
Regexp.new('^' + Regexp.escape(uri))
|
||||
end.join('|')
|
||||
|
||||
@matcher = Regexp.new(all_possibles)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private :rebuild
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
require 'rake/javaextensiontask'
|
||||
if ENV['JAVA']
|
||||
|
||||
# build http11 java extension
|
||||
Rake::JavaExtensionTask.new('http11', HOE.spec) do |ext|
|
||||
ext.java_compiling do |gs|
|
||||
gs.dependencies.delete gs.dependencies.find { |d| d.name == 'daemons' }
|
||||
require 'rake/javaextensiontask'
|
||||
|
||||
# build http11 java extension
|
||||
Rake::JavaExtensionTask.new('http11', HOE.spec) do |ext|
|
||||
ext.java_compiling do |gs|
|
||||
gs.dependencies.delete gs.dependencies.find { |d| d.name == 'daemons' }
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -21,11 +21,9 @@ class HttpParserTest < Test::Unit::TestCase
|
|||
assert !parser.error?, "Parser had error"
|
||||
assert nread == parser.nread, "Number read returned from execute does not match"
|
||||
|
||||
assert_equal 'HTTP/1.1', req['SERVER_PROTOCOL']
|
||||
assert_equal '/', req['REQUEST_PATH']
|
||||
assert_equal 'HTTP/1.1', req['HTTP_VERSION']
|
||||
assert_equal '/', req['REQUEST_URI']
|
||||
assert_equal 'CGI/1.2', req['GATEWAY_INTERFACE']
|
||||
assert_equal 'GET', req['REQUEST_METHOD']
|
||||
assert_nil req['FRAGMENT']
|
||||
assert_nil req['QUERY_STRING']
|
||||
|
|
Loading…
Reference in a new issue