2012-09-19 13 views
39

Używam SimpleHTTPServer do testowania stron, nad którymi pracuję. Działa wspaniale, ale muszę wykonać kilka żądań między domenami. To wymaga ustawienia nagłówka Access-Control-Allow-Origin z domenami, do których ma dostęp strona.Czy mogę ustawić nagłówek za pomocą SimpleHTTPServer Pythona?

Czy istnieje prosty sposób na ustawienie nagłówka za pomocą funkcji SimpleHTTPServer i podanie oryginalnej treści? Nagłówek będzie taki sam na każdym wniosku.

Odpowiedz

42

jest to bit hack, ponieważ zmienia end_headers() zachowanie, ale myślę, że jest nieco lepiej niż kopiowanie i wklejanie całą SimpleHTTPServer.py pliku.

Moje podejście zastępuje end_headers() w podklasie i wywołuje send_my_headers() następuje poprzez wywołanie nadklasy na end_headers().

To nie jest 1 - 2 linie albo, mniej niż 20 chociaż; w większości na płycie głównej.

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

Nie zapomnij również wysłać nagłówków, jeśli redefiniujesz do_GET: 'def do_GET (self): self.send_head()' – user474708

+1

To rozwiązanie nie działa, jeśli używasz domyślnej metody do_GET(). Nie wywołuje 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

Sądzę, że powinienem wyjaśnić, że nadal chcę służyć oryginalnej treści, ale z dodatkowym nagłówkiem, a nie tylko z samym nagłówkiem. – nynexman4464

9

Powiedziałbym, że nie ma prosty sposób to zrobić, gdzie proste środki „wystarczy dodać 1-2 linie, które będą pisać dodatkowy nagłówek i zachować istniejącą funkcjonalność”. Najlepszym rozwiązaniem byłoby więc podklasować klasę SimpleHTTPRequestHandler i ponownie zaimplementować funkcjonalność, dodając nowy nagłówek.

Problem z tyłu, dlaczego nie istnieje prosty sposób w ten sposób można zaobserwować patrząc na wdrażaniu klasy SimpleHTTPRequestHandler w bibliotece Python: http://hg.python.org/cpython/file/19c74cadea95/Lib/http/server.py#l654

Wskazówka metoda send_head(), zwłaszcza wiersze na koniec metoda, która wysyła nagłówki odpowiedzi. Zwróć uwagę na wywołanie metody end_headers(). Metoda ta pisze nagłówki do wyjścia, razem z pustą linią, która sygnalizuje koniec wszystkich nagłówków i początek korpusu odpowiedzi: http://docs.python.org/py3k/library/http.server.html#http.server.BaseHTTPRequestHandler.end_headers

Dlatego też nie byłoby możliwe do podklasy obsługi SimpleHTTPRequestHandler, wywołać Super -class do_GET() metoda, a następnie po prostu dodaj kolejny nagłówek - ponieważ wysyłanie nagłówków zostało już zakończone, gdy zostanie zwrócone wywołanie metody super-klasy do_GET(). I musi działać tak, ponieważ metoda do_GET() musi wysłać ciało (żądany plik) i wysłać ciało - musi sfinalizować wysyłanie nagłówków.

Więc jeszcze raz, myślę, że utkniesz z sub-classing klasę SimpleHTTPRequestHandler, wdrażanie go dokładnie jak kod w bibliotece (wystarczy skopiować i wkleić go?) I dodać kolejny nagłówek przed wywołaniem do end_headers() Sposób 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, tak, szukałem jednego lub dwóch rozwiązań liniowych. Kopiowanie metody jest kolejnym najlepszym rozwiązaniem, ale – nynexman4464

+0

Następnie nie powinno udostępniać publicznie funkcji self.send_header() i self.end_headers(), ponieważ wszystko, co robi, jest mylące dla deweloperów konsumenckich. Nagłówki są rzeczywiście dodawane do treści odpowiedzi. – yorkw

0

Chociaż jest to starszy odpowiedź, jego pierwszy wynik w google ...

Zasadniczo co @ iMon0 suggested..Seems prawidłowe? .. Przykład 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 robiąc to, przepływ jest poprawny ...

1: otrzymaniu prośby

2: stosowanie nagłówków i typ odpowiedzi chcesz

. 3: można zakładać z powrotem dane, które mają być w tym, co i jak kiedykolwiek chcesz,

Powyższy przykład działa dobrze dla mnie i może być dalej rozbudowywany, jest tylko serwerem postów JSON o gołej kości. Zostawię to tutaj na SOF, jeśli ktoś tego potrzebuje lub sam wrócę za kilka miesięcy.

To powoduje utworzenie prawidłowego pliku JSON tylko z obiektem sTest, takim samym, jak strona/plik wygenerowany przez PHP.

+1

Domyślam się, że pierwotne pytanie może być bardziej przejrzyste, ale chciałem, aby prosty sposób obsługiwał zawartość z katalogu dla celów deweloperskich, i dodać nagłówek, aby umożliwić żądanie krzyżowego pochodzenia. Mój ideał byłby podobny do 'python -m SimpleHTTPServer - header = Access-Control-Allow-Origin'. Nie jest to możliwe, więc musisz zaimplementować jakiś kod, aby to zrobić. Można oczywiście rozszerzyć 'SimpleHTTPServer', aby wykonać wiele innych rzeczy. – nynexman4464

+0

Powinieneś być w stanie opublikować nagłówek z zawartej w nim treści? W przeciwnym razie PHP oferuje teraz własny serwer WWW, więc nie musisz instalować apache. Pozwala wystrzelić z katalogu i nic więcej. Tak długo, jak znajdziesz rozwiązanie – Mayhem