Подтвердить что ты не робот

Отправлять прерывистый статус запроса перед отправкой фактического ответа

У меня есть сервер, который занимает несколько минут для обработки конкретного запроса, а затем отвечает на него.

Клиент должен продолжать ждать ответа, не зная, когда он будет завершен.

Есть ли способ сообщить клиенту о состоянии обработки? (скажем, 50% завершено, заполнено на 80%), без необходимости опроса клиента.

4b9b3361

Ответ 1

Без использования каких-либо новых методов (websockets, webpush/http2,...) я ранее использовал упрощенное решение Pushlet или Long > для HTTP 1.1 и различные javascript или собственные реализации клиента. Если мое решение не подходит в вашем случае использования, вы всегда можете указать эти два имени Google для дальнейших возможных путей.

Client отправляет запрос, считывает 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 байта не являются "ок", обработайте ошибку как-нибудь иначе. Это не красивое соответствие кода статуса 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.

Ответ 2

Использовать кодировку с канальным передачей, которая является стандартной методикой для передачи потоков неизвестной длины.

Смотрите: Википедия - кодировка с кодировкой передачи

Здесь реализована реализация сервера python как сущность GitHub:

Он отправляет контент с использованием кодирования с коротким передачей с использованием стандартных библиотечных модулей

В клиенте, если серверное кодирование с канальной передачей было уведомлено сервером, вам нужно будет:

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, потому что куски являются динамическими и будут определяться информацией в простых условностях семантики передачи с номером.

Смотрите: http://docs.python-requests.org/en/master/user/advanced/#chunk-encoded-requests

Когда вы видите, например, 100 в содержании ответа r, вы знаете, что следующий фрагмент будет фактическим содержимым после обработки 100.

Ответ 3

Этот ответ, вероятно, не поможет в вашем конкретном случае, но он может помочь в других случаях.

Протокол 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!

К сожалению, это не широко поддерживается. В частности, WSGI не предоставляет способ отправки произвольных ответов 1xx. Клиенты поддерживают ответы 1xx в том смысле, что они необходимы для синтаксического анализа и терпимости к ним, но обычно они не предоставляют программный доступ к ним: в этом примере заголовок Progress не будет доступен клиенту приложение.

Тем не менее, ответы 1xx могут по-прежнему быть полезными (если сервер может их отправить), поскольку они имеют эффект сброса тайм-аута чтения сокета клиентов, что является одной из основных проблем с медленными ответами.