Skip to content

Commit

Permalink
Upgrade http-parser
Browse files Browse the repository at this point in the history
  • Loading branch information
ry committed Jan 9, 2010
1 parent b3349eb commit c9e2143
Show file tree
Hide file tree
Showing 7 changed files with 137 additions and 118 deletions.
2 changes: 1 addition & 1 deletion deps/http_parser/LICENSE-MIT
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Copyright 2009 Ryan Dahl <ry@tinyclouds.org>
Copyright 2009,2010 Ryan Dahl <ry@tinyclouds.org>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to
Expand Down
10 changes: 5 additions & 5 deletions deps/http_parser/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@ Usage

One `http_parser` object is used per TCP connection. Initialize the struct
using `http_parser_init()` and set the callbacks. That might look something
like this:
like this for a request parser:

http_parser *parser = malloc(sizeof(http_parser));
http_parser_init(parser);
http_parser_init(parser, HTTP_REQUEST);
parser->on_path = my_path_callback;
parser->on_header_field = my_header_field_callback;
/* ... */
Expand All @@ -54,7 +54,7 @@ When data is received on the socket execute the parser and check for errors.
* Note we pass the recved==0 to http_parse_requests to signal
* that EOF has been recieved.
*/
nparsed = http_parse_requests(parser, buf, recved);
nparsed = http_parser_execute(parser, buf, recved);

if (nparsed != recved) {
/* Handle error. Usually just close the connection. */
Expand All @@ -63,7 +63,7 @@ When data is received on the socket execute the parser and check for errors.
HTTP needs to know where the end of the stream is. For example, sometimes
servers send responses without Content-Length and expect the client to
consume input (for the body) until EOF. To tell http_parser about EOF, give
`0` as the third parameter to `http_parse_requests()`. Callbacks and errors
`0` as the third parameter to `http_parser_execute()`. Callbacks and errors
can still be encountered during an EOF, so one must still be prepared
to receive them.

Expand All @@ -85,7 +85,7 @@ parser, for example, would not want such a feature.
Callbacks
---------

During the `http_parse_requests()` call, the callbacks set in `http_parser`
During the `http_parser_execute()` call, the callbacks set in `http_parser`
will be executed. The parser maintains state and never looks behind, so
buffering the data is not necessary. If you need to save certain data for
later usage, you can do that from the callbacks.
Expand Down
50 changes: 28 additions & 22 deletions deps/http_parser/http_parser.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* Copyright 2009 Ryan Dahl <ry@tinyclouds.org>
/* Copyright 2009,2010 Ryan Dahl <ry@tinyclouds.org>
*
* Some parts of this source file were taken from NGINX
* (src/http/ngx_http_parser.c) copyright (C) 2002-2009 Igor Sysoev.
Expand Down Expand Up @@ -97,6 +97,7 @@ static inline int message_complete_callback (http_parser *parser)
return parser->on_message_complete(parser);
}

#define PROXY_CONNECTION "proxy-connection"
#define CONNECTION "connection"
#define CONTENT_LENGTH "content-length"
#define TRANSFER_ENCODING "transfer-encoding"
Expand Down Expand Up @@ -218,6 +219,7 @@ enum header_states
, h_CON

, h_matching_connection
, h_matching_proxy_connection
, h_matching_content_length
, h_matching_transfer_encoding

Expand Down Expand Up @@ -245,6 +247,8 @@ enum flags
#define LF '\n'
#define LOWER(c) (unsigned char)(c | 0x20)

#define start_state (parser->type == HTTP_REQUEST ? s_start_req : s_start_res)

#if HTTP_PARSER_STRICT
# define STRICT_CHECK(cond) if (cond) goto error
# define NEW_MESSAGE() (http_should_keep_alive(parser) ? start_state : s_dead)
Expand All @@ -253,8 +257,9 @@ enum flags
# define NEW_MESSAGE() start_state
#endif

static inline
size_t parse (http_parser *parser, const char *data, size_t len, int start_state)
size_t http_parser_execute (http_parser *parser,
const char *data,
size_t len)
{
char c, ch;
const char *p, *pe;
Expand Down Expand Up @@ -950,6 +955,10 @@ size_t parse (http_parser *parser, const char *data, size_t len, int start_state
header_state = h_C;
break;

case 'p':
header_state = h_matching_proxy_connection;
break;

case 't':
header_state = h_matching_transfer_encoding;
break;
Expand Down Expand Up @@ -1007,6 +1016,18 @@ size_t parse (http_parser *parser, const char *data, size_t len, int start_state
}
break;

/* proxy-connection */

case h_matching_proxy_connection:
index++;
if (index > sizeof(PROXY_CONNECTION)-1
|| c != PROXY_CONNECTION[index]) {
header_state = h_general;
} else if (index == sizeof(PROXY_CONNECTION)-2) {
header_state = h_connection;
}
break;

/* content-length */

case h_matching_content_length:
Expand Down Expand Up @@ -1256,7 +1277,7 @@ size_t parse (http_parser *parser, const char *data, size_t len, int start_state
/* Content-Length header given and non-zero */
state = s_body_identity;
} else {
if (start_state == s_start_req || http_should_keep_alive(parser)) {
if (parser->type == HTTP_REQUEST || http_should_keep_alive(parser)) {
/* Assume content-length 0 - read the next */
CALLBACK2(message_complete);
state = NEW_MESSAGE();
Expand Down Expand Up @@ -1408,22 +1429,6 @@ size_t parse (http_parser *parser, const char *data, size_t len, int start_state
}


size_t
http_parse_requests (http_parser *parser, const char *data, size_t len)
{
if (!parser->state) parser->state = s_start_req;
return parse(parser, data, len, s_start_req);
}


size_t
http_parse_responses (http_parser *parser, const char *data, size_t len)
{
if (!parser->state) parser->state = s_start_res;
return parse(parser, data, len, s_start_res);
}


int
http_should_keep_alive (http_parser *parser)
{
Expand All @@ -1446,9 +1451,10 @@ http_should_keep_alive (http_parser *parser)


void
http_parser_init (http_parser *parser)
http_parser_init (http_parser *parser, enum http_parser_type t)
{
parser->state = 0;
parser->type = t;
parser->state = (t == HTTP_REQUEST ? s_start_req : s_start_res);
parser->on_message_begin = NULL;
parser->on_path = NULL;
parser->on_query_string = NULL;
Expand Down
10 changes: 6 additions & 4 deletions deps/http_parser/http_parser.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* Copyright 2009 Ryan Dahl <ry@tinyclouds.org>
/* Copyright 2009,2010 Ryan Dahl <ry@tinyclouds.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
Expand Down Expand Up @@ -74,8 +74,11 @@ enum http_method
, HTTP_UNLOCK = 0x4000
};

enum http_parser_type { HTTP_REQUEST, HTTP_RESPONSE };

struct http_parser {
/** PRIVATE **/
enum http_parser_type type;
unsigned short state;
unsigned short header_state;
size_t index;
Expand Down Expand Up @@ -125,9 +128,8 @@ struct http_parser {
http_cb on_message_complete;
};

void http_parser_init(http_parser *parser);
size_t http_parse_requests(http_parser *parser, const char *data, size_t len);
size_t http_parse_responses(http_parser *parser, const char *data, size_t len);
void http_parser_init(http_parser *parser, enum http_parser_type type);
size_t http_parser_execute(http_parser *parser, const char *data, size_t len);
/* Call this in the on_headers_complete or on_message_complete callback to
* determine if this will be the last message on the connection.
* If you are the server, respond with the "Connection: close" header
Expand Down
Loading

0 comments on commit c9e2143

Please sign in to comment.