使用python实现HTTP请求报文是否结束的判断。

1. 目的

使用python实现HTTP请求报文是否结束的判断。

2. 项目意义

  • 理解socket通信中的接收recv字节数大小
  • 掌握HTTP协议报文格式
  • 完善web服务器的请求信息解析
  • 实现返回页面显示请求信息

3. 项目技术要点

  • 基于python3.6语言编写
  • 此项目通过mini_web.py来实现web服务器解析请求信息功能
  • request_end方法实现请求报文解析和结束判断
  • deal_with_request实现返回页面显示请求信息
  • 请求信息同步打印显示在终端窗口
  • 默认测试地址localhost:8888

4. HTTP协议

  • 完整的HTTP请求包括:一个请求行、若干HTTP头域和可选的实体内容三部分

  • 请求行

    • 请求行以一个方法符号开头,以空格分开,后面跟着请求的URI和协议版本,格式如下:
      Method Request-URI HTTP-Version CRLF
    • 其中的Method表示请求方法,Request-URI是同一资源标识符,HTTP-Version表示请求的HTTP协议版本,CRLF表示回车换行。
  • 其中的Method表示请求方法,Request-URI是同一资源标识符,HTTP-Version表示请求的HTTP协议版本,CRLF表示回车换行。

  • 请求方法有8种,方法名全为大写:
    (1)GET 请求获取Request-URI指定的资源
    (2)HEAD 请求获取Request-URI制定资源的响应消息报头
    (3)POST 用于向服务器提交数据,正常情况下带有“消息体”

    (4)PUT 请求服务器存储一个资源,并用Request-URI作为其标识
    (5)DELETE 请求服务器删除Request-URI所标识的资源
    (6)TRACE 请求服务器回送收到的请求信息,主要用于测试或诊断
    (7)CONNECT 保留将来使用
    (8)OPTIONS 请求查询服务器的性能,或者查询与资源相关的选项和需求。

  • HTTP头域分为四种:通用头域、请求头域、响应头域和实体头域。每个头域由一个域名、冒号和域值三部分组成,域名大小写无关,域值前可以添加任何数量的空格符。
    通用头域

  • 通用头域是指请求和响应都支持的HTTP头域,最常见的有Cache-Control、Connection和Transfer-Encoding,具体含义如下:
    (1) Cache-Control:指定请求和相应遵循的缓存机制,最常见的值是no-cache,指示请求和响应消息不能缓存;
    (2) Connection:用于指定处理完本次请求/响应后,客户端和服务器是否还要继续保持连接。
    (3) Transfer-Encoding:用于指定实体内容的传输编码方式。

  • 请求头域
    请求头域是只有在请求头中带有的,用于向服务器传递关于请求或者关于客户端的附件信息。常见的有:Accept、Accept-Encoding、Accept-Language、Accept-Charset、Host、Referer、User-Agent和Cookie,具体含义如下:
    (1) Accept: 用于指定客户端程序能够处理的MIME类型,多个时用逗号隔开;
    (2) Accept-Encoding:指定客户端程序支持的压缩方式;
    (3) Accept-Language: 指定客户端期望返回哪个国家语言的文档;
    (4) Accept-Charset:指定客户端程序可以使用的字符集;
    (5) Host:指定资源所在的主机名和端口号;
    (6) Referer:指定请求uri的源资源地址,也就是用户从哪个uri过来,允许服务器生成回退链表;
    (7) User-Agent:浏览器客户端信息,如使用哪种浏览器等;
    (8) Cookie:服务器在浏览器端留下的信息,这是最重要的请求头字段之一。

  • 实体头域
    HTTP请求和响应中都可以包含实体头域,实体头域包含实体内容的一些信息。常见的实体头域有:Content-Encoding、Content-Length、Content-Type和Expires,具体含义如下:
    (1) Content-Encoding:指明实体内容采用的压缩方式;
    (2) Content-Length:指明实体内容的长度,单位为字节;
    (3) Content-Type:指定实体内容的MIME类型;
    (4) Expires:指明实体内容在什么时间之后过期,不再缓存。
    因此,由Content-Length头域标明后续的实体内容的字节长度,浏览器或者服务器根据解析出来的Content-Length去读取后续的实体内容。以此来判断是否传输完数据

5. 技术细节

  • 服务器类基本功能实现:
    • 初始化功能init
      • 创建服务器端套接字、绑定端口、监听设置等一系列操作socket
    • 永久启动功能run_forvever
      • 接收客户端请求后通过协程来建立调用浏览器请求处理措施
    • _request_end判断并解析请求数据
    • 浏览器请求处理deal_with_request
      • 接收解析信息,并将相关内容返回给浏览器以显示
  • _request_end方法的处理逻辑


    http请求报文接收完毕判断逻辑

完整源码链接:
https://github.com/ScrappyZhang/http_request_close_judgement

    def _request_end(self, client_socket):
        # 判断并解析请求数据
        recv_data = ''
        request_header = ''  # 请求头字符串
        request_headers = {}  # 请求头解析后的字典
        content_entity = ''  # 实体
        content_length = 0  # 实体长度
        request_line = ''  # 请求行
        while True:
            # 完整读取请求数据
            recv_data_s = client_socket.recv(256)
            print('接收长度为', len(recv_data_s))
            if recv_data_s == b'':
                request_line = '0'
                return request_line, request_headers, content_entity
            try:
                recv_data_s = recv_data_s.decode()
            except Exception as e:
                recv_data_s = recv_data_s.decode('gbk')

            if "\r\n\r\n" not in recv_data:
                recv_data += recv_data_s
            if "\r\n\r\n" not in recv_data:
                pass

            else:
                if request_header == '':
                    # 第一次接收到, 空行 说明请求头结束
                    space_line_index = recv_data.index("\r\n\r\n")
                    request_header = recv_data[0: space_line_index]
                    content_entity = recv_data[space_line_index + 4:]
                    for index, request in enumerate(request_header.split('\r\n')):
                        if index == 0:
                            request_line = request
                        else:
                            key = request.split(':')[0]
                            value = request.lstrip(key).lstrip(':')
                            key = key.strip(' ').lower()
                            value = value.strip(' ')
                            request_headers[key] = value

                    if "content-length" in request_headers.keys():
                        # 查看content_length是否在请求头,若在,需要获取其值
                        content_length = int(request_headers['content-length'])
                        if content_length == len(content_entity.encode()):
                            print("接收请求数据完毕")
                            return request_line, request_headers, content_entity
                    else:
                        # 不存在则说明只有请求头,没有实体
                        return request_line, request_headers, content_entity
                else:
                    # 实体数据
                    content_entity += recv_data_s
                    if content_length == len(content_entity.encode()):
                        print("接收请求数据完毕")
                        return request_line, request_headers, content_entity
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 227,283评论 6 530
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 97,947评论 3 413
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 175,094评论 0 373
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 62,485评论 1 308
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 71,268评论 6 405
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 54,817评论 1 321
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 42,906评论 3 440
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 42,039评论 0 285
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 48,551评论 1 331
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 40,502评论 3 354
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 42,662评论 1 366
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 38,188评论 5 356
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 43,907评论 3 345
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 34,304评论 0 25
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 35,563评论 1 281
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 51,255评论 3 389
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 47,637评论 2 370

推荐阅读更多精彩内容