Skip to content

Commit bdbaf09

Browse files
Add support for building with llhttp instead of http-parser
As http-parser has been unmaintained for a while [1], let's add support for its natural replacement, llhttp. However, as llhttp does not seem to be packaged in distros like Debian [2], we will keep supporting building with http-parser for time being, preferring llhttp, if it is present. [1] nodejs/http-parser#522 [2] https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=977716
1 parent 9e4f9a6 commit bdbaf09

File tree

5 files changed

+53
-18
lines changed

5 files changed

+53
-18
lines changed

.github/workflows/install-dependencies

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ debian:*|ubuntu:*)
1313
echo 'max_parallel_downloads=10' >> /etc/dnf/dnf.conf
1414
dnf -y clean all
1515
dnf -y --setopt=deltarpm=0 update
16-
dnf -y install gcc meson pkgconfig libjose-devel jose http-parser-devel \
16+
dnf -y install gcc meson pkgconfig libjose-devel jose llhttp-devel \
1717
systemd gcovr curl socat iproute
1818
;;
1919

meson.build

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,13 +55,22 @@ add_project_arguments('-DVERSION="'+meson.project_version() + '"', language : 'c
5555
jose = dependency('jose', version: '>=8')
5656
a2x = find_program('a2x', required: false)
5757
compiler = meson.get_compiler('c')
58-
if not compiler.has_header('http_parser.h',args : '-I/usr/local/include')
59-
error('http-parser devel files not found.')
58+
59+
http_lib = []
60+
if compiler.has_header('llhttp.h', args: '-I/usr/local/include')
61+
http_lib = 'llhttp'
62+
add_project_arguments('-DUSE_LLHTTP', language: 'c')
63+
else
64+
if not compiler.has_header('http_parser.h', args: '-I/usr/local/include')
65+
error('neither llhttp nor http-parser devel files found.')
66+
endif
67+
http_lib = 'http_parser'
6068
endif
69+
6170
if host_machine.system() == 'freebsd'
62-
http_parser = compiler.find_library('http_parser',dirs : '/usr/local/lib')
71+
http_parser = compiler.find_library(http_lib, dirs : '/usr/local/lib')
6372
else
64-
http_parser = compiler.find_library('http_parser')
73+
http_parser = compiler.find_library(http_lib)
6574
endif
6675

6776
licenses = ['COPYING']

src/http.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ HTTP_METHOD_MAP(XX)
3636
};
3737

3838
static int
39-
on_url(http_parser *parser, const char *at, size_t length)
39+
on_url(http_parser_t *parser, const char *at, size_t length)
4040
{
4141
struct http_state *state = parser->data;
4242

@@ -51,7 +51,7 @@ on_url(http_parser *parser, const char *at, size_t length)
5151
}
5252

5353
static int
54-
on_body(http_parser *parser, const char *at, size_t length)
54+
on_body(http_parser_t *parser, const char *at, size_t length)
5555
{
5656
struct http_state *state = parser->data;
5757

@@ -66,7 +66,7 @@ on_body(http_parser *parser, const char *at, size_t length)
6666
}
6767

6868
static int
69-
on_message_complete(http_parser *parser)
69+
on_message_complete(http_parser_t *parser)
7070
{
7171
struct http_state *state = parser->data;
7272
const char *addr = NULL;
@@ -132,15 +132,15 @@ on_message_complete(http_parser *parser)
132132
return 0;
133133
}
134134

