我有一个服务器,需要几分钟来处理特定的请求并回应它。客户端必须一直等待响应,而不知道什么时候会完成。有没有一种方法可以让客户端知道处理状态?(比如50%完成,80%完成),而无需客户端轮询状态。
在不使用任何新技术(如websockets、webpush/http2等)的情况下,我以前使用过简化的Pushlet或Long polling解决方案来处理HTTP 1.1和各种JavaScript或自己的客户端实现。如果我的解决方案不适合您的用例,您可以随时谷歌这两个名称以获取进一步可能的方法。
客户端 发送请求,读取17字节(初始http响应),然后每次读取2个字节以获取处理状态。
服务器 发送有效的HTTP响应,并在请求进程中发送百分比完成的2个字节,直到最后2个字节为“ok”,然后关闭连接。
更新:示例uwsgi server.py
from time import sleep
def application(env, start_response):
start_response('200 OK', [])
def working():
yield b'00'
sleep(1)
yield b'36'
sleep(1)
yield b'ok'
return working()
更新:client.py示例请求
import requests
response = requests.get('http://localhost:8080/', stream=True)
for r in response.iter_content(chunk_size=2):
print(r)
示例服务器(仅供测试使用 :))
import socket
from time import sleep
HOST, PORT = '', 8888
listen_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
listen_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
listen_socket.bind((HOST, PORT))
listen_socket.listen(1)
while True:
client_connection, client_address = listen_socket.accept()
request = client_connection.recv(1024)
client_connection.send('HTTP/1.1 200 OK\n\n')
client_connection.send('00') # 0%
sleep(2) # Your work is done here
client_connection.send('36') # 36%
sleep(2) # Your work is done here
client_connection.sendall('ok') # done
client_connection.close()
如果最后2个字节不是“ok”,那么以其他方式处理错误。这并不是符合美观的HTTP状态码规范,而是我很多年前使用的一种解决方法。
telnet客户端示例
$ telnet localhost 8888
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
GET / HTTP/1.1
HTTP/1.1 200 OK
0036okConnection closed by foreign host.
这个答案可能对你的情况无法帮助,但它可能会在其他情况下有所帮助。
HTTP协议支持信息性(1xx)响应:
指示中间状态响应,用于通信连接状态或请求进度,在完成请求操作并发送最终响应之前
甚至有一个特定于您的用例的状态码102(处理中):
用于通知客户端服务器已接受完整请求,但尚未完成请求操作的中间响应
状态码102由于缺乏实现而被从标准中删除,但仍然注册并可使用。
因此,它可能看起来像这样(HTTP/2具有等效的二进制形式):
HTTP/1.1 102 Processing
Progress: 50%
HTTP/1.1 102 Processing
Progress: 80%
HTTP/1.1 200 OK
Date: Sat, 05 Aug 2017 11:53:14 GMT
Content-Type: text/plain
All done!
import requests
response = requests.get('http://server.fqdn:port/', stream=True)
for r in response.iter_content(chunk_size=None):
print(r)
chunk_size=None
是因为块大小是动态的,并且将根据块传输语义的简单约定中的信息确定。r
的内容中看到100
时,您会知道在处理100
后下一个块将是实际内容。