Activer le contrôle d'accès sur un serveur HTTP simple

121

J'ai le script shell suivant pour un serveur HTTP très simple:

#!/bin/sh

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

Je me demandais comment activer ou ajouter un en-tête CORS comme Access-Control-Allow-Origin: *sur ce serveur?

MChan
la source

Réponses:

197

Malheureusement, le serveur HTTP simple est vraiment aussi simple qu'il ne permet aucune personnalisation, surtout pas pour les en-têtes qu'il envoie. Vous pouvez cependant créer vous-même un serveur HTTP simple, en utilisant la plupart desSimpleHTTPRequestHandler , et ajouter simplement l'en-tête souhaité.

Pour cela, créez simplement un fichier simple-cors-http-server.py(ou autre) et, selon la version Python que vous utilisez, mettez l'un des codes suivants à l'intérieur.

Ensuite, vous pouvez le faire python simple-cors-http-server.pyet il lancera votre serveur modifié qui définira l'en-tête CORS pour chaque réponse.

Avec le shebang en haut, rendez le fichier exécutable et placez-le dans votre PATH, et vous pouvez simplement l'exécuter en utilisant simple-cors-http-server.pyaussi.

Solution Python 3

Python 3 utilise SimpleHTTPRequestHandleret HTTPServerdu http.servermodule pour exécuter le serveur:

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

Solution Python 2

Python 2 utilise SimpleHTTPServer.SimpleHTTPRequestHandleret le BaseHTTPServermodule pour exécuter le serveur.

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

Solution Python 2 et 3

Si vous avez besoin de compatibilité pour Python 3 et Python 2, vous pouvez utiliser ce script polyglotte qui fonctionne dans les deux versions. Il essaie d'abord d'importer à partir des emplacements Python 3, puis revient à Python 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)
poussée
la source
J'ai suivi les instructions mais en exécutant python simple-cors-http-server.py j'obtiens l'erreur: python: impossible d'ouvrir le fichier 'simple-cors-http-server.py': [Errno 2] Aucun fichier ou répertoire de ce type ne se déconnecte ....Des pensées?
MChan
4
@poke Le serveur répond avec 501 Méthode non prise en charge ('OPTIONS'). J'utilise OS X 10.10.1 avec Python 2.7.6. Aucune suggestion? 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 Le SimpleHTTPRequestHandler ne prend pas en charge la méthode HTTP OPTIONS. Vous pouvez l'ajouter si vous le souhaitez (lisez le manuel Python sur les serveurs HTTP); ou vous ne pourriez tout simplement pas essayer d'accéder au serveur de cette manière.
poke le
2
@RobertoFranceschini Vous rencontrez peut-être des requêtes de contrôle en amont qui nécessitent que la OPTIONSméthode soit correctement implémentée. En ce qui concerne les demandes simples, la solution consistant à envoyer uniquement l'en- Access-Control-Allow-Origintête devrait toujours fonctionner correctement.
poke le
1
@ Tyguy7 Cela pourrait être un comportement général avec le simple serveur HTTP. J'ai eu des résultats variables en ce qui concerne les performances avant. Mais pour simplement faire fonctionner un serveur pendant un moment, je considère toujours que c'est la solution la plus rapide.
poke
108

Essayez une alternative comme http-server

Comme SimpleHTTPServer n'est pas vraiment le type de serveur que vous déployez en production, je suppose ici que vous ne vous souciez pas beaucoup de l'outil que vous utilisez tant qu'il fait le travail d'exposer vos fichiers http://localhost:3000avec les en-têtes CORS dans un simple ligne de commande

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

#run
http-server -p 3000 --cors

Besoin de HTTPS?

Si vous avez besoin de https en local, vous pouvez également essayer caddy ou certbot


