http_parse使用与学习

2023-05-16

最近学习了下http_parse解析库,是nginx的一个解析http库, 在解析的过程中,它不会调用任何系统调用,不会在HEAP上申请内存,不会缓存数据,并且可以在任意时刻打断解析过程,而不会产生任何影响。在解析http的时候使用http_parse可以大幅度提高效率(Ps:当然一些开源的库也是比较好用的。如果你写的是基础框架类,那么使用这个库是再好不过了)。

本文主要分为两部分学习。第一部分简单了解http的一些基本知识。第二部分简单学习http_parse库使用

第一部分:http基本知识

1.http的请求格式包括 request line、Request header、空行、Body。如果是get方法则不包含body。

2.url解释


schema://host[:port#]/path/.../[?query-string][#anchor]  

scheme               指定低层使用的协议(例如:http, https, ftp)

host                   HTTP服务器的IP地址或者域名

port#                 HTTP服务器的默认端口是80,这种情况下端口号可以省略。如果使用了别的端口,必须指明,例如 http://www.cnblogs.com:8080/

path                   访问资源的路径

query-string       发送给http服务器的数据

anchor-             锚

 

举例:


http://www.mywebsite.com/sj/test/test.aspx?name=sviergn&x=true#stuff

Schema:                 http
host:                   www.mywebsite.com
path:                   /sj/test/test.aspx
Query String:           name=sviergn&x=true
Anchor:                 stuff  

网上有很多http相关的学习博客或者文档。这里就不多余的阐述了

第二部分 http_parse使用

//设置回调函数
http_parser_settings settings_null;
settings_null.on_message_begin = on_message_begin;
settings_null.on_header_field = on_header_field;
settings_null.on_header_value = on_header_value;
settings_null.on_url = on_url;
settings_null.on_status = 0;
settings_null.on_body = on_body;
settings_null.on_headers_complete = on_headers_complete;
settings_null.on_message_complete = on_message_complete;
// 为结构体申请内存
http_parser *parser = malloc(sizeof(http_parser));
// 初始化解析器
http_parser_init(parser, HTTP_REQUEST);
//开始解析
parsed = http_parser_execute(parser, &settings_null, buf, strlen(buf));

在回调中可以进行处理。如果是解析回包设置HTTP_RESPONSE。使用还是很简单的。

下面看看http_parse结构。存放一些用于管理得状态

struct http_parser {
  /** PRIVATE **/                                                                                                       
  unsigned int type : 2;         /* enum http_parser_type */
  unsigned int flags : 8;        /* F_* values from 'flags' enum; semi-public */
  unsigned int state : 7;        /* enum state from http_parser.c */
  unsigned int header_state : 7; /* enum header_state from http_parser.c */
  unsigned int index : 7;        /* index into current matcher */
  unsigned int lenient_http_headers : 1;
 
  uint32_t nread;          /* # bytes read in various scenarios */
  uint64_t content_length; /* # bytes in body (0 if no Content-Length header) */
 
  /** READ-ONLY **/
  unsigned short http_major;
  unsigned short http_minor;
  unsigned int status_code : 16; /* responses only */
  unsigned int method : 8;       /* requests only */
  unsigned int http_errno : 7;
 
  /* 1 = Upgrade header was present and the parser has exited because of that.
   * 0 = No upgrade header present.
   * Should be checked when http_parser_execute() returns in addition to
   * error checking.
   */
  unsigned int upgrade : 1;
 
  /** PUBLIC **/
  void *data; /* A pointer to get hook to the "connection" or "socket" object */
};

看看http_parser_settings,里面的每一个变量其实都是回调地址

struct http_parser_settings {
  http_cb      on_message_begin;
  http_data_cb on_url;
  http_data_cb on_status;
  http_data_cb on_header_field;
  http_data_cb on_header_value;
  http_cb      on_headers_complete;
  http_data_cb on_body;
  http_cb      on_message_complete;
  /* When on_chunk_header is called, the current chunk length is stored
   * in parser->content_length.
   */
  http_cb      on_chunk_header;
  http_cb      on_chunk_complete;                                                                                       
};

typedef int (*http_data_cb) (http_parser*, const char *at, size_t length);                                              
typedef int (*http_cb) (http_parser*);
 

在调用http_parser_execute解析的时候,根据enum state来进行阶段性处理(有点类似状态机,把解析http看做一个流程。一步一步扭转状态以及解析)

