@@ -3,38 +3,167 @@
3 * package. It is intended to read one HTTP request after another
3 * package. It is intended to read one HTTP request after another
4 * from a file, nothing more.
4 * from a file, nothing more.
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.
6 * For the http-parser source, see http://github.com/ry/http-parser/
11 * For the http-parser source, see http://github.com/ry/http-parser/
15+ * Turn off this preprocessor symbol to have the callbacks do nothing
16+ * at all, which "improves performance" by about 50%.
8#include <fcntl.h>
21#include <fcntl.h>
9#include <stdio.h>
22#include <stdio.h>
10#include <sys/stat.h>
25#include <sys/stat.h>
11#include <sys/types.h>
26#include <sys/types.h>
12#include <unistd.h>
27#include <unistd.h>
14#include "http_parser.h"
29#include "http_parser.h"
16−int begin(http_parser *p)
31+struct http_string {
37+ struct http_string *name;
38+ struct http_string *value;
39+ struct http_header *next;
43+ struct http_string *method;
44+ struct http_string *uri;
45+ struct http_header *headers, *last;
48+static void *xmalloc(size_t size)
52+ if ((ptr = malloc(size)) == NULL) {
60+static struct http_string *xstrdup(const char *src, size_t len, size_t extra)
62+ struct http_string *dst = xmalloc(sizeof(*dst) + len + extra);
63+ memcpy(dst->value, src, len);
68+static void xstrcat(struct http_string **dst, const char *src, size_t len)
70+ struct http_string *p;
73+ *dst = xstrdup(src, len, 0);
77+ p = xstrdup((*dst)->value, (*dst)->len, len);
78+ memcpy(p->value + (*dst)->len, src, len);
84+static int begin(http_parser *p)
87+ struct http_request *req = xmalloc(sizeof(*req));
21−int url(http_parser *p, const char *at, size_t len)
100+static int url(http_parser *p, const char *at, size_t len)
103+ struct http_request *req = p->data;
105+ xstrcat(&req->uri, at, len);
23 return 0;
108 return 0;
26−int header_field(http_parser *p, const char *at, size_t len)
111+static int header_field(http_parser *p, const char *at, size_t len)
114+ struct http_request *req = p->data;
116+ if (req->last && req->last->value == NULL) {
117+ xstrcat(&req->last->name, at, len);
119+ struct http_header *hdr = xmalloc(sizeof(*hdr));
121+ hdr->name = xstrdup(at, len, 0);
126+ req->last->next = hdr;
128+ if (req->headers == NULL)
28 return 0;
133 return 0;
31−int header_value(http_parser *p, const char *at, size_t len)
136+static int header_value(http_parser *p, const char *at, size_t len)
139+ struct http_request *req = p->data;
141+ xstrcat(&req->last->value, at, len);
33 return 0;
144 return 0;
36−int complete(http_parser *p)
147+static int complete(http_parser *p)
150+ struct http_request *req = p->data;
151+ struct http_header *hdr, *next;
156+ for (hdr = req->headers; hdr != NULL; hdr = next) {
38 /* Bludgeon http_parser into understanding that we really want to
167 /* Bludgeon http_parser into understanding that we really want to
39 * keep parsing after a request that in principle ought to close
168 * keep parsing after a request that in principle ought to close
40 * the "connection". */
169 * the "connection". */
@@ -43,10 +172,11 @@ int complete(http_parser *p)
43 p->http_minor = 1;
172 p->http_minor = 1;
44 p->flags &= ~6;
173 p->flags &= ~6;
46 return 0;
176 return 0;
49−void parse(const char *path, int fd)
179+static void parse(const char *path, int fd)
51 http_parser p;
181 http_parser p;
52 ssize_t nread;
182 ssize_t nread;
@@ -72,7 +202,6 @@ void parse(const char *path, int fd)
72 } while (nread > 0);
202 } while (nread > 0);
76int main(int argc, char **argv)
205int main(int argc, char **argv)
@@ -91,3 +220,9 @@ int main(int argc, char **argv)
92 return 0;
221 return 0;
226+ * c-file-style: "stroustrup"