2010-04-05 7 views
8

gegeben, wenn ein Benutzer /foo auf meinem Server anfordert, schicke ich die folgende HTTP-Antwort (nicht die Verbindung zu schließen):Pushing Daten einmal eine URL angefordert wird

Content-Type: multipart/x-mixed-replace; boundary=----------------------- 

----------------------- 
Content-Type: text/html 

<a href="/bar">foo</a> 

Wenn der Benutzer auf /bar geht (was senden Sie 204 No Content so die Ansicht ändert sich nicht), ich möchte die folgenden Daten in der ersten Antwort senden.

Wie bekomme ich die zweite Anfrage, um dies aus der ersten Antwort auszulösen? Ich plane, möglicherweise eine Phantasie [Motoren, die multipart/x-mixed-ersetzen (derzeit nur Gecko)] zu erstellen - nur E-Mail-Webapp, die Server-Push-und Ajax-Effekte ohne JavaScript tut, nur zum Spaß.

Antwort

1

Keine vollständige Antwort, aber:

In Ihrer Frage, die Sie beschreiben eine Comet -Stil Architektur. Was die Unterstützung von Kometen-Techniken in Python/WSGI betrifft, gibt es eine StackOverflow question, die über verschiedene Python-Server mit Unterstützung für lang laufende Anfragen a la Comet spricht.

Interessant ist auch dieser Mail-Thread in der Python Web-SIG: "Could WSGI handle Asynchronous response?". Im Mai 2008 wurde in der Web-SIG eine breite Diskussion zum Thema asynchronous requests in WSGI geführt.

Eine neuere Entwicklung ist evserver, ein leichter WSGI-Server, der die Asynchronous WSGI extension von Christopher Stawarz in dem Web-SIG im Mai 2008

Schließlich vorgeschlagen implementiert, die Tornado web server unterstützt non-blocking asynchronous requests. Es hat eine Chat-Beispielanwendung, die lange Abfragen verwendet und Ähnlichkeiten mit Ihren Anforderungen aufweist.

+0

Sie können es nicht erkennen, aber "multipart/x-mixed-ersetzen" __is__ eine Form von Comet; das einzige Formular, das kein JavaScript benötigt. Wenn ich es mit Tornados asynchronen Anfragen arbeiten lassen kann, werde ich diese Antwort akzeptieren. –

+0

** Ich bin mir durchaus bewusst, dass "multipart/x-mixed-replace" eine Form von Comet ist, aber ich dachte ** du wärst nicht ** ;-), da du das Schlagwort in deinem nicht erwähnt hast Frage. Ich habe ein bisschen umformuliert. – flight

1

Wenn das Problem ist, einen Befehl aus/bar-Anwendung an/foo-Anwendung übergeben und Sie verwenden einige Servlet-Ansatz (der Python-Code wird einmal geladen und nicht für jede Anfrage wie in CGI), können Sie nur ändern einige Klasseneigenschaften der/foo-Anwendung und bereit sein, auf die Änderung in der/foo-Instanz zu reagieren (indem der Eigenschaftsstatus überprüft wird).

Offensichtlich sollte die/foo-Anwendung nicht direkt nach der ersten Anfrage zurückkehren und Zeile für Zeile Inhalt liefern.

Dachte das ist nur Theorie, ich habe das selbst nicht versucht.

+0

Ohne eine vollständige Datenbank zu verwenden (wie es ziemlich viel Overkill wäre), wie könnte ich leicht ein gemeinsames Zustandsobjekt ändern? –

+0

Wie gesagt, wenn der Code nur einmal geladen wird, dann ist jede neue Anfrage nur eine neue Instanz der Anwendungsklasse. Sie können dann einige Eigenschaften auf Modulebene oder Klasse (nicht Instanz) verwenden, um Informationen auszutauschen. – newtover

-1

nicht sicher, ob dies ganz ist das, was Sie suchen, aber es ist eine ziemlich alte Art und Weise Server-Push zu tun, einen Mime Inhalt von multipart/x-mixed-replace

Grundsätzlich komponieren Sie die Antwort als ein Mime-Objekt mit dem Inhaltstyp multipart/x-mixed-replace und sendet die erste "Version" eines Dokuments. Der Browser hält den Socket offen.

Wenn dann der Server entscheidet, mehr Daten zu übertragen, wird eine neue "Version" des Dokuments vom Server gesendet, und der Browser ersetzt den Inhalt intelligent (innerhalb des Rahmens/Iframes, der den Inhalt enthält).

Dies war eine frühe Art, Webcams zu machen, wo der Server Bild für Bild heruntersenden (pushen) würde, und der Browser würde einfach immer wieder das Bild im Dokument ersetzen. Dies ist auch eine Möglichkeit, eine "Loading ..." -Nachricht über eine einzelne HTTP-Anfrage auszuführen.

+0

Was hat mit der Beantwortung meiner Frage zu tun? Ich weiß, was "multipart/x-mixed-replace" ist und wie man es benutzt, wie in der Frage gezeigt. Ich frage eine WHSI-Frage von Python, wie ich mit diesem Szenario umgehen würde. –

1

ich etwas kleines Beispiel erstellt haben (nur zum Spaß, wissen Sie :))

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. 

Die Idee einer gemeinsamen Variablen und Thread-Synchronisation (unter Verwendung von Bedingungsvariablen Objekt) basiert auf der Tatsache, dass WSGI Server von CherryPyWSGIServer bereitgestellt wird eingefädelt.