- 提问
在过往的使用中对于post请求总是无差别的requests.post(url='', data=json.dumps(data))
, 这是错误的使用方式!!!
那么这个data到底如果给值呢?
- 直接给出结论
data是dict时:
requests 内部对这个dict进行了key-value+&
的字符串拼接. 即data作为表单方式进行的提交,对应的requestContent-Type
请求头为application/x-www-form-urlencoded
data是json.dumps()
序列化后的json字符串
时,原样传输, 且报文不携带Content-Type
请求头, 此时在服务器接受到的报文当然也是可以反序列化json对象出来, 但是没有Content-Type: application/json
请求头,如果需要这个请求头不要走弯路直接requests.post(url, json=data)
这里传dict.
- 直接通过
wireshark
抓包即可以看到区别, 以 dict类型的data为例:-
requests.post(url='', data=data)
-
requests.post(url='', data=json.dumps(data))
-
requests.post(url='', json=data)
-
下面给出一个TcpServer来演示下,刚好也复习下TcpServer.py的定义方式
-
Tcpserver.py:
import socket # 创建 socket 对象 import time, threading sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # bind 服务 sock.bind(('127.0.0.1', 8081)) # 开启服务端socket监听 sock.listen(1) # 设置 100 个 连接上限 sock.setblocking(False) readalbe_list = [] # 可读队列 writeable_list = [] # 可写队列 del_list = [] def read(): print('read running') while 1: for client_socket in readalbe_list: # time.sleep(5) recv_flag = 0 # print(f'客户端连接{client_socket}') try: response = b"" chunk = client_socket.recv(1) while chunk: recv_flag = 1 response += chunk chunk = client_socket.recv(10) print(f'line32: chunk--:: {chunk}') except BlockingIOError as err: if recv_flag: writeable_list.append(client_socket) print(123) if response: print('response: {}'.format(response)) threading.Thread(target=read).start() while 1: try: client_socket, client_addr = sock.accept() # 接收客户端 connect 返回 客户端 socket和 客户端的 地址 print(f"接收到新 连接加入可写队列, 客户端socket: {client_socket} \n 客户端地址: {client_addr}") time.sleep(1) readalbe_list.append(client_socket) except BlockingIOError as err: pass for client_socket in writeable_list: send_flag = 0 try: send_flag = 1 client_socket.send(f'welcome {client_socket}'.encode()) except OSError as err: if send_flag: del_list.append(client_socket) if client_socket in readalbe_list: readalbe_list.remove(client_socket) # 短连接 收发完成移除队列 client_socket.close() for each in del_list: if each in writeable_list: writeable_list.remove(each) del_list.clear()
-
client_demo.py
import requests data = { "id": 99800005, "hot_push_program": [ { "program_id": 200370447, "program_name": "乐享汇: 新的唱响 演唱会(11)", "content_type": 1999, "starttime": time.time(), "endtime": time.time() } ], "accesstoken": "TOKEN3590", "relevance_id": 0 } requests.post(url="http://127.0.0.1:8081/", data=data)
-
Tcpserver.py的打印:
POST / HTTP/1.1 Host: 127.0.0.1:8081 Connection: keep-alive Accept-Encoding: gzip, deflate Accept: */* User-Agent: python-requests/2.22.0 Content-Length: 188 Content-Type: application/x-www-form-urlencoded hot_push_program=program_name&hot_push_program=starttime&hot_push_program=endtime&hot_push_program=content_type&hot_push_program=program_id&id=99800005&accesstoken=TOKEN3590&relevance_id=0
- 附: 另外表单还有另外一种
Content-Type
即multipart/form-data; boundary=xxx
这种方式是以bondary
为分割符分割报文流,适用于海报、大文件等文件流
传输
下附两种表单请求头的区别 multipart/form-data
以上传海报的案例:
可以看到multipart/form-data
格式的数据在tcp报文呈现出的会是指定一个分隔符boundary
,x-www-form-urlencoded
报文段也是有分隔符不过是默认的&