LABS · JULIÁN LÓPEZ JIMÉNEZ · RECURSO GRATUITO

Mi API responde en local, pero fuera falla

Tres diagnósticos completos: conexión rechazada, ruta incorrecta y proceso vivo sin datos preparados. Evidencias, pistas y soluciones; sin cuenta ni tarjeta.

Diagnóstico: evidencias preparadas, sin ejecutar Python y servicios

Resuelve causa, evidencia, corrección mínima y prueba funcional antes de abrir la solución. Después realiza la práctica real.

Conexión rechazada no es una respuesta HTTP

El servidor usa 18991 y el cliente intenta 18992.

Observaciones del caso
Evidencias ficticias preparadas; no se ejecutan servicios en el navegador

Servidor: 127.0.0.1:18991
Cliente: 127.0.0.1:18992 → conexión rechazada
No se recibe estado HTTP.
Causa principal
  1. El cliente apunta a otro puerto, sin un proceso que acepte esa conexión.
  2. La ruta solicitada no coincide con la del contrato.
  3. La dependencia de datos no está preparada aunque el proceso esté vivo.
Evidencia determinante
  1. La salida muestra: Mismo host y puerto funcionan.
  2. La salida muestra: No se ha ejecutado iniciar para gratis.sqlite.
  3. La salida muestra: No se recibe estado HTTP.
Corrección mínima
  1. Crear la base docente con iniciar, conservando el proceso y la verificación.
  2. Usar el puerto 18991 de la instancia, sin abrir puertos públicos.
  3. Solicitar /healthz sin cambiar puertos o desactivar seguridad.
Cómo verificarlo
  1. Repetir /healthz y recibir 200 con vivo=true.
  2. Comparar /health=404 y /healthz=200 en el mismo proceso.
  3. Confirmar readyz=200 después de preparar y repetir healthz.
Pista 1 de 3

Clasifica la frontera: proceso, red, contrato, datos o compatibilidad.

Pista 2 de 3

Contrasta la petición y el estado antes de proponer un cambio: Servidor: 127.0.0.1:18991

Pista 3 de 3

Usar el puerto 18991 de la instancia, sin abrir puertos públicos.

Solución razonada
  1. El cliente apunta a otro puerto, sin un proceso que acepte esa conexión.
  2. La salida muestra: No se recibe estado HTTP.
  3. Usar el puerto 18991 de la instancia, sin abrir puertos públicos.
  4. Repetir /healthz y recibir 200 con vivo=true.

El cliente apunta a otro puerto, sin un proceso que acepte esa conexión. Usar el puerto 18991 de la instancia, sin abrir puertos públicos. Repetir /healthz y recibir 200 con vivo=true. Son evidencias preparadas; después realiza y documenta la práctica real.

Un 404 demuestra que sí hubo conversación HTTP

La conexión funciona, pero el cliente pide /health.

Observaciones del caso
Evidencias ficticias preparadas; no se ejecutan servicios en el navegador

GET /health →404 {error:ruta}
Contrato: GET /healthz
Mismo host y puerto funcionan.
Causa principal
  1. La dependencia de datos no está preparada aunque el proceso esté vivo.
  2. El cliente apunta a otro puerto, sin un proceso que acepte esa conexión.
  3. La ruta solicitada no coincide con la del contrato.
Evidencia determinante
  1. La salida muestra: No se recibe estado HTTP.
  2. La salida muestra: Mismo host y puerto funcionan.
  3. La salida muestra: No se ha ejecutado iniciar para gratis.sqlite.
Corrección mínima
  1. Solicitar /healthz sin cambiar puertos o desactivar seguridad.
  2. Crear la base docente con iniciar, conservando el proceso y la verificación.
  3. Usar el puerto 18991 de la instancia, sin abrir puertos públicos.
Cómo verificarlo
  1. Confirmar readyz=200 después de preparar y repetir healthz.
  2. Repetir /healthz y recibir 200 con vivo=true.
  3. Comparar /health=404 y /healthz=200 en el mismo proceso.
Pista 1 de 3

Clasifica la frontera: proceso, red, contrato, datos o compatibilidad.

Pista 2 de 3

Contrasta la petición y el estado antes de proponer un cambio: GET /health →404 {error:ruta}

Pista 3 de 3

Solicitar /healthz sin cambiar puertos o desactivar seguridad.

