Włącz kontrolę dostępu na prostym serwerze HTTP


122

Mam następujący skrypt powłoki dla bardzo prostego serwera HTTP:

#!/bin/sh

echo "Serving at http://localhost:3000"
python -m SimpleHTTPServer 3000

Zastanawiałem się, jak mogę włączyć lub dodać nagłówek CORS, taki jak Access-Control-Allow-Origin: *do tego serwera?

Odpowiedzi:


197

Niestety, prosty serwer HTTP jest naprawdę tak prosty, że nie pozwala na żadne dostosowanie, szczególnie nie w przypadku wysyłanych nagłówków. Możesz jednak samodzielnie utworzyć prosty serwer HTTP, używając większości SimpleHTTPRequestHandler, i po prostu dodać żądany nagłówek.

W tym celu po prostu utwórz plik simple-cors-http-server.py(lub cokolwiek) i, w zależności od używanej wersji Pythona, umieść w nim jeden z poniższych kodów.

Następnie możesz to zrobić python simple-cors-http-server.pyi uruchomi zmodyfikowany serwer, który ustawi nagłówek CORS dla każdej odpowiedzi.

Z shebang na górze, uczyń plik wykonywalnym i umieść go w swojej PATH, i możesz go po prostu uruchomić używając simple-cors-http-server.pyteż.

Rozwiązanie Python 3

Python 3 używa SimpleHTTPRequestHandleri HTTPServerz http.servermodułu do uruchamiania serwera:

#!/usr/bin/env python3
from http.server import HTTPServer, SimpleHTTPRequestHandler, test
import sys

class CORSRequestHandler (SimpleHTTPRequestHandler):
    def end_headers (self):
        self.send_header('Access-Control-Allow-Origin', '*')
        SimpleHTTPRequestHandler.end_headers(self)

if __name__ == '__main__':
    test(CORSRequestHandler, HTTPServer, port=int(sys.argv[1]) if len(sys.argv) > 1 else 8000)

Rozwiązanie Python 2

Python 2 używa SimpleHTTPServer.SimpleHTTPRequestHandleri BaseHTTPServermodułu do uruchamiania serwera.

#!/usr/bin/env python2
from SimpleHTTPServer import SimpleHTTPRequestHandler
import BaseHTTPServer

class CORSRequestHandler (SimpleHTTPRequestHandler):
    def end_headers (self):
        self.send_header('Access-Control-Allow-Origin', '*')
        SimpleHTTPRequestHandler.end_headers(self)

if __name__ == '__main__':
    BaseHTTPServer.test(CORSRequestHandler, BaseHTTPServer.HTTPServer)

Rozwiązanie Python 2 i 3

Jeśli potrzebujesz kompatybilności zarówno z Pythonem 3, jak i Pythonem 2, możesz użyć tego skryptu poliglota, który działa w obu wersjach. Najpierw próbuje zaimportować z lokalizacji Python 3, a w przeciwnym razie wraca do Pythona 2:

#!/usr/bin/env python
try:
    # Python 3
    from http.server import HTTPServer, SimpleHTTPRequestHandler, test as test_orig
    import sys
    def test (*args):
        test_orig(*args, port=int(sys.argv[1]) if len(sys.argv) > 1 else 8000)
except ImportError: # Python 2
    from BaseHTTPServer import HTTPServer, test
    from SimpleHTTPServer import SimpleHTTPRequestHandler

class CORSRequestHandler (SimpleHTTPRequestHandler):
    def end_headers (self):
        self.send_header('Access-Control-Allow-Origin', '*')
        SimpleHTTPRequestHandler.end_headers(self)

if __name__ == '__main__':
    test(CORSRequestHandler, HTTPServer)

Postępowałem zgodnie z instrukcjami, ale wykonując python simple-cors-http-server.py pojawia się błąd: python: nie można otworzyć pliku „simple-cors-http-server.py”: [Errno 2] Brak takiego pliku lub wylogowania z katalogu ....jakieś pomysły?
— MChan

4
@poke Serwer odpowiada metodą 501 nieobsługiwaną („OPCJE”). Używam OS X 10.10.1 z Pythonem 2.7.6. Jakieś sugestie? HTTP/1.0 501 Unsupported method ('OPTIONS') Server: SimpleHTTP/0.6 Python/2.7.6 Date: Wed, 21 Jan 2015 23:16:10 GMT Content-Type: text/html Connection: close Access-Control-Allow-Origin: *
— HairOfTheDog

1
@HairOfTheDog SimpleHTTPRequestHandler nie obsługuje metody HTTP OPTIONS. Możesz go dodać, jeśli chcesz (przeczytaj podręcznik Pythona o serwerach HTTP); lub po prostu nie możesz próbować uzyskać dostępu do serwera w ten sposób.
— szturchnij

2
@RobertoFranceschini Możesz napotkać wstępnie sprawdzone żądania, które wymagają OPTIONSpoprawnej implementacji metody. Jeśli chodzi o proste żądania, rozwiązanie polegające na wysyłaniu samego Access-Control-Allow-Originnagłówka powinno nadal działać dobrze.
— poke

1
@ Tyguy7 Może to być jednak ogólne zachowanie w przypadku prostego serwera HTTP. Wcześniej miałem różne wyniki dotyczące wydajności. Ale jeśli chodzi o po prostu uruchomienie serwera przez chwilę, nadal uważam to za najszybsze rozwiązanie.
— poke

108

Wypróbuj alternatywę, taką jak serwer http

