2012-09-19 6 views
39

Ich verwende SimpleHTTPServer, um einige Webseiten zu testen, an denen ich gerade arbeite. Es funktioniert gut, aber ich muss einige Domain-übergreifende Anfragen machen. Dazu muss ein Header Access-Control-Allow-Origin mit den Domänen festgelegt werden, auf die die Seite zugreifen darf.Kann ich mit dem SimpleHTTPServer von Python einen Header setzen?

Gibt es eine einfache Möglichkeit, eine Überschrift mit SimpleHTTPServer zu setzen und den ursprünglichen Inhalt zu liefern? Der Header wäre bei jeder Anfrage gleich.

Antwort

42

Dies ist ein bisschen wie ein Hack, weil es end_headers() Verhalten ändert, aber ich denke, es ist etwas besser ist als das Kopieren und die gesamte SimpleHTTPServer.py Datei einfügen.

Mein Ansatz überschreibt end_headers() in einer Unterklasse und ruft send_my_headers() auf, gefolgt von dem Aufruf der Superklasse end_headers().

Es ist auch nicht 1 - 2 Zeilen, weniger als 20 obwohl; meistens Standard.

#!/usr/bin/env python 
import SimpleHTTPServer 

class MyHTTPRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler): 
    def end_headers(self): 
     self.send_my_headers() 

     SimpleHTTPServer.SimpleHTTPRequestHandler.end_headers(self) 

    def send_my_headers(self): 
     self.send_header("Access-Control-Allow-Origin", "*") 


if __name__ == '__main__': 
    SimpleHTTPServer.test(HandlerClass=MyHTTPRequestHandler) 
+0

Vergessen Sie auch nicht, die Header zu senden, wenn Sie do_GET neu definieren: 'def do_GET (self): self.send_head()' – user474708

+1

Diese Lösung funktioniert nicht, wenn Sie den Standardwert do_GET() verwenden. Es ruft nicht end_headers auf. – Koffiman

4
# coding: utf-8 
import SimpleHTTPServer 
import SocketServer 
PORT = 9999 

def do_GET(self): 
    self.send_response(200) 
    self.send_header('Access-Control-Allow-Origin', 'http://example.com')   
    self.end_headers() 

Handler = SimpleHTTPServer.SimpleHTTPRequestHandler 
Handler.do_GET = do_GET 
httpd = SocketServer.TCPServer(("", PORT), Handler) 
httpd.serve_forever() 
+3

Ich denke, ich sollte klarer sein, dass ich immer noch den ursprünglichen Inhalt, aber mit dem zusätzlichen Header, nicht nur den Header allein dienen wollen. – nynexman4464

9

Ich würde sagen, es gibt keinen einfachen Weg, es zu tun, wo einfache Mittel „nur 1-2 Zeilen hinzufügen, die den zusätzlichen Header und halten die bestehende Funktionalität schreibt“. Die beste Lösung wäre also, die Klasse SimpleHTTPRequestHandler zu unterklassifizieren und die Funktionalität mit dem neuen Header neu zu implementieren.

Das Problem hinter warum gibt es keine einfache Möglichkeit, dies zu tun, kann durch einen Blick auf die Umsetzung der SimpleHTTPRequestHandler Klasse in der Python-Bibliothek zu beachten: http://hg.python.org/cpython/file/19c74cadea95/Lib/http/server.py#l654

Beachten Sie die send_head() Verfahren, insbesondere die Linien am Ende die Methode, die die Antwortheader sendet. Beachten Sie den Aufruf der Methode end_headers(). Diese Methode schreibt die Header an den Ausgang, zusammen mit einer Leerzeile, die signalisiert das Ende aller Header und den Beginn des Antworttextes: http://docs.python.org/py3k/library/http.server.html#http.server.BaseHTTPRequestHandler.end_headers

Daher wäre es nicht möglich sein, die SimpleHTTPRequestHandler Handler Unterklasse, rufen Sie die Super -klasse do_GET() Methode, und dann einfach einen weiteren Header hinzufügen - weil das Senden der Header bereits beendet ist, wenn der Aufruf der Super-Klasse do_GET() Methode zurückgibt. Und es muss so arbeiten, weil die do_GET() Methode den Körper (die Datei, die angefordert wird) senden muss, und den Körper zu senden - es muss das Senden der Überschriften abschließen.

Also, noch einmal, ich glaube, Sie mit Sub-Klassierung der SimpleHTTPRequestHandler Klasse stecken, ist es genau so, wie der Code in der Bibliothek, die (nur kopieren und einfügen?), Und einen anderen Header vor dem Aufruf der end_headers() hinzufügen Verfahren in send_head():

... 
self.send_header("Last-Modified", self.date_time_string(fs.st_mtime)) 
# this below is the new header 
self.send_header('Access-Control-Allow-Origin', '*') 
self.end_headers() 
return f 
... 
+0

Hmm, ja, ich war auf der Suche nach der ein oder zwei Zeilen Lösung. Kopieren der Methode ist die nächste beste Lösung obwohl – nynexman4464

+0

Dann sollte es nicht Self.send_header() und self.end_headers() API der Öffentlichkeit zur Verfügung stellen, wie es nur Consumer-Entwickler zu verwirren ist. Die Header werden tatsächlich zum Antworttext hinzugefügt. – yorkw

0

Während dies ist eine ältere Antwort, es ist das erste Ergebnis in google ...

Im Grunde, was @ iMon0 suggested..Seems richtig? .. Beispiel doPOST

def do_POST(self): 
    self.send_response 
    self.send_header('Content-type','application/json') 
    self.send_header('Access-Control-Allow-Origin','*') 
    self.end_headers() 
    sTest = {} 
    sTest['dummyitem'] = "Just an example of JSON" 
    self.wfile.write(json.dumps(sTest)) 

von dabei fühlt sich der Fluss korrekt an.

1: Sie erhalten eine Anfrage

2: Sie gelten die Header und Antworttyp Sie

wollen

. 3: Sie haben die Daten Post zurück Sie wollen, sei es, was oder wie immer Sie wollen,

Das obige Beispiel funktioniert gut für mich und kann weiter ausgebaut werden, es ist nur ein blanker JSON-Post-Server. Also werde ich das hier auf SOF lassen, wenn jemand es braucht oder ich selbst in ein paar Monaten zurückkomme.

Dies erzeugt eine gültige JSON-Datei mit nur dem sTest-Objekt, genauso wie eine PHP-generierte Seite/Datei.

+1

Ich denke, die ursprüngliche Frage könnte klarer sein, aber was ich wollte, war eine einfache Möglichkeit, Inhalte aus einem Verzeichnis für Dev-Zwecke zu liefern und eine Kopfzeile hinzuzufügen, um Cross-Ursprungs-Anfragen zuzulassen. Mein Ideal wäre etwas wie python -m SimpleHTTPServer --header = Access-Control-Allow-Origin. Das ist nicht möglich, also musst du etwas Code implementieren, um es zu tun. Sie können natürlich 'SimpleHTTPServer' erweitern, um viele andere Dinge zu tun. – nynexman4464

+0

Sie sollten in der Lage sein, den Header innerhalb des bereitgestellten Inhalts zu veröffentlichen? Ansonsten bietet PHP jetzt einen eigenen Webserver, so dass Sie Apache nicht installieren müssen. Ermöglicht Ihnen, es mit einem Verzeichnis und nicht mehr zu starten. Solange du eine Lösung gefunden hast – Mayhem