一、引言
在我们学习了http协议的结构后,我们肯定迫不及待地想要进行练习和巩固。
我们可以使用一个Request类来负责封装http协议发送的字符串信息。在解析的时候我们可以巩固常用的基本属性,如host、path、port、method、header等以及对于字符串和类的使用。
二、意义
为什么需要做这个呢?服务器不是已经帮我们封装好了吗?
说的没错........服务器已经都帮我们清晰的封装好了。
不过通过自己再次对原装的字符串进行切割,可以帮助我们更好的复习http协议的结构形式以及对于字符串语法的使用。
所以本篇博客比较适合于刚学习完http协议的基本结构且还不是那么熟悉的新手。
三、实例演练
get请求的示例
python
GET /api/v1/resource/1234?param1=value1¶m2=value2 HTTP/1.1
Host: www.example.com
User-Agent: curl/7.64.1
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
以上代码可以很清晰的看出http协议发送的字符串结构。下面我们就来进行代码解析。
python
class Request:
def __init__(self,method,path,protocol,headers):
self.method=method
self.path=path
self.protocol=protocol
self.headers=headers
@staticmethod
def parse_request(data):
parts=data.strip().split('\n\n')
request_line,headers=parts[0],parts[1]
method,path,protocol=request_line.split(' ')
header_lines=headers.split('\n')
headers={}
for header in header_lines:
key,value=header.split(':')
headers[key]=value
return Request(method,path,protocol,headers)
request=Request.parse_request(data)
print(request.method)
print(request.path)
print(request.protocol)
print(request.headers)
运行结果如下
解释一下方法: 总体来说就是先根据两个换行符\n来分为两个部分,一个是request_line,一个是headers,再分别切割。 request_line根据字符之间的空格' '来划分,再一个一个对应方法、路径和版本。 headers同理。最后返回Request,再输出出来。
post请求的示例
python
data = """POST /api/v1/resource HTTP/1.1
Host: www.example.com
User-Agent: curl/7.64.1
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
Content-Type: application/json
Content-Length: 81
{
"key1": "value1",
"key2": "value2",
"key3": {
"subKey": "subValue"
}
}
"""
解析代码
python
class Request:
def __init__(self, method, path, version, headers, body):
self.method = method
self.path = path
self.version = version
self.headers = headers
self.body = body
def parse_request(data):
lines = data.split('\n')
method, path, version = lines[0].split(' ')
headers = {}
index = lines.index('')
for line in lines[1:index]:
key, value = line.split(':')
headers[key] = value
body = '\n'.join(lines[index + 1:])
request = Request(method, path, version, headers, body)
return request
request = parse_request(data)
print(request.method)
print(request.path)
print(request.version)
print(request.headers)
print(request.body)
运行结果如下
说一下思路:其实本质上都差不多,具体的分割方法得看具体的data结构,比如这个例子就不像get方法的那个一样用\n\n来分块,它没有连续的换行,只能\n后一行一行解析,lines[0]就是第一行。以此类推,后面使用index索引来查找想要的行数,还是很好用的。
四、总结
通过一系列的切割练习,我们可以更好的巩固http协议的结构,以及对于python基本语法的强化练习。
当然了这只是示例,实际在运用的时候会有更难更复杂的情况,一步一步来吧,那都是后话了。(笑)