135-
const http_parser_settings http_settings = {
135+
const http_settings_t http_settings = {
136136
.on_url = on_url,
137137
.on_body = on_body,
138138
.on_message_complete = on_message_complete,
139139
};
140140

141141
int
142142
http_reply(const char *file, int line,
143-
enum http_status code, const char *fmt, ...)
143+
http_status_t code, const char *fmt, ...)
144144
{
145145
const char *msg = NULL;
146146
va_list ap;

src/http.h

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,27 @@
1919

2020
#pragma once
2121

22-
#include <http_parser.h>
2322
#include <sys/types.h>
2423
#include <regex.h>
2524

25+
#ifdef USE_LLHTTP
26+
#include <llhttp.h>
27+
28+
typedef llhttp_method_t http_method_t;
29+
typedef llhttp_status_t http_status_t;
30+
typedef llhttp_settings_t http_settings_t;
31+
typedef llhttp_t http_parser_t;
32+
#else
33+
#include <http_parser.h>
34+
/* Legacy http-parser. */
35+
typedef enum http_method http_method_t;
36+
typedef enum http_status http_status_t;
37+
typedef http_parser_settings http_settings_t;
38+
typedef struct http_parser http_parser_t;
39+
#endif /* USE_LLHTTP */
40+
2641
struct http_dispatch {
27-
int (*func)(enum http_method method, const char *path,
42+
int (*func)(http_method_t method, const char *path,
2843
const char *body, regmatch_t matches[], void *misc);
2944
uint64_t methods;
3045
size_t nmatches;
@@ -43,11 +58,11 @@ struct http_state {
4358
void *misc;
4459
};
4560

46-
extern const http_parser_settings http_settings;
61+
extern const http_settings_t http_settings;
4762

4863
int __attribute__ ((format(printf, 4, 5)))
4964
http_reply(const char *file, int line,
50-
enum http_status code, const char *fmt, ...);
65+
http_status_t code, const char *fmt, ...);
5166

5267
#define http_reply(code, ...) \
5368
http_reply(__FILE__, __LINE__, code, __VA_ARGS__)

src/tangd.c

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ str_cleanup(char **str)
6464
}
6565

6666
static int
67-
adv(enum http_method method, const char *path, const char *body,
67+
adv(http_method_t method, const char *path, const char *body,
6868
regmatch_t matches[], void *misc)
6969
{
7070
__attribute__((cleanup(str_cleanup))) char *adv = NULL;
@@ -101,7 +101,7 @@ adv(enum http_method method, const char *path, const char *body,
101101
}
102102

103103
static int
104-
rec(enum http_method method, const char *path, const char *body,
104+
rec(http_method_t method, const char *path, const char *body,
105105
regmatch_t matches[], void *misc)
106106
{
107107
__attribute__((cleanup(str_cleanup))) char *enc = NULL;
@@ -197,13 +197,18 @@ static int
197197
process_request(const char *jwkdir, int in_fileno)
198198
{
199199
struct http_state state = { .dispatch = dispatch, .misc = (char*)jwkdir };
200-
struct http_parser parser = { .data = &state };
200+
http_parser_t parser;
201201
struct stat st = {};
202202
char req[4096] = {};
203203
size_t rcvd = 0;
204204
int r = 0;
205205

206+
#ifdef USE_LLHTTP
207+
llhttp_init(&parser, HTTP_REQUEST, &http_settings);
208+
#else
206209
http_parser_init(&parser, HTTP_REQUEST);
210+
#endif
211+
parser.data = &state;
207212

208213
if (stat(jwkdir, &st) != 0) {
209214
fprintf(stderr, "Error calling stat() on path: %s: %m\n", jwkdir);
@@ -224,17 +229,23 @@ process_request(const char *jwkdir, int in_fileno)
224229

225230
rcvd += r;
226231

232+
#ifdef USE_LLHTTP
233+
r = llhttp_execute(&parser, req, rcvd);
234+
if (parser.error != 0) {
235+
fprintf(stderr, "HTTP Parsing Error: %s\n",
236+
llhttp_errno_name(parser.error));
237+
#else
227238
r = http_parser_execute(&parser, &http_settings, req, rcvd);
228239
if (parser.http_errno != 0) {
229240
fprintf(stderr, "HTTP Parsing Error: %s\n",
230241
http_errno_description(parser.http_errno));
242+
#endif
231243
return EXIT_SUCCESS;
232244
}
233245

234246
memmove(req, &req[r], rcvd - r);
235247
rcvd -= r;
236248
}
237-
238249
return EXIT_SUCCESS;
239250
}
240251

0 commit comments

Comments
 (0)