Python Logo

Cómo hacer un servidor HTTP básico en Python

Probando unas cosas me he encontrado con la necesidad de tener un pequeño servidor que escuchara peticiones entrantes y realizara un acción basado en ello. Para lograrlo hay diferentes formas de hacerlo: levantar un servidor web y escribir el código con ASP.NET MVC o PHP, escribir una aplicación nativa utilizando sockets, etc.Sin embargo, quería algo rápido, sencillo y con posibilidad luego de extenderlo en el caso de que fuera necesario. Así que partiendo de esos requisitos terminé con Python y sus capacidades nativas que tiene para desplegar un servidor web.

¿Qué es necesario para ejecutar nuestro servidor?

Dentro de la rama 3.x de Python tenemos disponible dentro del módulo http una clase que nos permite crear un servidor web, su nombre es bastante descriptivo: server. Dicha clase hereda de la clase base socketserver.TCPServer implementando los elementos necesarios para responder a peticiones bajo el protocolo HTTP.

Junto con ello, necesitamos definir qué sucede cuando recibimos una petición. Para ello vamos a definir un manejador o handler. Utilizaremos como punto de partida la implementación básica que proporciona Python a través de BaseHttpRequestHandler y la extenderemos. El manejador es el encargado de analizar las cabeceras y llamar al método correcto para que procese la petición. En nuestro caso trabajaremos con peticiones del tipo HTTP GET por lo que el método que necesitaremos implementar será el do_GET, si trabajáramos con el tipo HTTP POST tendríamos que implementar el método do_POST. Al método no se le pasan argumentos, toda la información está disponible en las variables a nivel de instancia del manejador. En la documentación se pueden consultar dichas variables para saber cuáles tenemos disponibles. Si traducimos esto a código nos quedaría lo siguiente.

En primer lugar importamos las dos clases que he comentado del módulo http.server

from http.server import  BaseHTTPRequestHandler, HTTPServer

Tras ello definimos la clase que acogerá a nuestro servidor. Su constructor está sobrescrito con uno propio en el que se inicializa el servidor HTTP en el puerto 5050 y se le indica cuál va a ser el manejador que gestione las peticiones.

class http_server:
    def __init__(self):
        server = HTTPServer(('', 5050), myHandler)
        server.serve_forever()

Dicho manejador lo definimos a continuación. Dentro del mismo podemos hacer aquello que sea necesario en nuestra aplicación. En el ejemplo aparece una respuesta básica en la que se le indica al cliente que se ha procesado correctamente usando el código 200, se establecen las cabeceras HTML de la respuesta y se devuelve la información.

class myHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        self.send_response(200)
        self.send_header('Content-type','text/html')
        self.end_headers()
        # Hacer lo que queramos con la petición
        return

Si estás interesado en servir ficheros HTML puedes echarle un ojo al manejador SimpleHTTPRequestHandler que te permite construir un servidor de ficheros a partir del directorio donde se ejecute el script. En la documentación existe un ejemplo de cómo hacerlo.

Por último será definir el punto de entrada de nuestro script de Python. En este caso, será la clase que hemos definido como main y dentro de la cual instanciamos a nuestro servidor http.

class main:
    def __init__(self):
 
        self.server = http_server()
 
if __name__ == '__main__':
    m = main()

Sería posible escribir todo el código como un script en lugar de hacerlo basado en clases como hemos visto. Sin embargo, de esta forma nos permite ir añadiendo funcionalidad de una forma más sencilla y organizada.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.