@ -34,14 +34,12 @@
# define MAX_HEADERS 10
# define MAX_ELEMENT_SIZE 500
enum message_type { REQUEST , RESPONSE } ;
static http_parser * parser ;
struct message {
const char * name ; // for debugging purposes
const char * raw ;
enum message _type type ;
enum http_parser _type type ;
enum http_method method ;
int status_code ;
char request_path [ MAX_ELEMENT_SIZE ] ;
@ -65,12 +63,11 @@ struct message {
static int currently_parsing_eof ;
inline size_t parse ( enum message_type t , const char * buf , size_t len )
inline size_t parse ( const char * buf , size_t len )
{
size_t nparsed ;
currently_parsing_eof = ( len = = 0 ) ;
nparsed = ( t = = REQUEST ? http_parse_requests ( parser , buf , len )
: http_parse_responses ( parser , buf , len ) ) ;
nparsed = http_parser_execute ( parser , buf , len ) ;
return nparsed ;
}
@ -81,7 +78,7 @@ static int num_messages;
const struct message requests [ ] =
# define CURL_GET 0
{ { . name = " curl get "
, . type = REQUEST
, . type = HTTP_ REQUEST
, . raw = " GET /test HTTP/1.1 \r \n "
" User-Agent: curl/7.18.0 (i486-pc-linux-gnu) libcurl/7.18.0 OpenSSL/0.9.8g zlib/1.2.3.3 libidn/1.1 \r \n "
" Host: 0.0.0.0=5000 \r \n "
@ -107,7 +104,7 @@ const struct message requests[] =
# define FIREFOX_GET 1
, { . name = " firefox get "
, . type = REQUEST
, . type = HTTP_ REQUEST
, . raw = " GET /favicon.ico HTTP/1.1 \r \n "
" Host: 0.0.0.0=5000 \r \n "
" User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9) Gecko/2008061015 Firefox/3.0 \r \n "
@ -143,7 +140,7 @@ const struct message requests[] =
# define DUMBFUCK 2
, { . name = " dumbfuck "
, . type = REQUEST
, . type = HTTP_ REQUEST
, . raw = " GET /dumbfuck HTTP/1.1 \r \n "
" aaaaaaaaaaaaa:++++++++++ \r \n "
" \r \n "
@ -165,7 +162,7 @@ const struct message requests[] =
# define FRAGMENT_IN_URI 3
, { . name = " fragment in url "
, . type = REQUEST
, . type = HTTP_ REQUEST
, . raw = " GET /forums/1/topics/2375?page=1#posts-17408 HTTP/1.1 \r \n "
" \r \n "
, . should_keep_alive = TRUE
@ -184,7 +181,7 @@ const struct message requests[] =
# define GET_NO_HEADERS_NO_BODY 4
, { . name = " get no headers no body "
, . type = REQUEST
, . type = HTTP_ REQUEST
, . raw = " GET /get_no_headers_no_body/world HTTP/1.1 \r \n "
" \r \n "
, . should_keep_alive = TRUE
@ -202,7 +199,7 @@ const struct message requests[] =
# define GET_ONE_HEADER_NO_BODY 5
, { . name = " get one header no body "
, . type = REQUEST
, . type = HTTP_ REQUEST
, . raw = " GET /get_one_header_no_body HTTP/1.1 \r \n "
" Accept: */* \r \n "
" \r \n "
@ -224,7 +221,7 @@ const struct message requests[] =
# define GET_FUNKY_CONTENT_LENGTH 6
, { . name = " get funky content length body hello "
, . type = REQUEST
, . type = HTTP_ REQUEST
, . raw = " GET /get_funky_content_length_body_hello HTTP/1.0 \r \n "
" conTENT-Length: 5 \r \n "
" \r \n "
@ -247,7 +244,7 @@ const struct message requests[] =
# define POST_IDENTITY_BODY_WORLD 7
, { . name = " post identity body world "
, . type = REQUEST
, . type = HTTP_ REQUEST
, . raw = " POST /post_identity_body_world?q=search#hey HTTP/1.1 \r \n "
" Accept: */* \r \n "
" Transfer-Encoding: identity \r \n "
@ -274,7 +271,7 @@ const struct message requests[] =
# define POST_CHUNKED_ALL_YOUR_BASE 8
, { . name = " post - chunked body: all your base are belong to us "
, . type = REQUEST
, . type = HTTP_ REQUEST
, . raw = " POST /post_chunked_all_your_base HTTP/1.1 \r \n "
" Transfer-Encoding: chunked \r \n "
" \r \n "
@ -299,7 +296,7 @@ const struct message requests[] =
# define TWO_CHUNKS_MULT_ZERO_END 9
, { . name = " two chunks ; triple zero ending "
, . type = REQUEST
, . type = HTTP_ REQUEST
, . raw = " POST /two_chunks_mult_zero_end HTTP/1.1 \r \n "
" Transfer-Encoding: chunked \r \n "
" \r \n "
@ -325,7 +322,7 @@ const struct message requests[] =
# define CHUNKED_W_TRAILING_HEADERS 10
, { . name = " chunked with trailing headers. blech. "
, . type = REQUEST
, . type = HTTP_ REQUEST
, . raw = " POST /chunked_w_trailing_headers HTTP/1.1 \r \n "
" Transfer-Encoding: chunked \r \n "
" \r \n "
@ -355,7 +352,7 @@ const struct message requests[] =
# define CHUNKED_W_BULLSHIT_AFTER_LENGTH 11
, { . name = " with bullshit after the length "
, . type = REQUEST
, . type = HTTP_ REQUEST
, . raw = " POST /chunked_w_bullshit_after_length HTTP/1.1 \r \n "
" Transfer-Encoding: chunked \r \n "
" \r \n "
@ -381,7 +378,7 @@ const struct message requests[] =
# define WITH_QUOTES 12
, { . name = " with quotes "
, . type = REQUEST
, . type = HTTP_ REQUEST
, . raw = " GET /with_ \" stupid \" _quotes?foo= \" bar \" HTTP/1.1 \r \n \r \n "
, . should_keep_alive = TRUE
, . message_complete_on_eof = FALSE
@ -404,7 +401,7 @@ const struct message requests[] =
* Compare with NO_CONTENT_LENGTH_RESPONSE .
*/
, { . name = " apachebench get "
, . type = REQUEST
, . type = HTTP_ REQUEST
, . raw = " GET /test HTTP/1.0 \r \n "
" Host: 0.0.0.0:5000 \r \n "
" User-Agent: ApacheBench/2.3 \r \n "
@ -433,7 +430,7 @@ const struct message requests[] =
const struct message responses [ ] =
# define GOOGLE_301 0
{ { . name = " google 301 "
, . type = RESPONSE
, . type = HTTP_ RESPONSE
, . raw = " HTTP/1.1 301 Moved Permanently \r \n "
" Location: http://www.google.com/ \r \n "
" Content-Type: text/html; charset=UTF-8 \r \n "
@ -479,7 +476,7 @@ const struct message responses[] =
* Compare with APACHEBENCH_GET
*/
, { . name = " no content-length response "
, . type = RESPONSE
, . type = HTTP_ RESPONSE
, . raw = " HTTP/1.1 200 OK \r \n "
" Date: Tue, 04 Aug 2009 07:59:32 GMT \r \n "
" Server: Apache \r \n "
@ -522,7 +519,7 @@ const struct message responses[] =
# define NO_HEADERS_NO_BODY_404 2
, { . name = " 404 no headers no body "
, . type = RESPONSE
, . type = HTTP_ RESPONSE
, . raw = " HTTP/1.1 404 Not Found \r \n \r \n "
, . should_keep_alive = TRUE
, . message_complete_on_eof = FALSE
@ -536,7 +533,7 @@ const struct message responses[] =
# define NO_REASON_PHRASE 3
, { . name = " 301 no response phrase "
, . type = RESPONSE
, . type = HTTP_ RESPONSE
, . raw = " HTTP/1.1 301 \r \n \r \n "
, . should_keep_alive = TRUE
, . message_complete_on_eof = FALSE
@ -550,7 +547,7 @@ const struct message responses[] =
# define TRAILING_SPACE_ON_CHUNKED_BODY 4
, { . name = " 200 trailing space on chunked body "
, . type = RESPONSE
, . type = HTTP_ RESPONSE
, . raw = " HTTP/1.1 200 OK \r \n "
" Content-Type: text/plain \r \n "
" Transfer-Encoding: chunked \r \n "
@ -581,7 +578,7 @@ const struct message responses[] =
# define NO_CARRIAGE_RET 5
, { . name = " no carriage ret "
, . type = RESPONSE
, . type = HTTP_ RESPONSE
, . raw = " HTTP/1.1 200 OK \n "
" Content-Type: text/html; charset=utf-8 \n "
" Connection: close \n "
@ -715,7 +712,7 @@ message_complete_cb (http_parser *p)
}
void
parser_init ( )
parser_init ( enum http_parser_type type )
{
num_messages = 0 ;
@ -723,7 +720,7 @@ parser_init ()
parser = malloc ( sizeof ( http_parser ) ) ;
http_parser_init ( parser );
http_parser_init ( parser , type );
memset ( & messages , 0 , sizeof messages ) ;
@ -791,7 +788,7 @@ message_eq (int index, const struct message *expected)
MESSAGE_CHECK_NUM_EQ ( expected , m , http_major ) ;
MESSAGE_CHECK_NUM_EQ ( expected , m , http_minor ) ;
if ( expected - > type = = REQUEST) {
if ( expected - > type = = HTTP_ REQUEST) {
MESSAGE_CHECK_NUM_EQ ( expected , m , method ) ;
} else {
MESSAGE_CHECK_NUM_EQ ( expected , m , status_code ) ;
@ -869,17 +866,17 @@ print_error (const char *raw, size_t error_location)
void
test_message ( const struct message * message )
{
parser_init ( ) ;
parser_init ( message - > type ) ;
size_t read ;
read = parse ( message - > type, message - > raw, strlen ( message - > raw ) ) ;
read = parse ( message - > raw, strlen ( message - > raw ) ) ;
if ( read ! = strlen ( message - > raw ) ) {
print_error ( message - > raw , read ) ;
exit ( 1 ) ;
}
read = parse ( message - > type , NULL , 0 ) ;
read = parse ( NULL , 0 ) ;
if ( read ! = 0 ) {
print_error ( message - > raw , read ) ;
exit ( 1 ) ;
@ -898,13 +895,13 @@ test_message (const struct message *message)
void
test_error ( const char * buf )
{
parser_init ( ) ;
parser_init ( HTTP_REQUEST ) ;
size_t parsed ;
parsed = parse ( REQUEST, buf, strlen ( buf ) ) ;
parsed = parse ( buf, strlen ( buf ) ) ;
if ( parsed ! = strlen ( buf ) ) goto out ;
parsed = parse ( REQUEST , NULL , 0 ) ;
parsed = parse ( NULL , 0 ) ;
if ( parsed ! = 0 ) goto out ;
fprintf ( stderr , " \n *** Error expected but none found *** \n \n %s " , buf ) ;
@ -929,17 +926,17 @@ test_multiple3 (const struct message *r1, const struct message *r2, const struct
strcat ( total , r2 - > raw ) ;
strcat ( total , r3 - > raw ) ;
parser_init ( ) ;
parser_init ( r1 - > type ) ;
size_t read ;
read = parse ( r1- > type , total, strlen ( total ) ) ;
read = parse ( total, strlen ( total ) ) ;
if ( read ! = strlen ( total ) ) {
print_error ( total , read ) ;
exit ( 1 ) ;
}
read = parse ( REQUEST , NULL , 0 ) ;
read = parse ( NULL , 0 ) ;
if ( read ! = 0 ) {
print_error ( total , read ) ;
exit ( 1 ) ;
@ -992,7 +989,7 @@ test_scan (const struct message *r1, const struct message *r2, const struct mess
}
ops + = 1 ;
parser_init ( ) ;
parser_init ( r1 - > type ) ;
buf1_len = i ;
strncpy ( buf1 , total , buf1_len ) ;
@ -1006,25 +1003,25 @@ test_scan (const struct message *r1, const struct message *r2, const struct mess
strncpy ( buf3 , total + j , buf3_len ) ;
buf3 [ buf3_len ] = 0 ;
read = parse ( r1- > type , buf1, buf1_len ) ;
read = parse ( buf1, buf1_len ) ;
if ( read ! = buf1_len ) {
print_error ( buf1 , read ) ;
goto error ;
}
read = parse ( r1- > type , buf2, buf2_len ) ;
read = parse ( buf2, buf2_len ) ;
if ( read ! = buf2_len ) {
print_error ( buf2 , read ) ;
goto error ;
}
read = parse ( r1- > type , buf3, buf3_len ) ;
read = parse ( buf3, buf3_len ) ;
if ( read ! = buf3_len ) {
print_error ( buf3 , read ) ;
goto error ;
}
parse ( r1 - > type , NULL , 0 ) ;
parse ( NULL , 0 ) ;
if ( 3 ! = num_messages ) {
fprintf ( stderr , " \n \n Parser didn't see 3 messages only %d \n " , num_messages ) ;