Skip to content

Commit

Permalink
update http-parser to v2.9.2 (2019-04-16)
Browse files Browse the repository at this point in the history
Ref : https://github.com/nodejs/http-parser.git , tag v2.9.2 , commit 5c17dad400e45c
  • Loading branch information
benlabbe committed Jun 25, 2019
1 parent c08f7d9 commit 6ef0c0c
Show file tree
Hide file tree
Showing 12 changed files with 2,605 additions and 626 deletions.
26 changes: 26 additions & 0 deletions http-parser/.gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,30 @@
/out/
core
tags
*.o
test
test_g
test_fast
bench
url_parser
parsertrace
parsertrace_g
*.mk
*.Makefile
*.so.*
*.exe.*
*.exe
*.a


# Visual Studio uglies
*.suo
*.sln
*.vcxproj
*.vcxproj.filters
*.vcxproj.user
*.opensdf
*.ncrunchsolution*
*.sdf
*.vsp
*.psess
30 changes: 29 additions & 1 deletion http-parser/AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ Andre Caron <[email protected]>
Ivo Raisr <[email protected]>
James McLaughlin <[email protected]>
David Gwynne <[email protected]>
LE ROUX Thomas <[email protected]>
Thomas LE ROUX <[email protected]>
Randy Rizun <[email protected]>
Andre Louis Caron <[email protected]>
Simon Zimmermann <[email protected]>
Expand All @@ -38,3 +38,31 @@ Bertrand Paquet <[email protected]>
BogDan Vatra <[email protected]>
Peter Faiman <[email protected]>
Corey Richardson <[email protected]>
Tóth Tamás <[email protected]>
Cam Swords <[email protected]>
Chris Dickinson <[email protected]>
Uli Köhler <[email protected]>
Charlie Somerville <[email protected]>
Patrik Stutz <[email protected]>
Fedor Indutny <[email protected]>
runner <[email protected]>
Alexis Campailla <[email protected]>
David Wragg <[email protected]>
Vinnie Falco <[email protected]>
Alex Butum <[email protected]>
Rex Feng <[email protected]>
Alex Kocharin <[email protected]>
Mark Koopman <[email protected]>
Helge Heß <[email protected]>
Alexis La Goutte <[email protected]>
George Miroshnykov <[email protected]>
Maciej Małecki <[email protected]>
Marc O'Morain <[email protected]>
Jeff Pinner <[email protected]>
Timothy J Fontaine <[email protected]>
Akagi201 <[email protected]>
Romain Giraud <[email protected]>
Jay Satiro <[email protected]>
Arne Steen <[email protected]>
Kjell Schubert <[email protected]>
Olivier Mengué <[email protected]>
4 changes: 0 additions & 4 deletions http-parser/CONTRIBUTIONS

This file was deleted.

6 changes: 1 addition & 5 deletions http-parser/LICENSE-MIT
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
http_parser.c is based on src/http/ngx_http_parse.c from NGINX copyright
Igor Sysoev.

Additional changes are licensed under the same terms as NGINX and
copyright Joyent, Inc. and other Node contributors. All rights reserved.
Copyright Joyent, Inc. and other Node contributors.

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
138 changes: 103 additions & 35 deletions http-parser/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
HTTP Parser
===========