Quelques outils connexes que vous pourriez trouver utiles

  • ngrok : lors de l'exécution ngrok http 3000, il crée une URL https://$random.ngrok.comqui permet à quiconque d'accéder à votre http://localhost:3000serveur. Il peut exposer au monde ce qui s'exécute localement sur votre ordinateur (y compris les backends / apis locaux)

  • localtunnel : presque le même que ngrok

  • now : lors de l'exécution now, il télécharge vos actifs statiques en ligne et les déploie sur https://$random.now.sh. Ils restent en ligne pour toujours, sauf si vous en décidez autrement. Le déploiement est rapide (sauf le premier) grâce aux différences. Convient désormais au déploiement de code frontend / SPA de production.Il peut également déployer des applications Docker et NodeJS. Ce n'est pas vraiment gratuit, mais ils ont un plan gratuit.

Sébastien Lorber
la source
5
Je suis un homme simple. Je vois une solution qui nécessite l'installation npmsur une machine connue uniquement pour avoir python, je vote défavorable.
Parthe Shot
6
@ParthianShot: vous voudrez peut-être apprendre à utiliser le meilleur outil pour le travail.
Dan Dascalescu
2
@ParthianShot De nombreux développeurs ont déjà installé node / npm et le titre de la question est suffisamment générique pour attirer un large public d'utilisateurs qui ne se soucient manifestement pas de python ou de SimpleHTTPServer, ce qui est confirmé par des votes positifs. Ce n'est pas parce que cela ne vous aide pas que c'est pour tout le monde. Il y a de bonnes raisons de ne pas aimer à la fois Node et Python. Des choses comme leftpad / mauvaise publication / mauvaise utilisation de git me semblent totalement indépendantes.
Sébastien Lorber
5
L'ajout d'un langage et d'un framework supplémentaires entraîne une dette technique et augmente la surface d'attaque d'un environnement. "Des erreurs fatales peuvent être commises dans n'importe quel langage de programmation" C'est vrai, mais JS rend cela plus facile que la plupart des autres langages. Et chaque langue a des pièges; moins vous utilisez de langues, moins il est probable qu'un développeur qui ne connaît pas l'une des langues fasse une erreur qui ne serait pas une erreur dans une autre langue.
Tir parthe
2
C'est comme adopter un enfant chaque fois que vous avez besoin d'aide à la maison; cela crée plus de problèmes qu'il n'en résout sur la route.
Parthe Shot
1

J'ai eu le même problème et suis arrivé à cette solution:

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

J'ai simplement créé une nouvelle classe héritant de SimpleHTTPRequestHandler qui ne change que la send_responseméthode.

Hugo Trentesaux
la source
0

Vous devrez fournir vos propres instances de do_GET () (et do_HEAD () si vous choisissez de prendre en charge les opérations HEAD). quelque chose comme ça:

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
la source
Merci pour votre réponse, mais je n'ai aucune connaissance de Python, j'utilise juste le script shell mentionné ci-dessus comme un simple serveur http pour mes applications Emberjs. Ce n'est qu'en cas de collision avec le problème de contrôle d'accès que j'ai recherché pour trouver que je devais l'activer dans ce simple serveur http. Donc, après quelques recherches, j'ai ajouté (activer 'CrossOrigin', origins => '*';) mais sans surprise, cela n'a pas fonctionné. Si vous pouvez me diriger vers n'importe quel script shell de serveur http simple Python qui inclut la fonctionnalité de contrôle d'accès qui sera très appréciée
MChan
Sur une note mineure, je n'essaye pas d'être paresseux ici vraiment, mais commencez à apprendre python simplement pour ajouter cette fonctionnalité au serveur simpleHTTP ne semble pas logique à ce stade, alors j'espérais que ce sera facile à ajouter OU j'espère pouvoir trouver un script Python alternatif / prêt à l'emploi qui peut faire le travail afin que je puisse continuer mon travail de développement
MChan
3
Le SimpleHTTPServer n'a pas d'options pour prendre en charge les contrôles d'accès. Soit vous devrez rouler votre propre code, soit passer à un autre serveur Web prenant en charge les contrôles d'accès. Penser à lighttpd.net
user590028