澳门至尊网站-首页

您的位置:澳门至尊网站 > 软件综合 > 如何解析HTTP请求报文

如何解析HTTP请求报文

2019-11-21 21:55

以此http server的贯彻源代码作者放在了我的github上,风乐趣的话能够点击查看哦。

在上意气风发篇小说中,叙述了什么样编写一个最简便的server,但该程序只是经受到乞求之后顿时回到响应,实在无法更简便。在常规的花销中,应该依照不相同的哀告做出分歧的响应。要完结上述的功能,首先要解析客商端发来的乞请报文。

报文在区别的上下文情景下有区别的理解,本文所说的报文都以在HTTP上下文中描述的名词。

HTTP报文是何许

在HTTP程序中,报文便是HTTP用来搬运东西的包裹,也得以通晓为顺序之间传递消息时发送的数据块。这个数据块以局地文本方式的元音信起首,那个音讯描述了报文的剧情和含义,后边随着可选的多少部分。

报文的流淌

HTTP使用归属流入和流出来描述报文的传递方向。HTTP报文少禽像合水同样流动。不管时诉求报文依旧响应报文,都会向上游流动,全部报文的发送者都在选取者的中游。下图突显了报文向上游流动的例证。

图片 1

报文的构成

报文由七个部分组成:

  • 对报文实行描述的最初行
  • 蕴涵属性的首部块
  • 可选的、满含数据的基点部分

