c - 将缓冲区传递给 picohttpparser 会导致编译错误

标签 c http parsing

我一直在尝试获取 picohttpparser工作,但我所有的努力都是徒劳的。我正在努力开始的基本上是将“手动”缓冲区传递给 picohttpparser 来解析它。这是来自官方项目页面的示例:

char buf[4096], *method, *path;
int pret, minor_version;
struct phr_header headers[100];
size_t buflen = 0, prevbuflen = 0, method_len, path_len, num_headers;
ssize_t rret;

while (1) {
    /* read the request */
    while ((rret = read(sock, buf + buflen, sizeof(buf) - buflen)) == -1 && errno == EINTR)
        ;
    if (rret <= 0)
        return IOError;
    prevbuflen = buflen;
    buflen += rret;
    /* parse the request */
    num_headers = sizeof(headers) / sizeof(headers[0]);
    pret = phr_parse_request(buf, buflen, &method, &method_len, &path, &path_len,
                             &minor_version, headers, &num_headers, prevbuflen);
    if (pret > 0)
        break; /* successfully parsed the request */
    else if (pret == -1)
        return ParseError;
    /* request is incomplete, continue the loop */
    assert(pret == -2);
    if (buflen == sizeof(buf))
        return RequestIsTooLongError;
}

printf("request is %d bytes long\n", pret);
printf("method is %.*s\n", (int)method_len, method);
printf("path is %.*s\n", (int)path_len, path);
printf("HTTP version is 1.%d\n", minor_version);
printf("headers:\n");
for (i = 0; i != num_headers; ++i) {
    printf("%.*s: %.*s\n", (int)headers[i].name_len, headers[i].name,
           (int)headers[i].value_len, headers[i].value);
}

尽管如此,它涉及太多,我感到迷茫,所以我开始做一个简单的缓冲区,用这段代码传递给解析器:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "picohttpparser.h"



int main(int argc, char **argv)
{
    /* simple buffer */
    char rret[58]="GET /tutorials/other/top-20-mysql-best-practices/ HTTP/1.1";

    /* parse the request */
    phr_parse_request(rret, 58, "GET", 3);

    return 0;
}

问题是我不断收到此错误:

parsebuf.c: In function ‘main’:
parsebuf.c:14:33: warning: passing argument 3 of ‘phr_parse_request’ from incompatible pointer type [-Wincompatible-pointer-types]
     phr_parse_request(rret, 58, "GET", 3);
                                 ^~~~~
In file included from parsebuf.c:4:0:
picohttpparser.h:53:5: note: expected ‘const char **’ but argument is of type ‘char *’
 int phr_parse_request(const char *buf, size_t len, const char **method, size_t *method_len, const char **path, size_t *path_len,
     ^~~~~~~~~~~~~~~~~
parsebuf.c:14:40: warning: passing argument 4 of ‘phr_parse_request’ makes pointer from integer without a cast [-Wint-conversion]
     phr_parse_request(rret, 58, "GET", 3);
                                        ^
In file included from parsebuf.c:4:0:
picohttpparser.h:53:5: note: expected ‘size_t * {aka long unsigned int *}’ but argument is of type ‘int’
 int phr_parse_request(const char *buf, size_t len, const char **method, size_t *method_len, const char **path, size_t *path_len,
     ^~~~~~~~~~~~~~~~~
parsebuf.c:14:5: error: too few arguments to function ‘phr_parse_request’
     phr_parse_request(rret, 58, "GET", 3);
     ^~~~~~~~~~~~~~~~~
In file included from main.c:4:0:
picohttpparser.h:53:5: note: declared here
 int phr_parse_request(const char *buf, size_t len, const char **method, size_t *method_len, const char **path, size_t *path_len,
     ^~~~~~~~~~~~~~~~~

我哪里可能错了?或者,是否有比项目网站上的例子更直接的例子?

最佳答案

我去了他们的 github 页面,这是他们在代码之前所说的:

The example below reads an HTTP request from socket sock using read(2), parses it using phr_parse_request, and prints the details.

phr_parse_request 函数解析向服务器发出的请求,因此它需要 写什么样的请求(GET,POST,DELETE等),这就是为什么函数 需要一个 const char**

函数如下所示:

int phr_parse_request(const char *buf_start, size_t len, const char **method, size_t *method_len, const char **path,
size_t *path_len, int *minor_version, struct phr_header *headers, size_t *num_headers, size_t last_len)

参数都是指针,因为phr_parse_request会改变where 这些变量 (method, path) 指向,这就是为什么你不需要 初始化它们或为其分配内存。

因此您必须像示例中那样声明变量:

int main(void)
{
    char *method, *path;
    size_t buflen = 0, method_len, path_len, num_headers;
    struct phr_header headers[100];
    int pret, minor_version;

    char request[] = "GET /tutorials/other/top-20-mysql-best-practices/ HTTP/1.1\r\nHost: ....";

    num_headers = sizeof(headers) / sizeof(headers[0]);

    pret = phr_parse_request(request, strlen(request), &method, &method_len, &path, &path_len,
                             &minor_version, headers, &num_headers, 0);

    if(pret > 0)
    {
        // success
        // method has the request methid,
        // method_len the length of (I presume they don't write the 0
        // terminating byte
        // etc.
    }

    ...
}

唯一不明白的是prevbuflen的意思,就是用 作为示例中的最后一个参数。可悲的是没有文件(或在 至少我找不到)。但是从bench.c来看上的文件 存储库,该值可以为 0。查看 that file ,这就是“快速& dirty”示例,而无需编写网络支持。将该文件用于 你的实验。

关于c - 将缓冲区传递给 picohttpparser 会导致编译错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49906017/

相关文章:

html - 在 Go 中解析 HTML 输入标签

html - 如何在没有 JavaScript 的情况下清除已经发送到浏览器的 HTML 内容?

Node.js 管道 http 请求和 promise

android - 在 Android 中处理 POST 请求

c - 在具有换行符 : how to read all lines? 的缓冲区上使用 sscanf

c - 写入/访问I/O端口硬件看门狗寄存器linux

c - 解释包含结构的 union 的 sizeof 运算符的结果

c++ - 从一端关闭的管道或套接字对读取直到达到 EOF 是否安全?

c - 文件中声明的结构内的结构无法访问内部结构

java - 解释对多个 XML 文档应用多个 xpath 查询的规则