[![Build Status](https://api.travis-ci.org/nodejs/http-parser.svg?branch=master)](https://travis-ci.org/nodejs/http-parser)

This is a parser for HTTP messages written in C. It parses both requests and
responses. The parser is designed to be used in performance HTTP
applications. It does not make any syscalls nor allocations, it does not
Expand Down Expand Up @@ -34,43 +36,46 @@ 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 for a request parser:
```c
http_parser_settings settings;
settings.on_url = my_url_callback;
settings.on_header_field = my_header_field_callback;
/* ... */

http_parser_settings settings;
settings.on_url = my_url_callback;
settings.on_header_field = my_header_field_callback;
/* ... */

http_parser *parser = malloc(sizeof(http_parser));
http_parser_init(parser, HTTP_REQUEST);
parser->data = my_socket;
http_parser *parser = malloc(sizeof(http_parser));
http_parser_init(parser, HTTP_REQUEST);
parser->data = my_socket;
```
When data is received on the socket execute the parser and check for errors.
size_t len = 80*1024, nparsed;
char buf[len];
ssize_t recved;
```c
size_t len = 80*1024, nparsed;
char buf[len];
ssize_t recved;
recved = recv(fd, buf, len, 0);
recved = recv(fd, buf, len, 0);
if (recved < 0) {
/* Handle error. */
}
if (recved < 0) {
/* Handle error. */
}
/* Start up / continue the parser.
* Note we pass recved==0 to signal that EOF has been recieved.
*/
nparsed = http_parser_execute(parser, &settings, buf, recved);
/* Start up / continue the parser.
* Note we pass recved==0 to signal that EOF has been received.
*/
nparsed = http_parser_execute(parser, &settings, buf, recved);
if (parser->upgrade) {
/* handle new protocol */
} else if (nparsed != recved) {
/* Handle error. Usually just close the connection. */
}
if (parser->upgrade) {
/* handle new protocol */
} else if (nparsed != recved) {
/* Handle error. Usually just close the connection. */
}
```

HTTP needs to know where the end of the stream is. For example, sometimes
`http_parser` 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 forth parameter to `http_parser_execute()`. Callbacks and errors
consume input (for the body) until EOF. To tell `http_parser` about EOF, give
`0` as the fourth 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 @@ -88,8 +93,8 @@ the on_body callback.
The Special Problem of Upgrade
------------------------------

HTTP supports upgrading the connection to a different protocol. An
increasingly common example of this is the Web Socket protocol which sends
`http_parser` supports upgrading the connection to a different protocol. An
increasingly common example of this is the WebSocket protocol which sends
a request like

GET /demo HTTP/1.1
Expand All @@ -101,11 +106,11 @@ a request like

followed by non-HTTP data.

(See http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-75 for more
information the Web Socket protocol.)
(See [RFC6455](https://tools.ietf.org/html/rfc6455) for more information the
WebSocket protocol.)

To support this, the parser will treat this as a normal HTTP message without a
body. Issuing both on_headers_complete and on_message_complete callbacks. However
body, issuing both on_headers_complete and on_message_complete callbacks. However
http_parser_execute() will stop parsing at the end of the headers and return.

The user is expected to check if `parser->upgrade` has been set to 1 after
Expand All @@ -126,21 +131,84 @@ There are two types of callbacks:
* notification `typedef int (*http_cb) (http_parser*);`
Callbacks: on_message_begin, on_headers_complete, on_message_complete.
* data `typedef int (*http_data_cb) (http_parser*, const char *at, size_t length);`
Callbacks: (requests only) on_uri,
Callbacks: (requests only) on_url,
(common) on_header_field, on_header_value, on_body;

Callbacks must return 0 on success. Returning a non-zero value indicates
error to the parser, making it exit immediately.

For cases where it is necessary to pass local information to/from a callback,
the `http_parser` object's `data` field can be used.
An example of such a case is when using threads to handle a socket connection,
parse a request, and then give a response over that socket. By instantiation
of a thread-local struct containing relevant data (e.g. accepted socket,
allocated memory for callbacks to write into, etc), a parser's callbacks are
able to communicate data between the scope of the thread and the scope of the
callback in a threadsafe manner. This allows `http_parser` to be used in
multi-threaded contexts.

Example:
```c
typedef struct {
socket_t sock;
void* buffer;
int buf_len;
} custom_data_t;


int my_url_callback(http_parser* parser, const char *at, size_t length) {
/* access to thread local custom_data_t struct.
Use this access save parsed data for later use into thread local
buffer, or communicate over socket
*/
parser->data;
...
return 0;
}

...

void http_parser_thread(socket_t sock) {
int nparsed = 0;
/* allocate memory for user data */
custom_data_t *my_data = malloc(sizeof(custom_data_t));

/* some information for use by callbacks.
* achieves thread -> callback information flow */
my_data->sock = sock;

/* instantiate a thread-local parser */
http_parser *parser = malloc(sizeof(http_parser));
http_parser_init(parser, HTTP_REQUEST); /* initialise parser */
/* this custom data reference is accessible through the reference to the
parser supplied to callback functions */
parser->data = my_data;

http_parser_settings settings; /* set up callbacks */
settings.on_url = my_url_callback;

/* execute parser */
nparsed = http_parser_execute(parser, &settings, buf, recved);

...
/* parsed information copied from callback.
can now perform action on data copied into thread-local memory from callbacks.
achieves callback -> thread information flow */
my_data->buffer;
...
}

```
In case you parse HTTP message in chunks (i.e. `read()` request line
from socket, parse, read half headers, parse, etc) your data callbacks
may be called more than once. Http-parser guarantees that data pointer is only
may be called more than once. `http_parser` guarantees that data pointer is only
valid for the lifetime of callback. You can also `read()` into a heap allocated
buffer to avoid copying memory around if this fits your application.
Reading headers may be a tricky task if you read/parse headers partially.
Basically, you need to remember whether last header callback was field or value
and apply following logic:
and apply the following logic:
(on_header_field and on_header_value shortened to on_h_*)
------------------------ ------------ --------------------------------------------
Expand Down
Loading

0 comments on commit 6ef0c0c

Please sign in to comment.