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?

MChan
źródło

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)
szturchać
źródło
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.

Sebastien Lorber
źródło
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ę.

Hugo Trentesaux
źródło
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()
user590028
źródło
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