2 * This is a simple driver for the http-parser package. It is
3 * intended to read one HTTP request after another from a file,
6 * For "feature parity" with the Haskell code in RFC2616.hs, we
7 * allocate and populate a simple structure describing each request,
8 * since that's the sort of thing that many real applications would
9 * themselves do and the library doesn't do this for us.
11 * For the http-parser source, see
12 * https://github.com/joyent/http-parser/blob/master/http_parser.c
16 * Turn off this preprocessor symbol to have the callbacks do nothing
17 * at all, which "improves performance" by about 50%.
30#include "http_parser.h"
38 struct http_string *name;
39 struct http_string *value;
40 struct http_header *next;
44 struct http_string *method;
45 struct http_string *uri;
46 struct http_header *headers, *last;
51 struct http_request req;
54static void *xmalloc(size_t size)
58 if ((ptr = malloc(size)) == NULL) {
66static struct http_string *xstrdup(const char *src, size_t len, size_t extra)
68 struct http_string *dst = xmalloc(sizeof(*dst) + len + extra);
69 memcpy(dst->value, src, len);
74static void xstrcat(struct http_string **dst, const char *src, size_t len)
76 struct http_string *p;
79 *dst = xstrdup(src, len, 0);
83 p = xstrdup((*dst)->value, (*dst)->len, len);
84 memcpy(p->value + (*dst)->len, src, len);
90static int begin(http_parser *p)
92 struct data *data = p->data;
99static int url(http_parser *p, const char *at, size_t len)
102 struct data *data = p->data;
104 xstrcat(&data->req.uri, at, len);
110static int header_field(http_parser *p, const char *at, size_t len)
113 struct data *data = p->data;
115 if (data->req.last && data->req.last->value == NULL) {
116 xstrcat(&data->req.last->name, at, len);
118 struct http_header *hdr = xmalloc(sizeof(*hdr));
120 hdr->name = xstrdup(at, len, 0);
124 if (data->req.last != NULL)
125 data->req.last->next = hdr;
126 data->req.last = hdr;
127 if (data->req.headers == NULL)
128 data->req.headers = hdr;
135static int header_value(http_parser *p, const char *at, size_t len)
138 struct data *data = p->data;
140 xstrcat(&data->req.last->value, at, len);
146static int complete(http_parser *p)
149 struct data *data = p->data;
150 struct http_header *hdr, *next;
152 free(data->req.method);
155 for (hdr = data->req.headers; hdr != NULL; hdr = next) {
163 data->req.method = NULL;
164 data->req.uri = NULL;
165 data->req.headers = NULL;
166 data->req.last = NULL;
169 /* Bludgeon http_parser into understanding that we really want to
170 * keep parsing after a request that in principle ought to close
171 * the "connection". */
172 if (!http_should_keep_alive(p)) {
181static void parse(const char *path, int fd)
184 http_parser_settings s;
188 memset(&s, 0, sizeof(s));
189 s.on_message_begin = begin;
191 s.on_header_field = header_field;
192 s.on_header_value = header_value;
193 s.on_message_complete = complete;
197 http_parser_init(&p, HTTP_REQUEST);
200 data.req.method = NULL;
202 data.req.headers = NULL;
203 data.req.last = NULL;
206 char buf[HTTP_MAX_HEADER_SIZE];
209 nread = read(fd, buf, sizeof(buf));
211 np = http_parser_execute(&p, &s, buf, nread);
213 fprintf(stderr, "%s: parse failed\n", path);
218 printf("%ld\n", (unsigned long) data.count);
221int main(int argc, char **argv)
225 for (i = 1; i < argc; i++) {
228 fd = open(argv[i], O_RDONLY);
242 * c-file-style: "stroustrup"
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list