Python viene con un módulo llamado SimpleHTTPServer que permite montar un sencillo Servidor HTTP al que acceder través de localhost. Esto es útil a la hora de desarrollar porque hay cosas que no funcionan con ficheros. Por ejemplo las URLs en los navegadores web.
En la documentación de Python explica que también es posible «lanzar» directamente el servidor HTTP utilizando el modificador -m del intérprete y como argumento opcional el número de puerto.
Ejemplo:
python -m SimpleHTTPServer 8000
La clase encarga de hacer todo esto es SimpleHTTPRequestHandler que implementa la interface BaseHTTPRequestHandler. Esta clase es capaz de servir archivos del directorio actual y de cualquier archivo que esté por debajo, asi como la cartografía de la estructura de directorios en una petición HTTP:
Un problemilla: SimpleHTTPRequestHandler no admite HTTP POST
Tengo form.html que contiene un formulario con un submit action de tipo POST:
<!DOCTYPE html> <html> <head> </head> <body> <img src="python.png"/> <form action="action_page.php" method="post"> First name:<br> <input type="text" name="firstname" value="Mickey"><br> Last name:<br> <input type="text" name="lastname" value="Mouse"><br><br> <input type="submit" value="Submit"> </form> </body> </html>
Con el siguiente resultado:
Ahora bien si hago submit me encuentro con una desagradable sorpresa:
El problema es que SimpleHTTPRequestHandler implementa las funciones do_GET() y do_HEAD(), pero NO implementa do_POST() aunque si lo pensamos tiene cierta lógica.
Implementación de do_POST() con el objetivo de testear una aplicación
Si el objetivo es comprobar que información POST esta llegando al servidor esta implementación puede servirnos:
from SimpleHTTPServer import SimpleHTTPRequestHandler import SocketServer import time import urlparse from cgi import parse_header, parse_multipart class MyRequestHandler(SimpleHTTPRequestHandler): def __init__(self, *args): SimpleHTTPRequestHandler.__init__(self, *args) def parse_POST(self): ctype, pdict = parse_header(self.headers['content-type']) if ctype == 'multipart/form-data': postvars = parse_multipart(self.rfile, pdict) elif ctype == 'application/x-www-form-urlencoded': length = int(self.headers['content-length']) postvars = urlparse.parse_qs( self.rfile.read(length), keep_blank_values=1) else: postvars = {} return postvars def do_GET(self): print self.command print self.path return SimpleHTTPRequestHandler.do_GET(self) def do_POST(self): print self.command print self.path fields = self.parse_POST() self.send_response(200) self.send_header('Content-type', 'text/html') self.end_headers() self.wfile.write('<ul>') for key, value in fields.iteritems(): self.wfile.write('<li>%s: %s</li>' % (key, value)) self.wfile.write('</ul>') PORT = 8000 Handler = MyRequestHandler httpd = SocketServer.TCPServer(("", PORT), Handler) print "serving at port", PORT httpd.serve_forever()
Si lanzo el script, ahora al hacer el submit de form.htm este es el resultado:
Espero que os pueda servir.
demo: server.zip