http_parse中还有一个结构可以方便的进行url格式解析。先上代码

    struct http_parser_url u;
    if(0 == http_parser_parse_url(url, strlen(url), 0, &u))
    {
        if(u.field_set & (1 << UF_PORT))
        {
            httpc->port = u.port;
        }
        else
        {
            httpc->port = 80;
        }
        
        if(httpc->host) free(httpc->host);
        if(u.field_set & (1 << UF_HOST) )
        {
            httpc->host = (char*)malloc(u.field_data[UF_HOST].len+1);
            strncpy(httpc->host, url+u.field_data[UF_HOST].off, u.field_data[UF_HOST].len);
            httpc->host[u.field_data[UF_HOST].len] = 0;
        }

        if(httpc->path) free(httpc->path);
        if(u.field_set & (1 << UF_PATH))
        {
            httpc->path = (char*)malloc(u.field_data[UF_PATH].len+1);
            strncpy(httpc->path, url+u.field_data[UF_PATH].off, u.field_data[UF_PATH].len);
            httpc->path[u.field_data[UF_PATH].len] = 0;
        }

        return 0;
    }

struct http_parser_url结构其实很简单

struct http_parser_url {
  uint16_t field_set;           /* Bitmask of (1 << UF_*) values */
  uint16_t port;                /* Converted UF_PORT string */
  
  struct {
    uint16_t off;               /* Offset into buffer in which field starts */
    uint16_t len;               /* Length of run in buffer */
  } field_data[UF_MAX];
};

通过field_set来可以判断field是否被设置。field有如下bit

enum http_parser_url_fields
  { UF_SCHEMA           = 0                                                                                             
  , UF_HOST             = 1
  , UF_PORT             = 2
  , UF_PATH             = 3
  , UF_QUERY            = 4
  , UF_FRAGMENT         = 5
  , UF_USERINFO         = 6
  , UF_MAX              = 7
  };

