Habilite el control de acceso en un servidor HTTP simple

121

Tengo el siguiente script de shell para un servidor HTTP muy simple:

#!/bin/sh

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

Me preguntaba cómo puedo habilitar o agregar un encabezado CORS como Access-Control-Allow-Origin: *este servidor.

MChan
fuente

Respuestas:

197

Desafortunadamente, el servidor HTTP simple es realmente tan simple que no permite ninguna personalización, especialmente no para los encabezados que envía. Sin embargo, puede crear un servidor HTTP simple usted mismo, utilizando la mayor parte SimpleHTTPRequestHandler, y simplemente agregar el encabezado deseado.

Para eso, simplemente cree un archivo simple-cors-http-server.py(o lo que sea) y, dependiendo de la versión de Python que esté usando, coloque uno de los siguientes códigos dentro.

Luego puede hacerlo python simple-cors-http-server.pyy lanzará su servidor modificado que configurará el encabezado CORS para cada respuesta.

Con el shebang en la parte superior, haga que el archivo sea ejecutable y colóquelo en su PATH, y puede ejecutarlo usando simple-cors-http-server.pytambién.

Solución Python 3

Python 3 usa SimpleHTTPRequestHandlery HTTPServerdel http.servermódulo para ejecutar el servidor:

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

Solución Python 2

Python 2 usa SimpleHTTPServer.SimpleHTTPRequestHandlery el BaseHTTPServermódulo para ejecutar el servidor.

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

Solución Python 2 y 3

Si necesita compatibilidad tanto para Python 3 como para Python 2, puede usar este script políglota que funciona en ambas versiones. Primero intenta importar desde las ubicaciones de Python 3 y, de lo contrario, recurre a 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)
dar un toque
fuente
Seguí las instrucciones, pero al ejecutar python simple-cors-http-server.py obtengo el error: python: no se puede abrir el archivo 'simple-cors-http-server.py': [Errno 2] No existe tal archivo o directorio de cierre de sesión ....¿Alguna idea?
MChan
4
@poke El servidor responde con el método 501 no admitido ('OPCIONES'). Estoy ejecutando OS X 10.10.1 con Python 2.7.6. ¿Alguna sugerencia? 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 El SimpleHTTPRequestHandler no admite el método OPTIONS HTTP. Puede agregarlo si lo desea (lea el manual de Python sobre servidores HTTP); o simplemente no podría intentar acceder al servidor de esa manera.
empuje el
2
@RobertoFranceschini Es posible que se encuentre con solicitudes de verificación previa que requieren que el OPTIONSmétodo se implemente correctamente. En cuanto a las solicitudes simples, la solución de enviar solo el Access-Control-Allow-Originencabezado debería funcionar bien.
toque el
1
@ Tyguy7 Sin embargo, ese podría ser un comportamiento general con el servidor HTTP simple. Tuve resultados variables con respecto al rendimiento antes. Pero por simplemente ejecutar un servidor por un momento, todavía lo considero la solución más rápida.
Empuje
108

Pruebe una alternativa como servidor http

Como SimpleHTTPServer no es realmente el tipo de servidor que implementa en producción, estoy asumiendo aquí que no le importa mucho qué herramienta usa siempre que haga el trabajo de exponer sus archivos http://localhost:3000con encabezados CORS en un simple línea de comando

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

#run
http-server -p 3000 --cors

¿Necesitas HTTPS?

Si necesita https en local, también puede probar caddy o certbot


Algunas herramientas relacionadas que pueden resultarle útiles

  • ngrok : cuando se ejecuta ngrok http 3000, crea una URL https://$random.ngrok.comque permite que cualquiera pueda acceder a su http://localhost:3000servidor. Puede exponer al mundo lo que se ejecuta localmente en su computadora (incluidos backends / apis locales)

  • localtunnel : casi lo mismo que ngrok

  • ahora : cuando se ejecuta now, carga sus activos estáticos en línea y los implementa en https://$random.now.sh. Permanecen en línea para siempre a menos que decida lo contrario. La implementación es rápida (excepto la primera) gracias a la diferencia. Ahora es adecuado para la implementación de código SPA / frontend de producción. También puede implementar aplicaciones Docker y NodeJS. No es realmente gratis, pero tienen un plan gratuito.

Sebastien Lorber
fuente
5
Soy un hombre sencillo. Veo una solución que requiere la instalación npmen una máquina que solo se sabe que tiene python, voto en contra.
Parthian Shot
6
@ParthianShot: es posible que desee aprender a usar la mejor herramienta para el trabajo.
Dan Dascalescu
2
@ParthianShot Muchos desarrolladores ya tienen node / npm instalado. Y el título de la pregunta es lo suficientemente genérico como para atraer a una gran audiencia de usuarios a los que claramente no les importa Python o SimpleHTTPServer, lo cual es confirmado por upvotes. No es porque no sea útil para usted, sino para todos. Hay buenas razones para que no te gusten tanto Node como Python. Cosas como leftpad / bad publish / bad git me parecen totalmente ajenas a mí.
Sebastien Lorber
5
Agregar un lenguaje y un marco adicionales genera una deuda técnica y aumenta la superficie de ataque de un entorno. "Se pueden cometer errores fatales en cualquier lenguaje de programación" Es cierto, pero JS lo hace más fácil que la mayoría de los otros lenguajes. Y cada idioma tiene trampas; cuantos menos idiomas use, menos probable es que algún desarrollador que no esté familiarizado con uno de los idiomas cometa un error que no sería un error en otro idioma.
Disparo parto
2
Es como adoptar un niño cada vez que necesita ayuda en la casa; crea más problemas de los que resuelve en el futuro.
Disparo parto
1

Tuve el mismo problema y llegué a esta solución:

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

Simplemente creé una nueva clase heredada de SimpleHTTPRequestHandler que solo cambia el send_responsemétodo.

Hugo Trentesaux
fuente
0

Deberá proporcionar sus propias instancias de do_GET () (y do_HEAD () si elige admitir operaciones HEAD). algo como esto:

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
fuente
Gracias por su respuesta, pero no tengo ningún conocimiento de Python, solo estoy usando el script de shell mencionado anteriormente como un servidor http simple para mis aplicaciones Emberjs. Solo cuando choqué con el problema del control de acceso, investigué para encontrar que necesito habilitarlo en este simple servidor http. Entonces, después de investigar un poco, agregué (habilitar 'CrossOrigin', origins => '*';) pero, como era de esperar, no funcionó. Si puede, por favor
indíqueme
En una nota menor, no estoy tratando de ser perezoso aquí realmente, pero comenzar a aprender Python solo para agregar esta función al servidor HTTP simple no suena lógico en este punto, así que esperaba que fuera fácil de agregar O, con suerte, puedo encontrar una secuencia de comandos de Python alternativa / lista para usar que puede hacer el trabajo para que pueda continuar con mi trabajo de desarrollo
MChan
3
SimpleHTTPServer no tiene opciones para admitir controles de acceso. Deberá crear su propio código o cambiar a otro servidor web que admita controles de acceso. Piense en lighttpd.net
user590028