2012-09-19 16 views
39

Sto utilizzando SimpleHTTPServer per testare alcune pagine Web su cui sto lavorando. Funziona alla grande, tuttavia ho bisogno di fare alcune richieste cross-domain. Ciò richiede l'impostazione di un'intestazione Access-Control-Allow-Origin con i domini cui la pagina può accedere.Posso impostare un'intestazione con SimpleHTTerver di python?

C'è un modo semplice per impostare un'intestazione con SimpleHTTPServer e servire il contenuto originale? L'intestazione sarebbe la stessa su ogni richiesta.

risposta

42

Questo è un po 'di un hack perché cambia end_headers() comportamento, ma penso che sia un po' meglio di copiare e incollare l'intero file SimpleHTTPServer.py.

Il mio approccio sovrascrive end_headers() in una sottoclasse e in esso chiama send_my_headers() seguito chiamando il numero della superclasse end_headers().

Non è neanche 1 - 2 linee, meno di 20; per lo più boilerplate.

#!/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

Inoltre, non dimenticare di inviare le intestazioni se stai ridefinendo do_GET: 'def do_GET (self): self.send_head()' – user474708

+1

Questa soluzione non funziona se si utilizza l'impostazione predefinita do_GET(). Non chiama end_headers. – 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

Immagino che dovrei essere più chiaro in quanto voglio ancora servire il contenuto originale, ma con l'intestazione aggiuntiva, non solo l'intestazione da solo. – nynexman4464

9

direi che non c'è modo semplice di farlo, in cui mezzi semplici "basta aggiungere 1-2 linee che scriveranno l'intestazione addizionale e mantenere la funzionalità esistenti". Quindi, la soluzione migliore sarebbe quella di sottoclasse la classe SimpleHTTPRequestHandler e la nuova implementazione della funzionalità, con l'aggiunta della nuova intestazione.

Il problema dietro perché non esiste un modo semplice di fare questo si può osservare guardando l'implementazione della classe SimpleHTTPRequestHandler nella libreria Python: http://hg.python.org/cpython/file/19c74cadea95/Lib/http/server.py#l654

Avviso il metodo send_head(), in particolare le linee alla fine del il metodo che invia le intestazioni di risposta. Si noti l'invocazione del metodo end_headers(). Questo metodo scrive le intestazioni all'uscita, insieme ad una riga vuota, che segnala la fine di tutte le intestazioni e l'inizio del corpo della risposta: http://docs.python.org/py3k/library/http.server.html#http.server.BaseHTTPRequestHandler.end_headers

Pertanto, non sarebbe possibile sottoclasse gestore SimpleHTTPRequestHandler, richiamare il super -class metodo do_GET(), e quindi basta aggiungere un'altra intestazione - perché l'invio delle intestazioni è già terminato quando viene restituita la chiamata al super-classe do_GET() metodo. E deve funzionare così perché il metodo do_GET() deve inviare il corpo (il file richiesto) e inviare il corpo - deve finalizzare l'invio delle intestazioni.

Quindi, ancora una volta, penso che sei bloccato con la sottoclasse della classe SimpleHTTPRequestHandler, implementandola esattamente come il codice nella libreria (solo copia-incolla?) E aggiungi un'altra intestazione prima della chiamata allo end_headers() metodo 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, sì, stavo cercando la soluzione a una o due linee. La copia del metodo è la soluzione migliore per il momento – nynexman4464

+0

Quindi non dovrebbe fornire al pubblico l'API self.send_header() e self.end_headers() poiché tutto ciò che fa è confondere lo sviluppatore del consumatore. Le intestazioni sono infatti aggiunte al corpo della risposta. – yorkw

0

Mentre questo è una risposta più vecchio, è il primo risultato in google ...

Fondamentalmente ciò @ iMon0 suggested..Seems corretta? .. Esempio di 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)) 

By facendo questo, il flusso si sente corretto ..

1: È possibile ottenere una richiesta di

2: È possibile applicare le intestazioni e il tipo di risposta che si desidera

3:. Si registra di nuovo i dati che si desidera, essere questo che cosa o come mai si desidera,

L'esempio precedente funziona perfettamente per me e può essere esteso ulteriormente, è solo un post server JSON con osso nudo. Quindi lascerò questo qui su SOF in caso qualcuno ne abbia bisogno o io stesso tornerò tra qualche mese.

Ciò produce un file JSON valido con solo l'oggetto sTest, come una pagina/file generato in PHP.

+1

Immagino che la domanda originale potrebbe essere più chiara, ma quello che volevo era un modo semplice per pubblicare contenuti da una directory per scopi di sviluppo e aggiungere un'intestazione per consentire richieste di origine incrociata. Il mio ideale sarebbe stato qualcosa come 'python -m SimpleHTTPServer --header = Access-Control-Allow-Origin'. Non è possibile, quindi ti ritrovi a dover implementare del codice per farlo. Si può ovviamente estendere 'SimpleHTTerver' per fare molte altre cose. – nynexman4464

+0

Dovresti riuscire a pubblicare l'intestazione dal contenuto pubblicato? Altrimenti, PHP ora offre il proprio webserver in modo da non dover installare apache. Ti permette di accenderlo con una directory e niente di più. Finché hai trovato una soluzione – Mayhem

Problemi correlati