Ponieważ SimpleHTTPServer nie jest tak naprawdę rodzajem serwera, który wdrażasz w środowisku produkcyjnym, zakładam, że nie obchodzi Cię, jakiego narzędzia używasz, o ile wykonuje on zadanie ujawniania plików http://localhost:3000z nagłówkami CORS w prostym wiersz poleceń

# install (it requires nodejs/npm)
npm install http-server -g

#run
http-server -p 3000 --cors

Potrzebujesz protokołu HTTPS?

Jeśli potrzebujesz https w lokalnym, możesz również wypróbować caddy lub certbot


Niektóre powiązane narzędzia, które mogą okazać się przydatne

  • ngrok : podczas uruchamiania ngrok http 3000tworzy adres URL, https://$random.ngrok.comktóry umożliwia każdemu dostęp do Twojego http://localhost:3000serwera. Może ujawnić światu to, co działa lokalnie na twoim komputerze (w tym lokalne backendy / API)

  • localtunnel : prawie taki sam jak ngrok

  • teraz : po uruchomieniu nowprzesyła statyczne zasoby online i wdraża je do https://$random.now.sh. Pozostają online na zawsze, chyba że zdecydujesz inaczej. Wdrożenie jest szybkie (z wyjątkiem pierwszego) dzięki różnicowaniu. Teraz nadaje się do wdrażania kodu frontend / SPA. Może również wdrażać aplikacje Docker i NodeJS. To nie jest naprawdę darmowe, ale mają darmowy plan.


5
Jestem prostym człowiekiem. Widzę rozwiązanie, które wymaga instalacji npmna komputerze, o którym wiadomo, że ma python, głosuję przeciw.
— Parthian Shot

6
@ParthianShot: możesz nauczyć się używać najlepszego narzędzia do pracy.
— Dan Dascalescu

2
@ParthianShot Wielu programistów ma już zainstalowany node / npm, a tytuł pytania jest na tyle ogólny, że przyciąga dużą grupę użytkowników, którzy wyraźnie nie dbają o Pythona lub SimpleHTTPServer, co potwierdzają głosy za. Nie dlatego, że nie jest to dla ciebie pomocne, jest to dla wszystkich. Istnieją dobre powody, aby nie lubić zarówno Node, jak i Pythona. Rzeczy takie jak lewy pad / złe publikowanie / złe użycie gita wydają się zupełnie niezwiązane ze mną.
— Sebastien Lorber

5
Dodanie dodatkowego języka i frameworka pociąga za sobą dług techniczny i zwiększa powierzchnię ataku środowiska. „Fatalne błędy można popełnić w każdym języku programowania” To prawda, ale JS sprawia, że ​​jest to łatwiejsze niż w przypadku większości innych języków. A każdy język ma kłopoty; im mniej języków używasz, tym mniej prawdopodobne jest, że jakiś programista, który nie jest zaznajomiony z jednym z języków, popełni błąd, który nie byłby błędem w innym języku.
— Parthian Shot

2
To tak, jakby adoptować dziecko za każdym razem, gdy potrzebujesz pomocy w domu; stwarza więcej problemów niż rozwiązuje w przyszłości.
— Parthian Shot

1

Miałem ten sam problem i doszedłem do takiego rozwiązania:

class Handler(SimpleHTTPRequestHandler):
    def send_response(self, *args, **kwargs):
        SimpleHTTPRequestHandler.send_response(self, *args, **kwargs)
        self.send_header('Access-Control-Allow-Origin', '*')

Po prostu utworzyłem nową klasę dziedziczącą po SimpleHTTPRequestHandler, która tylko zmienia send_responsemetodę.


0

Będziesz musiał podać własne instancje do_GET () (i do_HEAD (), jeśli zdecydujesz się na obsługę operacji HEAD). coś takiego:

class MyHTTPServer(SimpleHTTPServer):

    allowed_hosts = (('127.0.0.1', 80),)

    def do_GET(self):
        if self.client_address not in allowed_hosts:
            self.send_response(401, 'request not allowed')
        else:
            super(MyHTTPServer, self).do_Get()

Dziękuję za odpowiedź, ale nie mam żadnej wiedzy na temat Pythona, używam tylko wspomnianego powyżej skryptu powłoki jako prostego serwera http dla moich aplikacji Emberjs. Dopiero gdy zderzyłem się z problemem kontroli dostępu, zbadałem, że muszę go włączyć na tym prostym serwerze http. Więc po kilku badaniach dodałem (włącz 'CrossOrigin', origins => '*';), ale nic dziwnego, że nie zadziałało. Jeśli możesz, proszę, wskaż mi dowolny prosty skrypt powłoki serwera http w języku Python, który zawiera funkcję kontroli dostępu, która będzie bardzo cenna
— MChan

Drobiazgowo, nie próbuję tu być naprawdę leniwy, ale zacznę się uczyć Pythona tylko po to, aby dodać tę funkcję do prostego serwera HTTP, nie brzmi to logicznie w tym momencie, więc miałem nadzieję, że będzie łatwo dodać LUB mam nadzieję, że mogę znaleźć alternatywny / gotowy skrypt w Pythonie, który może wykonać zadanie, dzięki czemu mogę kontynuować moją pracę
— deweloperską

3
SimpleHTTPServer nie ma opcji obsługi kontroli dostępu. Albo będziesz musiał rzucić własny kod - albo przełączyć się na inny serwer WWW, który obsługuje kontrolę dostępu. Pomyśl o lighttpd.net
— user590028
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.