Отправка данных после запроса URL

Учитывая, что когда пользователь запрашивает /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 (в настоящее время только Gecko)] - только веб-приложение электронной почты, которое выполняет server-push и эффекты Ajax без какого-либо JavaScript, просто для удовольствия.


person Eli Grey    schedule 05.04.2010    source источник


Ответы (4)


Нет полного ответа, но:

В своем вопросе вы описываете архитектуру в стиле Comet. Что касается поддержки методов стиля кометы в Python / WSGI, существует вопрос StackOverflow, в котором говорится о различных Серверы Python с поддержкой длительных запросов а-ля Comet.

Также интересна эта почтовая ветка в Python Web-SIG: " Может ли WSGI обрабатывать асинхронный ответ? ". В мае 2008 года в Web-SIG прошла широкая дискуссия по теме асинхронные запросы в WSGI.

Недавняя разработка - evserver, легкий сервер WSGI, который реализует Асинхронное расширение WSGI, предложенное Кристофером Ставарцем в Web-SIG в мае 2008 г. .

Наконец, веб-сервер Tornado поддерживает неблокирующие асинхронные запросы. В нем есть пример приложения чата, использующего длинный опрос, который имеет сходство с вашими требованиями.

person flight    schedule 20.04.2010
comment
Вы можете этого не осознавать, но multipart/x-mixed-replace является формой Кометы; единственная форма, не требующая JavaScript. Если я смогу заставить его работать с асинхронными запросами Tornado, я приму этот ответ. - person Eli Grey; 22.04.2010
comment
Мне хорошо известно, что multipart/x-mixed-replace - это форма кометы, но я подумал, вы не были ;-), поскольку вы не упомянули модное слово в своем вопросе. Я немного переделал. - person flight; 22.04.2010

Если проблема заключается в передаче какой-либо команды из приложения / bar в приложение / foo, и вы используете какой-то сервлетоподобный подход (код Python загружается один раз, а не для каждого запроса, как в CGI), вы можете просто изменить какое-то свойство класса для приложение / foo и будьте готовы отреагировать на изменение экземпляра / foo (проверив состояние свойства).

Очевидно, что приложение / foo не должно возвращаться сразу после первого запроса и выводить контент построчно.

Думал, что это всего лишь теория, я сам не пробовал.

person newtover    schedule 05.04.2010
comment
Как я могу легко изменить объект общего состояния без использования полной базы данных (поскольку это было бы излишним)? - person Eli Grey; 06.04.2010
comment
Как я уже сказал, если код загружается только один раз, то каждый новый запрос - это просто новый экземпляр класса приложения. Затем вы можете использовать некоторые свойства уровня модуля или класса (не экземпляра) для обмена информацией. - person newtover; 06.04.2010

Я создал небольшой пример (вы знаете, просто для удовольствия :))

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, является многопоточным.

person Messa    schedule 20.04.2010

Не уверен, что это именно то, что вы ищете, но есть довольно старый способ выполнения push-сервера с использованием mime-содержимого multipart / x-mixed-replace

Обычно вы составляете ответ как объект mime с типом содержимого multipart / x-mixed-replace и отправляете первую «версию» документа. Браузер будет держать сокет открытым.

Затем, когда сервер решает отправить больше данных, с сервера отправляется новая «версия» документа, и браузер разумно заменяет (в любом фрейме / iframe, содержащем контент) контент.

Это был ранний способ создания веб-камер, когда сервер отправлял (выталкивал) изображение за изображением, а браузер просто продолжал заменять изображение в документе снова и снова. Это также способ отправки сообщения «Загрузка ...» с помощью одного HTTP-запроса.

person alecf    schedule 05.04.2010
comment
При чем тут ответ на мой вопрос? Я знаю, что такое multipart/x-mixed-replace и как его использовать, как показано в вопросе. Я задаю вопрос Python wsgi о том, как бы я справился с этим сценарием. - person Eli Grey; 06.04.2010