Данный, когда пользователь запрашивает /foo
на моем сервере я отправляю следующий ответ HTTP (не закрывающий соединение):
Content-Type: multipart/x-mixed-replace; boundary=-----------------------
-----------------------
Content-Type: text/html
<a href="/bar">foo</a>
Когда пользователь переходит в /bar
(который отправит 204 No Content
таким образом, представление не изменяется), я хочу отправить следующие данные в начальном ответе.
-----------------------
Content-Type: text/html
bar
Как я заставил бы второй запрос инициировать это от начального ответа? Я - планирование возможно создающий воображение [механизмы, которые поддерживают multipart/x-mixed-replace (в настоящее время только Геккон)] - только почтовое веб-приложение, которое делает нажатие сервера и эффекты Ajax без любого JavaScript, только для забавы.
Нет полного ответа, но:
В своем вопросе вы описываете комету -стайл архитектуры. Что касается поддержки методов стиля Comet в Python / WSGI, существует вопрос StackOverflow , в котором говорится о различных серверах Python с поддержкой длительных запросов в стиле Comet.
Также интересен этот почтовый поток в Python Web-SIG: «Может ли WSGI обрабатывать асинхронный ответ?» . В мае 2008 года в Web-SIG прошла широкая дискуссия по теме асинхронных запросов в WSGI .
Недавняя разработка - evserver , облегченный сервер WSGI, который реализует расширение асинхронного WSGI , предложенное Кристофером Ставарцем в Web-SIG в мае 2008 года.
Наконец, веб-сервер Tornado поддерживает неблокирующие асинхронные запросы . В нем есть пример приложения чата, использующего длинный опрос, который имеет сходство с вашими требованиями.
Если проблема заключается в передаче некоторой команды из приложения / bar в приложение / foo, и вы используете подход, подобный сервлету (код Python загружается один раз а не для каждого запроса, как в CGI), вы можете просто изменить какое-либо свойство класса приложения / foo и быть готовым отреагировать на изменение в экземпляре / foo (проверив состояние свойства).
Очевидно, что приложение / foo не должно возвращаться сразу после первого запроса и выводить контент построчно.
Думал, это всего лишь теория, я сам не пробовал.
Не уверен, что это именно то, что вы ищете, но есть довольно старый способ отправки сервера с использованием mime-содержимого multipart / x -mixed-replace
Обычно вы составляете ответ как mime-объект с типом содержимого multipart / x-mixed-replace и отправляете первую «версию» документа. Браузер будет держать сокет открытым.
Затем, когда сервер решает отправить больше данных, с сервера отправляется новая «версия» документа, и браузер разумно заменяет (в любом фрейме / iframe, содержащем контент) контент.
Это был ранний способ создания веб-камер, когда сервер отправлял (выталкивал) изображение за изображением, а браузер просто продолжал заменять изображение в документе снова и снова. Это также способ отправки сообщения «Загрузка ...» через один HTTP-запрос.
Я создал небольшой пример (вы знаете, просто для удовольствия :))
import threading
num = 0
cond = threading.Condition()
def app(environ, start_response):
global num
cond.acquire()
num += 1
cond.notifyAll()
cond.release()
start_response("200 OK", [("Content-Type", "multipart/x-mixed-replace; boundary=xxx")])
while True:
n = num
s = "--xxx\r\nContent-Type: text/html\r\n\r\n%s\n" % n
yield s
# wait for num change:
cond.acquire()
while num == n:
cond.wait()
cond.release()
from cherrypy.wsgiserver import CherryPyWSGIServer
server = CherryPyWSGIServer(("0.0.0.0", 3000), app)
try:
server.start()
except KeyboardInterrupt:
server.stop()
# Now whenever you visit http://127.0.0.1:3000/, the number increases.
# It also automatically increases in all previously opened windows/tabs.
Идея синхронизации разделяемой переменной и потока (с использованием объекта переменной условия) основана на том факте, что сервер WSGI, предоставляемый CherryPyWSGIServer, является многопоточным .