3.7. Servidor HTTP

Un servidor HTTP en Python esta disponible mediante la librería http.server el uso de esta puede ejecutarse por línea de comando usando el interprete Python o desde script Python.

3.7.1. Archivos a servir

El http.server en Python puede servir archivos estáticos, como archivos HTML, a continuación unos archivos:

3.7.1.1. test.html

<!DOCTYPE html>
<html>
  <head>
    <title>HTTP GET verb</title>
  </head>
  <body>
    <h1>This is a GET verb!</h1>
  </body>
</html>

Importante

Usted puede descargar los archivos HTML en esta sección haciendo clic en los siguientes enlaces: index2.html, index.html, y test.html.

Cree y guarde con el contenido los anteriores archivos dentro de una carpeta llamada leccion3 para usar en las siguientes prácticas.

Truco

La estructura de la carpeta llamada http donde se encuentra los archivos HTML, como se muestra a continuación:

proyectos/
└── http/
    ├── index2.html
    ├── index.html
    └── test.html

3.7.2. Línea de comando

Python le permite la ejecución en línea de comando usando el interprete Python de un servidor HTTP de forma local.

En Python 3 usted puede desplegar un simple servidor HTTP desde línea de comando, ejecutando dentro de la carpeta llamada leccion3 el siguiente comando:

python3 -m http.server

Si ejecuto el comando anterior, este da como resultado lo siguiente:

Serving HTTP on 0.0.0.0 port 8000 ...

De esta forma, una vez ejecutado el comando, se puede abrir desde con su navegador Web favorito (Mozilla Firefox, Google Chrome, etc) las siguientes direcciones:

Si desea cambiar el puerto de ejecución del servidor HTTP local, ejecute dentro de la carpeta llamada http el siguiente comando:

python3 -m http.server 8001

Si ejecuto el comando anterior, este da como resultado lo siguiente:

Serving HTTP on 0.0.0.0 port 8001 ...

De esta forma, una vez ejecutado el comando, se puede abrir desde con su navegador Web favorito (Mozilla Firefox, Google Chrome, etc) las siguientes direcciones:

Si desea cambiar la IP de ejecución del servidor HTTP local, ejecute dentro de la carpeta llamada http el siguiente comando:

python3 -m http.server 8080 --bind 127.0.0.1

Si ejecuto el comando anterior, este da como resultado lo siguiente:

Serving HTTP on 127.0.0.1 port 8080 ...

De esta forma, una vez ejecutado el comando, se puede abrir desde con su navegador Web favorito (Mozilla Firefox, Google Chrome, etc) las siguientes direcciones:

De esta forma, puede usar la librería http.server para servir archivos estáticos, como archivos HTML.


3.7.3. Ejecución en script

Python le permite la ejecución vía script de un servidor HTTP de forma local, este tiene un comportamiento básico que le demuestra al menos dos métodos HTTP GET y POST. Usted puede desplegar un simple servidor HTTP usando las librerías urllib y http.server con el siguiente código fuente:

import urllib.parse
import html
import os
import sys
from pathlib import Path

try:
    from http.server import BaseHTTPRequestHandler, HTTPServer
    import urllib.request
except ImportError:
    print("use python3 instead python")
    sys.exit(1)

# Server IP
HOST_NAME = "127.0.0.1"

# Server port
PORT_NUMBER = "8085"


class MyHTTPRequestHandler(BaseHTTPRequestHandler):
    """Create custom HTTPRequestHandler class"""

    def _set_headers(self):
        """Set HTTP headers"""

        # send code 200 response
        self.send_response(200)
        # send header first
        self.send_header("Content-type", "text/html; charset=utf-8")
        self.send_header("X-Content-Type-Options", "nosniff")
        self.send_header("X-Frame-Options", "DENY")
        self.send_header("Content-Security-Policy", "default-src 'self'")
        self.send_header("X-XSS-Protection", "1; mode=block")
        # send file content to client
        self.end_headers()

    def do_GET(self):
        """Handle GET command"""

        ROOT_DIR = Path(os.path.dirname(__file__))  # file location
        try:
            if self.path.endswith(".html"):
                # Sanitize and validate path
                requested_path = ROOT_DIR / self.path.lstrip("/")
                if not requested_path.is_file() or not str(requested_path).startswith(
                    str(ROOT_DIR)
                ):
                    raise OSError("Invalid path")

                with open(requested_path) as f:  # open requested file
                    # set headers
                    self._set_headers()
                    # send file content to client
                    self.wfile.write(bytes(f.read(), "utf-8"))
                f.close()
                return
        except OSError:
            self.send_error(404, "File not found")

    def do_POST(self):
        """Handle POST command"""
        try:
            # Read the form data posted
            content_length = int(self.headers.get("Content-Length", 0))
            if content_length > 1048576:  # Limit to 1MB
                raise ValueError("Content too large")

            post_data = self.rfile.read(content_length)
            form = urllib.parse.parse_qs(post_data.decode("utf-8"))

            # Get data from fields
            message = form.get("message", [""])[0] or "Default"

            # Sanitize user input
            message = html.escape(message)

            # HTML template response
            html_response = f"""<!DOCTYPE html>
<html>
  <body>
    <h1>POST verb demo</h1>
    <p>The message is '{message}'.</p>
    <br />
    <p>This is a POST verb!</p>
  </body>
</html>\n"""

            # set HTTP headers
            self._set_headers()
            # Write the response
            self.wfile.write(bytes(html_response, "utf-8"))
        except Exception as e:
            self.send_error(400, "Bad Request")