Solución razonada
  1. La ruta solicitada no coincide con la del contrato.
  2. La salida muestra: Mismo host y puerto funcionan.
  3. Solicitar /healthz sin cambiar puertos o desactivar seguridad.
  4. Comparar /health=404 y /healthz=200 en el mismo proceso.

La ruta solicitada no coincide con la del contrato. Solicitar /healthz sin cambiar puertos o desactivar seguridad. Comparar /health=404 y /healthz=200 en el mismo proceso. Son evidencias preparadas; después realiza y documenta la práctica real.

Vivo no significa preparado

El proceso responde y todavía no existe la tabla de datos.

Observaciones del caso
Evidencias ficticias preparadas; no se ejecutan servicios en el navegador

GET /healthz →200 {vivo:true}
GET /readyz →503 {lista:false}
No se ha ejecutado iniciar para gratis.sqlite.
Causa principal
  1. La ruta solicitada no coincide con la del contrato.
  2. La dependencia de datos no está preparada aunque el proceso esté vivo.
  3. El cliente apunta a otro puerto, sin un proceso que acepte esa conexión.
Evidencia determinante
  1. La salida muestra: No se ha ejecutado iniciar para gratis.sqlite.
  2. La salida muestra: No se recibe estado HTTP.
  3. La salida muestra: Mismo host y puerto funcionan.
Corrección mínima
  1. Usar el puerto 18991 de la instancia, sin abrir puertos públicos.
  2. Solicitar /healthz sin cambiar puertos o desactivar seguridad.
  3. Crear la base docente con iniciar, conservando el proceso y la verificación.
Cómo verificarlo
  1. Comparar /health=404 y /healthz=200 en el mismo proceso.
  2. Confirmar readyz=200 después de preparar y repetir healthz.
  3. Repetir /healthz y recibir 200 con vivo=true.
Pista 1 de 3

Clasifica la frontera: proceso, red, contrato, datos o compatibilidad.

Pista 2 de 3

Contrasta la petición y el estado antes de proponer un cambio: GET /healthz →200 {vivo:true}

Pista 3 de 3

Crear la base docente con iniciar, conservando el proceso y la verificación.

Solución razonada
  1. La dependencia de datos no está preparada aunque el proceso esté vivo.
  2. La salida muestra: No se ha ejecutado iniciar para gratis.sqlite.
  3. Crear la base docente con iniciar, conservando el proceso y la verificación.
  4. Confirmar readyz=200 después de preparar y repetir healthz.

La dependencia de datos no está preparada aunque el proceso esté vivo. Crear la base docente con iniciar, conservando el proceso y la verificación. Confirmar readyz=200 después de preparar y repetir healthz. Son evidencias preparadas; después realiza y documenta la práctica real.

Qué necesitas: Para diagnosticar basta un navegador con JavaScript; ordenador recomendado. Para repetir de verdad: Python 3.12+, dos terminales y una carpeta nueva. El servidor gratuito es docente y solo escucha en 127.0.0.1; no publicarlo en Internet.

Tu resultado: Distinguir fallo de conexión, respuesta 404 y readiness 503, justificando causa, cambio y comprobación.

Repite con Python real en tu equipo

Guarda el siguiente código como gratis.py en una carpeta nueva. En una terminal ejecuta python gratis.py servir. Mantén esa terminal abierta. En otra ejecuta las peticiones siguientes. No necesitas comprar el curso ni instalar Docker. Esta alternativa es local; no ejecuta Gunicorn o TLS y no sustituye el laboratorio del curso.

"""Práctica gratuita local. Servidor docente, nunca publicar en Internet."""

from contextlib import closing
import argparse
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
import json
from pathlib import Path
import sqlite3
import urllib.request
import urllib.error


def handler(db):
    class Handler(BaseHTTPRequestHandler):
        def log_message(self, *args):
            pass

        def do_GET(self):
            code, data = 404, {"error": "ruta"}
            if self.path == "/healthz":
                code, data = 200, {"vivo": True}
            if self.path == "/readyz":
                try:
                    with closing(
                        sqlite3.connect(
                            Path(db).resolve().as_uri() + "?mode=ro",
                            uri=True,
                        )
                    ) as c:
                        c.execute("SELECT valor FROM comprobacion").fetchone()
                    code, data = 200, {"lista": True}
                except sqlite3.Error:
                    code, data = 503, {"lista": False}
            body = json.dumps(data).encode()
            self.send_response(code)
            self.send_header("Content-Type", "application/json")
            self.send_header("Content-Length", str(len(body)))
            self.end_headers()
            self.wfile.write(body)

    return Handler


