2012-09-19 19 views
39

Estoy usando SimpleHTTPServer para probar algunas páginas web en las que estoy trabajando. Funciona muy bien, sin embargo, necesito hacer algunas solicitudes entre dominios. Eso requiere establecer un encabezado Access-Control-Allow-Origin con los dominios a los que se permite el acceso a la página.¿Puedo establecer un encabezado con SimpleHTTPServer de python?

¿Hay una manera fácil de establecer un encabezado con SimpleHTTPServer y servir el contenido original? El encabezado sería el mismo en cada solicitud.

Respuesta

42

Esto es un poco de un truco, ya que cambia el comportamiento end_headers(), pero creo que es un poco mejor que copiar y pegar todo el archivo SimpleHTTPServer.py.

Mi enfoque anula end_headers() en una subclase y llama a send_my_headers() seguido de llamar a la superclase end_headers().

No son 1 - 2 líneas tampoco, menos de 20; en su mayoría repetitivo.

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

Además, no olvides enviar los encabezados si estás redefiniendo do_GET: 'def do_GET (self): self.send_head()' – user474708

+1

Esta solución no funciona si se usa do_GET() predeterminado. No llama a 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

Supongo que debería ser más claro en cuanto a que todavía quiero servir el contenido original, pero con el encabezado adicional, no solo el encabezado solo. – nynexman4464

9

yo diría que no hay forma sencilla de hacerlo, en medio sencillo "sólo tiene que añadir 1-2 líneas que va a escribir la cabecera adicional y mantener la funcionalidad existente". Entonces, la mejor solución sería subclasificar la clase SimpleHTTPRequestHandler y volver a implementar la funcionalidad, con la adición del nuevo encabezado.

El problema de por qué no hay una forma sencilla de hacer esto se puede observar mirando a la implementación de la clase SimpleHTTPRequestHandler en la biblioteca de Python: http://hg.python.org/cpython/file/19c74cadea95/Lib/http/server.py#l654

Aviso el método send_head(), en particular las líneas al final de el método que envía los encabezados de respuesta. Observe la invocación del método end_headers(). Este método escribe los encabezados de la salida, junto con una línea en blanco que señala el final de todas las cabeceras y el inicio del cuerpo de la respuesta: http://docs.python.org/py3k/library/http.server.html#http.server.BaseHTTPRequestHandler.end_headers

Por lo tanto, no sería posible subclase el manejador SimpleHTTPRequestHandler, invoque el súper -class do_GET() método, y luego simplemente agrega otro encabezado, porque el envío de los encabezados ya ha finalizado cuando se devuelve la llamada a la superclase do_GET() método. Y tiene que funcionar así porque el método do_GET() tiene que enviar el cuerpo (el archivo que se solicita), y para enviar el cuerpo - tiene que finalizar el envío de los encabezados.

Así que, de nuevo, creo que estás atascado con la subclasificación de la clase SimpleHTTPRequestHandler, implementándola exactamente como el código en la biblioteca (¿solo copiar y pegar?) Y agregar otro encabezado antes de la llamada al end_headers() método en el 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, sí, estaba buscando la solución de una o dos líneas. Copiar el método es la siguiente mejor solución, aunque – nynexman4464

+0

Luego no debe proporcionar self.send_header() y self.end_headers() API al público, ya que todo lo que hace es confundir al desarrollador de consumo. Los encabezados se agregan al cuerpo de respuesta. – yorkw

0

Si bien esta es una respuesta mayor, su primer resultado en Google ...

Básicamente lo @ iMon0 suggested..Seems correcta? .. Ejemplo de 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)) 

Por haciendo esto, el flujo se siente correcto ...

1: Usted recibe una solicitud

2: Se aplican las cabeceras y el tipo de respuesta que desea

. 3: Se contabiliza volver los datos que desea, ser esto qué o cómo cada vez que desee,

El ejemplo anterior funciona bien para mí y se puede ampliar aún más, es solo un servidor de publicación JSON bare bone. Así que dejaré esto aquí en SOF en caso de que alguien lo necesite o yo mismo regrese en unos meses por ello.

Esto produce un archivo JSON válido con solo el objeto sTest, igual que una página/archivo generado por PHP.

+1

Supongo que la pregunta original podría ser más clara, pero lo que quería era una forma sencilla de servir contenido de un directorio para propósitos de desarrollo, y agregar un encabezado para permitir las solicitudes de origen cruzadas. Mi ideal hubiera sido algo como 'python -m SimpleHTTPServer --header = Access-Control-Allow-Origin'. Eso no es posible, así que terminas teniendo que implementar algún código para hacerlo. Puede, por supuesto, extender 'SimpleHTTPServer' para hacer muchas otras cosas. – nynexman4464

+0

¿Debería poder publicar el encabezado dentro del contenido servido? De lo contrario, PHP ahora ofrece su propio servidor web, por lo que no es necesario instalar Apache. Le permite encenderlo con un directorio y nada más. Mientras encuentres una solución – Mayhem

Cuestiones relacionadas