def run():
    """Run HTTP Server"""
    server = None
    try:
        print("HTTP Server is starting...")
        server_address = (HOST_NAME, int(PORT_NUMBER))
        server = HTTPServer(server_address, MyHTTPRequestHandler)
        print(
            f" HTTP Server running on http://{HOST_NAME}:{PORT_NUMBER}/ use <Ctrl-C> to stop."
        )
        server.serve_forever()
    except KeyboardInterrupt:
        print(" <Ctrl-C> entered, stopping HTTP Server...")
        if server:
            server.socket.close()


if __name__ == "__main__":
    """Starting HTTP Server"""
    run()
else:
    print("This program is bad configured, you should be call to the module...")

Importante

Usted puede descargar el código usado en esta sección haciendo clic en los siguientes enlaces:

Truco

Para ejecutar el código httpserver.py abra una consola de comando, acceda al directorio donde se encuentra el programa y los archivos a servir:

proyectos/
└── http/
    ├── httpserver.py
    ├── index2.html
    ├── index.html
    └── test.html

Si tiene la estructura de archivo previa, entonces ejecute el siguiente comando:

python3 httpserver.py

Para probar el funcionamiento del script del servidor HTTP, abra otra ventana de la terminal de comando, donde puede usar el cliente cURL para hacer una petición GET al recurso test.html, ejecutando el siguiente comando:

curl -X GET 127.0.0.1:8085/test.html

Si ejecuto el comando anterior, este da como resultado lo siguiente:

<!DOCTYPE html>
<html>
  <head>
    <title>HTTP GET verb</title>
  </head>
  <body>
    <h1>This is a GET verb!</h1>
  </body>
</html>

Para probar el funcionamiento del script del servidor HTTP, abra otra ventana de la terminal de comando, donde puede usar el cliente cURL para hacer una petición GET al recurso index.html, ejecutando el siguiente comando:

curl -X GET 127.0.0.1:8085/index.html

Para probar el funcionamiento del script del servidor HTTP, abra otra ventana de la terminal de comando, donde puede usar el cliente cURL para hacer una petición GET al recurso index2.html, ejecutando el siguiente comando:

curl -X GET 127.0.0.1:8085/index2.html

Para probar el funcionamiento del script del servidor HTTP, abra otra ventana de la terminal de comando, donde puede usar el cliente cURL para hacer una petición POST enviando un mensaje Python, ejecutando el siguiente comando:

curl -X POST -d "message=Python" 127.0.0.1:8085

Si ejecuto el comando anterior, este da como resultado lo siguiente:

<!DOCTYPE html>
<html>
  <body>
    <h1>POST verb demo</h1>
    <p>The message is 'Python'.</p>
    <br />
    <p>This is a POST verb!</p>
  </body>
</html>

Para probar el funcionamiento del script del servidor HTTP, abra otra ventana de la terminal de comando, donde puede usar el cliente cURL para hacer una petición POST enviando un mensaje vació, ejecutando el siguiente comando:

curl -X POST -d "message=" 127.0.0.1:8085

Si ejecuto el comando anterior, este da como resultado lo siguiente:

<!DOCTYPE html>
<html>
  <body>
    <h1>POST verb demo</h1>
    <p>The message is 'Default'.</p>
    <br />
    <p>This is a POST verb!</p>
  </body>
</html>

De esta forma pudo simular el comportamiento de un servidor HTTP de forma local, con al menos dos métodos HTTP GET y POST.


Ver también

Consulte la sección de lecturas suplementarias del entrenamiento para ampliar su conocimiento en esta temática.


¿Cómo puedo ayudar?

¡Mi soporte está aquí para ayudar!

Mi horario de oficina es de lunes a sábado, de 9 AM a 5 PM. UTM - Madrid, España.

La hora aquí es actualmente 7:35 PM UTM.

Mi objetivo es responder a todos los mensajes dentro de un día hábil.

Contrata mi increíble soporte profesional