在github有轮子http-parser解析器,小的就不再造轮子了,哈哈(造这个轮子真不是一时半会的事)。目前该解析器用于nodejs的http解析,另还有大家熟知的tcpflow 以及 libtnet都以他作为引擎。
http-parser地址:http-parser
http-parser是一个用C代码编写的HTTP消息解析器。可以解析HTTP请求或者回应消息。 这个解析器常常在高性能的HTTP应用中使用。 在解析的过程中,它不会调用任何系统调用,不会在HEAP上申请内存,不会缓存数据,并且可以在任意时刻打断解析过程,而不会产生任何影响。 对于每个HTTP消息(在WEB服务器中就是每个请求),它只需要40字节的内存占用(解析器本身的基本数据结构),不过最终的要看你实际的代码架构。
特性:
无第三方依赖
可以处理持久消息(keep-alive)
支持解码chunk编码的消息
支持Upgrade协议升级(如无例外就是WebSocket)
可以防御缓冲区溢出攻击
解析器可以处理以下类型的HTTP消息:
头部的字段和值
Content-Length
请求方法
返回的HTTP代码
Transfer-Encoding
HTTP版本
请求的URL
HTTP消息主体
分为3步:
1、初始化参数http_parser_url
结构
2、使用http_parser_parse_url
函数进行解析
3、将解析处理的结果dump_url
拿来使用即可,然后就没有然后了。如此简洁!
//从解析的http_parser_url 结构体中,提取相关字段
void dump_url (const char *url, const struct http_parser_url *u)
{
unsigned int i;
printf("\tfield_set: 0x%x, port: %u\n", u->field_set, u->port);
for (i = 0; i < UF_MAX; i++) {
if ((u->field_set & (1 << i)) == 0) {
printf("\tfield_data[%u]: unset\n", i);
continue;
}
printf("\tfield_data[%u]: off: %u, len: %u, part: %.*s\n",
i,
u->field_data[i].off,
u->field_data[i].len,
u->field_data[i].len,
url + u->field_data[i].off);
}
}
int main(int argc, char ** argv) {
struct http_parser_url u;
int len, connect, result;
if (argc != 3) {
printf("Syntax : %s connect|get url\n", argv[0]);
return 1;
}
len = strlen(argv[2]);
connect = strcmp("connect", argv[1]) == 0 ? 1 : 0;
printf("Parsing %s, connect %d\n", argv[2], connect);
http_parser_url_init(&u);//初始化 -- 步骤1
//URL参数,长度,是否为connect模式,返回结果(http_parser_url )
result = http_parser_parse_url(argv[2], len, connect, &u);//步骤2
if (result != 0) {
printf("Parse error : %d\n", result);
return result;
}
printf("Parse ok, result : \n");
dump_url(argv[2], &u);//步骤3
return 0;
}
注意:当为connect模式时,需要为主机名+端口号
测试 1
[root@ide_81 test_code]# ./url_parser get http://blog.csdn.net/njust_ecjtu/article/details/40453577
Parsing http://blog.csdn.net/njust_ecjtu/article/details/40453577, connect 0
Parse ok, result :
field_set: 0xb, port: 0
field_data[0]: off: 0, len: 4, part: http
field_data[1]: off: 7, len: 13, part: blog.csdn.net
field_data[2]: unset
field_data[3]: off: 20, len: 37, part: /njust_ecjtu/article/details/40453577
field_data[4]: unset
field_data[5]: unset
field_data[6]: unset
解析出协议,主机名,路径,均是原BUF的偏移
测试2
[root@ide_81 test_code]# ./url_parser connect blog.csdn.net:80
Parsing blog.csdn.net:80, connect 1
Parse ok, result :
field_set: 0x6, port: 80
field_data[0]: unset
field_data[1]: off: 0, len: 13, part: blog.csdn.net
field_data[2]: off: 14, len: 2, part: 80
field_data[3]: unset
field_data[4]: unset
field_data[5]: unset
field_data[6]: unset
解析出地址与端口号,均是原BUF的偏移,0 copy
http_parser_url
中仅是记录了解析URL中各字段的起始位置以及长度,0 COPY,速度极快。支持SCHEMA、PORT、HOST、PATH、QUERY、USERINFO、FRAGMENT七种信息的提取。 – 在web服务器,抓包分析,代理中,可以借鉴使用。
http://blog.rootk.com/post/tutorial-for-http-parser.html