解析URL

简介

在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

你可能感兴趣的:(linux,网络)