如何使用 llhttp

llhttpNode.js v12 以上版本使用的 HTTP 解析器,代替了旧版的 http_parser。根据官方宣传,相较于旧版解析器,新版本解析器性能提升了 156%。llhttp 的主要代码由 Typescript 实现,描述了一个有限状态机,最终通过 llparse 将代码转换成 C 语言源代码。然而官方文档里根本没写如何生成 C 语言代码,只能自己探索了。

首先 clone 下 llhttp 的代码:

shellgit clone https://github.com/nodejs/llhttp

在项目根目录下能找到 Makefile 配置文件。打开看了下,并不是很复杂。这个 Makefile 配置仅支持 clang 编译器 和 Linux 操作系统。不过我们只需要生成 C 语言代码的部分就行了。

找到 Makefilegenerate: 一节:

makefilegenerate:
	npx ts-node bin/generate.ts

原来只要执行 bin 目录下的 generate.ts 就能生成 C 语言代码了。在此之前需要先安装 Node.js 环境。

在项目根目录下执行命令:

shellnpm i
npx ts-node bin/generate.ts

构建成功后,会在项目 build 目录下创建 llhttp.hc/llhttp.c 两个文件。再加上项目 src/native 目录下的 api.capi.hhttp.c 三个 C 源代码文件,就是完整的 llhttp 源代码了。

此外,也可以在 pyllhttp 项目中找到生成好的全部 C 源代码。只不过这里的代码并不是最新版本的。

测试代码:

c#include <stdio.h>
#include <string.h>
#include "llhttp/llhttp.h"

#define URL_MAX_LEN 2048

int handle_url(llhttp_t* parser, const char* at, size_t length)
{
    char url[URL_MAX_LEN];
    strncpy_s(url, URL_MAX_LEN, at, length);
    printf("URL: %s", url);
    return 0;
}

int main()
{
    llhttp_t parser;
    llhttp_settings_t settings;
    llhttp_settings_init(&settings);
    llhttp_init(&parser, HTTP_BOTH, &settings);

    settings.on_url = handle_url;

    const char* request = "GET /index.html HTTP/1.1\r\n\r\n";
    int request_len = strlen(request);

    enum llhttp_errno err = llhttp_execute(&parser, request, request_len);
    if (err == HPE_OK) {
        /* Successfully parsed! */
    }
    else {
        fprintf(stderr, "Parse error: %s %s\n", llhttp_errno_name(err),
            parser.reason);
    }

    return 0;
}