if __name__ == "__main__":
    p = argparse.ArgumentParser(description=__doc__)
    p.add_argument("accion", choices=["iniciar", "servir", "consultar"])
    p.add_argument("--db", default="gratis.sqlite")
    p.add_argument("--puerto", type=int, default=18991)
    p.add_argument("--ruta", default="/healthz")
    a = p.parse_args()
    if a.accion == "iniciar":
        if Path(a.db).exists():
            raise SystemExit(
                "La base ya existe; usa otro nombre para repetir sin sobrescribir"
            )
        with closing(sqlite3.connect(a.db)) as c, c:
            c.execute("CREATE TABLE comprobacion(valor TEXT)")
            c.execute("INSERT INTO comprobacion VALUES('datos ficticios')")
        print("Base local preparada")
    elif a.accion == "servir":
        print("Solo local: http://127.0.0.1:" + str(a.puerto), flush=True)
        ThreadingHTTPServer(("127.0.0.1", a.puerto), handler(a.db)).serve_forever()
    else:
        if not a.ruta.startswith("/") or a.ruta.startswith("//"):
            raise SystemExit("Ruta inválida")
        try:
            try:
                r = urllib.request.urlopen(
                    "http://127.0.0.1:" + str(a.puerto) + a.ruta, timeout=3
                )
            except urllib.error.HTTPError as e:
                r = e
            with r:
                print(r.status, r.read().decode())
        except urllib.error.URLError:
            raise SystemExit(
                "Conexión rechazada: revisa proceso y puerto; no es un 404 HTTP"
            )
Necesito una pista

En Windows puedes usar py -3.12 en lugar de python. En macOS/Linux utiliza python3 si corresponde.

Ver solución de este reto
Detén el servidor con Ctrl+C. Para repetir usa otra carpeta o un nombre de base nuevo; iniciar nunca sobrescribe una base existente.

Un fallo de conexión no tiene estado HTTP;404 y 503 son respuestas de un servidor que sí ha atendido la petición.

Comprueba: Explica cada resultado antes de consultar la solución.

Comandos y resultados observables

Caso1: con servir activo en 18991, consulta primero 18992: debe fallar la conexión. Corrige al 18991:200. Caso2: /health devuelve 404 y /healthz 200. Caso3: /readyz 503 antes de iniciar; después 200 sin reiniciar el proceso. Usa una carpeta nueva para garantizar que no había base previa. Comprueba que 18992 no lo usa otro servicio: recibir un HTTP allí no es conexión rechazada. Si está ocupado, elige otro puerto sin un servidor propio y no detengas procesos ajenos.

python gratis.py servir
# En otra terminal:
python gratis.py consultar --puerto 18992
python gratis.py consultar --puerto 18991

python gratis.py consultar --ruta /health
python gratis.py consultar --ruta /healthz

python gratis.py consultar --ruta /readyz
python gratis.py iniciar
python gratis.py consultar --ruta /readyz
Necesito una pista

No borres datos de otros proyectos para repetir. Un archivo de base distinto permite otro ensayo.

Ver solución de este reto
Conexión rechazada → puerto.404 → ruta.503 en readyz con healthz 200 → dependencia de datos no preparada.

Cada cambio corrige una frontera y se confirma repitiendo la petición que fallaba.

Comprueba: Usa --db otra.sqlite tanto en servir como en iniciar para repetir con una base independiente. Los nombres con espacios, # o % también funcionan; escríbelos entre comillas.

Tu turno

Cambia el puerto del servidor y del cliente de forma coherente; repite los tres resultados y explica qué has aprendido sin copiar las soluciones.

Ver solución y explicación
Predice → observa → cambia una causa → repite la misma petición → explica el estado posterior.

No hay un servidor dentro del playground. Las evidencias son preparadas. Comprobar no avanza ni concede XP; guardar respuestas/notas en cuenta es manual. La guía contiene todo el código gratuito para practicar sin cuenta.

Explícalo con tus palabras

Repite con datos distintos antes de marcarlo como practicado. Esta es una autoevaluación, no una certificación.

Si quieres continuar

El curso continúa con SQLite persistente, Gunicorn, proxy HTTPS, idempotencia, migraciones y restauración. El recurso y su alternativa local permanecen gratuitos.

Ver el curso Tu API en producción y su temario

Fuente: Recurso original de Labs. Puedes guardar este HTML, abrirlo sin conexión o imprimirlo como PDF desde tu navegador. No guarda tus respuestas ni el progreso de tu cuenta.