使用u.field_set & (1 << UF_PORT或者u.field_set & (1 << UF_HOST)或者。。。可以判断字段是否设置取得字段可以使用field_data+off来得到。比如u.field_data[UF_HOST].off。http_parser_parse_url的解析就是纯字符串解析了。有兴趣可以看看源码。

总结:http_parse主要使用c来写的。下面可以再接着研究下fast-http的源码以及使用。好记性不如烂笔头。如有不对大家可以一起探讨


 

 

转载于:https://my.oschina.net/sosomywork/blog/3003653

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

http_parse使用与学习 的相关文章

  • URL 真的可以被视为 HTTP 响应的唯一密钥吗? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 这个问题既可以看作是实践问题 也可以看作是理论问题 我正在设计一个涉及 HTTP 客户端 Flash Player 应用程序 和 HT
  • 如何使用服务更改作用域变量?

    我有一个应用程序 应用程序内部有一个注册和登录表单 通过注册表单 当用户创建帐户时 他们会自动登录 通过登录表单 用户也可以登录 显然 我有两个控制器 一个用于注册表单 一个用于登录表单 我希望他们能够共享一个服务 logIn 因为两种形式
  • 数据融合 - http post 插件问题

    我正在尝试使用 DataFusion 进行 http 调用 来源 GCS csv 文件 接收器 HTTP POST API 期望该文件作为 HTTP 请求的一部分 执行此操作后 我在 API 日志中收到以下错误 所需的请求部分 文件 不存在
  • 允许获取请求但仅在我的域中?

    在我的网站上 我可以使用 GET 请求触发某些操作 例如隐藏或删除评论的功能 我不是很担心 但如果有人使用 img src url 设计攻击来删除评论或电子邮件 那会很烦人 有办法防止这种情况吗 我使用 httponlycookies 作为
  • 如何获取http重定向状态码

    我想记录 301 与 302 但找不到读取 Client Do Get doFollowingRedirects CheckRedirect 中的响应状态代码的方法 我必须自己实施重定向才能实现此目的吗 The http Client ht
  • 重定向后,curl 对所有请求使用 POST

    根据文档和一些类似的问题 SOcurl 应该遵循使用 GET 方法的重定向 除非将 post30x 指定为参数 但这是我测试的结果 curl kvv b tmp tmp BEo6w3GKDq c tmp tmp BEo6w3GKDq X P
  • 如何让 Symfony 2 采用协议方案(http vs https)

    我有一个 Symfony 2 网站 在开发中运行在 HTTP 上 在生产中运行在 HTTPS 上 我注意到在生产中 Symfony 生成的 URL 仍然全部呈现为 HTTP 我怎么也可以 让框架采用当前提供网站的协议 可能是首选 或者 仅在
  • Android Http 获取会话 Cookie

    我本来不想在这里发帖 因为网上有太多信息 但我已经深入搜寻但无法弄清楚 好吧 所以我无法让它在两种情况下工作 希望这两种情况的答案是相同的 我的问题是我设置了请求标头 但它似乎没有发送它 我有一个会话 id s e32ff223fwefd3
  • AJAX 中的 GET 与 POST?

    为什么 AJAX 中有 GET 和 POST 请求 因为它无论如何都不影响页面 URL 由于数据未反映到页面 URL 因此通过 AJAX 中的 GET 传递敏感数据有何区别 您应该根据您的 Web 服务要求使用正确的 HTTP 动词 当处理
  • 让请求在curl中工作,但在Python中不起作用

    我正在尝试使用curl 制作一个 put 方法 一切正常 并且我得到了JSON curl X PUT d foo more foo http ip 6001 whatever api key whatever 但是在使用python时由于某
  • Python http.client.RemoteDisconnected

    尝试使用 python 通过 Web 服务运行多个 ID 我收到 http client RemoteDisconnected 远程端关闭连接而没有响应 错误 我不想尝试 捕获此错误 我想调查为什么会收到此响应 我已经能够得到 400 和
  • 为什么我的 Android HttpClient 在调用 Execute 时不发送参数?

    我有一个AsyncTask设置创建一个AndroidHttpClient并打电话Execute 有一个HttpPost and BasicHttpContext我提供的对象 我设置了HttpPost像这样 HttpPost myPost n
  • 使用 netcat 提供包含图像的 HTTP 响应

    我正在尝试使用 netcat 编写一个小型 HTTP 服务器 对于纯文本文件 这工作正常 但当我尝试发送图片时 浏览器仅显示损坏图像的图标 我所做的就是提取所请求文件的 mime 类型和大小 并将其发送给客户端 我的示例图片的请求标头如下所
  • 为什么 Python 3 http.client 比 python-requests 快这么多?

    我今天测试了不同的 Python HTTP 库 我意识到http client https docs python org 3 library http client html库的执行速度似乎比requests http docs pyth
  • 如何用 Java 以编程方式下载网页

    我希望能够获取网页的 html 并将其保存到String 这样我就可以对其进行一些处理 另外 我如何处理各种类型的压缩 我将如何使用 Java 来做到这一点 我会使用像样的 HTML 解析器Jsoup http jsoup org 那么就很
  • 如何使用 Jade 和 Node.js 迭代 JSON 数组

    所以我有这个 JSON 数组apiData被传递到视图作为data Backend router get function req res var data JSON stringify apiData res render gallery
  • video 元素发送多个网络请求

    我有一个带有 mp4 源的视频元素
  • IIS7 和 HTTP 状态代码处理

    我因试图对 IIS7 集成模式 中的错误呈现进行完整的编程控制而感到非常头疼 我想要做的是给出一个错误 找不到页面 内部服务器错误 未经过身份验证等 将整个请求传输到自定义 ASPX 或 HTML 我更喜欢后者 并使用正确的 HTTP 状态
  • (Flutter) HTTPClient 参数无效:URI 中未指定主机

    目前正在开发一个小应用程序 允许用户查看存储在 Heroku 上的数据库 但是在使用数据库的 URL herokuapp com api 时 我遇到了上述问题 var client createHttpClient var response
  • 如何在 ASP.NET Core 控制器中接收“multipart/mixed”

    旧系统会向我发送以下内容 POST xml HTTP 1 1 Host localhost 9000 User Agent curl 7 64 1 Accept Content Length 321 Content Type multipa

随机推荐

  • 学习日志5

    最近老师让我阅读了一篇新文章 xff0c 文章标题如下图 文章通过解决时间分配问题以及通过模型预测轮廓同时控制问题控制 xff08 MPCC xff09 优化能够使四旋翼无人机找到最优轨迹 xff0c 可以快速地避障 xff0c 速度甚至可
  • 万字长文 | 阿里大佬 ssp offer 的后台服务器开发学习路线

    前言 小北去年经历春秋招 xff0c 拿到了不少大厂 offer xff0c 其中包括 sp ssp 等 xff0c 感觉在复习准备校招上还是有一定方法的 xff0c 因为我自己是 Linux C C 43 43 路线 所以这一篇的主题是
  • 看完谷歌大佬的刷题笔记, 我直接手撕了200道 Leetcode 算法题

    如果你刷leetcode觉得吃力 那么一定需要这份谷歌大佬的leetcode刷题笔记 在这里推荐一个谷歌大佬的刷题笔记 每一道题的题解都写得非常清楚 作者在美国卡内基梅隆大学攻读硕士学位时 xff0c 为了准备实习秋招 xff0c 他从夏天
  • JVM中的栈区域

    一 栈 xff1a 在JVM中也叫栈内存 xff0c 主要负责java程序的运行 xff0c 栈在线程创建时被创建 xff0c 栈时线程私有的 xff0c 也即每一个线程都有自己的栈空间 xff0c 线程之间的运行不受影响 相互独立 二 栈
  • 初步认识ADRC(自抗扰控制)与应用

    这是一个目录 ADRC的基本原理一 参考资料推荐二 为什么PID好 xff0c 以及 xff0c 为什么PID不够好1 为什么PID好 不依赖于模型的控制器2 为什么PID不够好 PID的缺点 三 ADRC给出的方案 如何保留PID的优点
  • 先进非线性控制方法 INDI 快速部署到PX4用于四旋翼控制(part2)

    目录 一 PX4 v11 的姿态控制解析1 角度环控制2 角速度环控制3 控制分配 二 简易INDI如何部署到PX41 获取角加速度 和 电机转速测量值 xff08 1 xff09 角加速度 xff08 2 xff09 转速 2 具体实现过
  • ubuntu18.04 cv2.VideoCapture无法读取视频

    源代码 xff1a span class token comment 读取视频 span span class token keyword import span cv2 video file span class token operat
  • 关于字符串结束标志‘\0‘的一些见解

    前言 本人是一个刚刚上路的IT新兵 菜鸟 分享一点自己的见解 如果有错误的地方欢迎各位大佬莅临指导 如果这篇文章可以帮助到你 劳请大家点赞转发支持一下 一 39 0 是什么 xff1f 0 是转义字符 xff0c 为了告诉编译器 0 是空字
  • gRPC 基础(二)-- Go 语言版 gRPC-Go

    gRPC Go Github gRPC的Go实现 一个高性能 开源 通用的RPC框架 xff0c 将移动和HTTP 2放在首位 有关更多信息 xff0c 请参阅Go gRPC文档 xff0c 或直接进入快速入门 一 快速入门 本指南通过一个
  • 校验和算法

    原文链接 xff1a http blog chinaunix net uid 26758209 id 3146230 html 校验和算法 经常看计算机网络相关的书时 xff0c 每次看到关于IP或者是UDP报头校验和时 xff0c 都是一
  • PID控制输出PWM核心代码(基于STM32F103)

    注 xff1a 1 如果对于PID控制原理不是很了解 xff0c 可以找些资料看 xff0c 最好先搞懂原理 2 程序中Kp Ki Kd 199 0可根据实际情况自己修改 全局变量 float target 61 30 0 目标温度 flo
  • (已修正精度 1mm左右)Realsense d435i深度相机+Aruco+棋盘格+OpenCV手眼标定全过程记录

    文章目录 2023 5更新 下面为原文 一 前期准备1 1 手眼标定原理1 2 Aruco返回位姿的原理1 3 生成一个Aruco Marker1 4 安装aruco ros包1 5 安装realsense ros包 二 实验环境三 实验过
  • 外贸常用英语词汇

    外贸常用英语词汇 国际贸易 出口信贷 export credit 出口津贴 export subsidy 商品倾销 dumping 外汇倾销 exchange dumping 优惠关税 special preferences 保税仓库 bo
  • Betaflight连接飞控相关问题

    问题描述 xff1a Betaflight连接飞控时 xff0c 若遇到 打开串口失败 xff0c 则为飞控芯片驱动未安装的原因 xff0c 此时 xff0c 在设备管理器中是看不到所连接的硬件的 解决方法 xff1a Betaflight
  • 嵌入式软件开发------指针和内存释放的问题分析

    指针和内存的问题关于指针分配是否要delete的问题 1 请大家在使用指针变量时遵守以下几点 xff0c 可以让你们在编程时 少许多的麻烦 xff0c 以下假设p为某个类型的指针变量 1 定义指针 xff1a a 定义指针变量时赋初值为ty
  • 记录下Qt各版本的下载地址,便于后期查找及下载

    记录下Qt各版本的下载地址 xff0c 便于后期查找及下载 1 所有Qt版本下载地址 xff1a http download qt io archive qt 2 所有Qt Creator下载地址 xff1a http download q
  • 计算机网络 -- RS232接口 ----OSI物理层协议----RS232接口

    个人计算机上的通讯接口之一 xff0c 由电子工业协会 Electronic Industries Association xff0c EIA 所制定的异步传输标准接口 是目前使用最广泛的串行物理接口 xff0c 必须理解 xff1a 1
  • 来自一个前端大神转产品经理后的聊天感悟

    给的学习建议 xff1a 1 推荐给我一本书 锋利的jQuery 2 学会使用思维导图工具 3 课余时间学习理财 4 研发过程中 xff0c 多多留心一些交互 xff0c 自己完善反复琢磨自己的思路 xff08 保证是最简的 xff09 5
  • 算法竞赛入门经典(第二版)-刘汝佳-第三章 数组与字符串 例题+习题(17/18)

    文章目录 说明例题例3 1 UVA 272 TeX 中的引号例3 2 UVA 10082 WERTYU例3 3 UVA 401 回文词例3 4 UVA 340 猜数字游戏的提示例3 5 UVA 1583 生成元例3 6 UVA 1584 环
  • http_parse使用与学习

    最近学习了下http parse解析库 xff0c 是nginx的一个解析http库 xff0c 在解析的过程中 xff0c 它不会调用任何系统调用 xff0c 不会在HEAP上申请内存 xff0c 不会缓存数据 xff0c 并且可以在任意