发轫行和首部是由行分隔的ASCII文本。每行都是二个由七个字符(回车符--ASCII码13和换行符--ASCII码10卡塔尔国组成的行终止类别结束。能够写做CRLF

固然规范表达应该用CEnclaveLF来代表行终止,但肃穆的应用程序也应该选拔单个换行作为行的终止。作者仅接济以CPRADOLF换行的深入分析,因为我认为既然有了职业,那就必要依照,服从雷同的商议的前后相继技能相互符信。

实业是二个可选的数据块。与起先行和首部分化的是,主体中得以蕴含主体或二进制数据,也可认为空(举例仅仅GET三个页面或文件卡塔 尔(英语:State of Qatar)。

下边来走访报文的语法的格式和法规。

报文的语法

哀告报文的语法:

<method> <request-URL> <version>
<headers>

<entity-body>

响应报文的语法:

<version> <status-code> <reason-phrase>
<headers>

<entity-body>

method,方法

客户端希望服务器对能源试行的操作。比如GET、POST

request-URL,请求URL

倡议财富,只怕UOdysseyL路线组件的完全UHavalL。

version,版本

报文所接收的HTTP版本。格式:HTTP/.。当中major(首要版本号)和minor(次要版本号)都以整数。

status-code,状态码

呈报哀告进程所产生的气象的数字。

reason-phrase,原因短语

数字状态码的文字描述版本。

headers,首部

各类首部饱含叁个名字,后边随着三个冒号(:),然后是二个可选的空格,接着是二个值,最后是三个C讴歌ZDXLF。能够有零个或四个首部。首部由一个C奇骏LF甘休,表示首部停止和实体中央伊始。

entity-body,实体的重头戏部分

富含三个由随机数据整合的数据块。能够未有,那个时候是以二个C帕杰罗LF停止。

请求行

号召报文的起头行称为必要行。全部的HTTP报文都以一行早先行作为早先。央求行李包裹罗一个方法和多个呼吁U昂CoraL以至HTTP的本子四个字段。每种字段都是空格分隔。

比如:GET / HTTP/1.1

恳请方法为GET,央求UCRUISERL为/,HTTP版本为HTTP/1.1。

响应行

响应报文的发轫行称为响应行。响应行富含HTTP版本、数字状态码以至描述操作情状的文件格局的来头短语。多个字段也是以空格分隔。

比如:HTTP/1.1 200 OK

HTTP版本为HTTP/1.1,数字状态码是200,原因短语是OK。表示央求成功。

首部

首部是是带有在乞求和响应报文的有的叠合音讯。本质上,他们只是一些键值没有错列表。

比如:Content-Length: 19

意味着回去内容长度为19。

实体的主体部分

大约地说,这生机勃勃部分正是HTTP要传输的源委。

浅析倡议报文

打探了报文是哪些构成和各部分代表的原委之后,就对什么剖析呼吁报文心里有数了。

主干代码

    /* 解析请求行 */
    int parse_start_line(int sockfd, char *recv_buf, req_pack *rp)
    {
        char *p = recv_buf;
        char *ch = p;
        int i = 0;
        enum parts { method, url, ver } req_part = method;
        char *method_str;
        char *url_str;
        char *ver_str;
        int k = 0;

        if (*ch < 'A' || *ch > 'Z') {
            return -1;
        }

        while (*ch != CR) {
            if (*ch != BLANK) {
                k++;
            } else if (req_part == method) {
                method_str = (char *)malloc(k * sizeof(char *));
                memset(method_str, 0, sizeof(char *));
                strncpy(method_str, recv_buf, k);
                k = 0;
                req_part = url;
            } else if (req_part == url) {
                url_str = (char *)malloc(k * sizeof(char *));
                memset(url_str, 0, sizeof(char *));
                strncpy(url_str, recv_buf + strlen(method_str) + 1, k);
                k = 0;
                req_part = ver;
            }
            ch++;
            i++;
        }

        if (req_part == url) {
            if (k != 0) {
                url_str = (char *)malloc(k * sizeof(char));
                memset(url_str, 0, sizeof(char));
                strncpy(url_str, recv_buf + strlen(method_str) + 1, k);
                k = 0;
            } else {
                return -1;
            }
        }

        if (k == 0) {
            ver_str = (char *)malloc(8 * sizeof(char));
            memset(ver_str, 0, sizeof(char));
            strcpy(ver_str, "HTTP/1.1");
        } else {
            ver_str = (char *)malloc(k * sizeof(char));
            memset(ver_str, 0, sizeof(char));
            strncpy(ver_str,
                    recv_buf + strlen(method_str) + strlen(url_str) + 2, k);
        }

        rp->method = method_str;
        rp->url = url_str;
        rp->version = ver_str;

        return (i + 2);
    }

    /* 解析首部字段 */
    int parse_header(int sockfd, char *recv_buf, header headers[])
    {
        char *p = recv_buf;
        char *ch = p;
        int i = 0;
        int k = 0;
        int v = 0;
        int h_i = 0;
        bool is_newline = false;
        char *key_str;
        char *value_str;
        header *tmp_header = (header *)malloc(sizeof(header *));
        memset(tmp_header, 0, sizeof(header));

        while (1) {
            if (*ch == CR && *(ch + 1) == LF) {
                break;
            }
            while (*ch != COLON) {
                ch++;
                i++;
                k++;
            }
            if (*ch == COLON) {
                key_str = (char *)malloc(k * sizeof(char *));
                memset(key_str, 0, sizeof(char *));
                strncpy(key_str, recv_buf + i - k, k);
                k = 0;
                ch++;
                i++;
            }
            while (*ch != CR) {
                ch++;
                i++;
                v++;
            }
            if (*ch == CR) {
                value_str = (char *)malloc(v * sizeof(char *));
                memset(value_str, 0, sizeof(char *));
                strncpy(value_str, recv_buf + i - v, v);
                v = 0;
                i++;
                ch++;
            }
            i++;
            ch++;
            headers[h_i].key = key_str;
            headers[h_i].value = value_str;
            h_i++;
        }

        return (i + 2);
    }

深入剖判观念

遍历recv选择到的需要字符串,检查是否遭遇回车符r判断风华正茂行数据。

对于起初行,检查是不是蒙受空格分隔差别的字段;对于首部,检查是还是不是境遇冒号分隔键值对的字段值;对于实体的注重部分,则先判别是或不是遭逢C昂CoraLF字符串,然后将剩余内容全方位看作实体的主导部分。

重返值是报告程序下叁回遍历的前奏地点。

假使境遇违法央浼行则赶回400的响应。

总结

解析报文的经过正是依据HTTP合同明确的内容去深入分析报文,获取报文包罗的新闻。

是因为底工知识较柔弱,代码还会有不菲荒唐以致好多地点须求优化。借使有看齐错误之处或有此外提议望各位硬汉多多支持。^_^

其风流倜傥http server的贯彻源代码我放在了我的github上,有意思味的话可以点击查看哦。

原创小说,文笔有限,胸无点墨,文中若有不正之处,万望告知。

假如本文对你有帮扶,请点下推荐吧,感激^_^

本文由澳门至尊网站发布于软件综合,转载请注明出处:如何解析HTTP请求报文

关键词: