LABS · JULIÁN LÓPEZ JIMÉNEZ · RECURSO GRATUITO
Tres diagnósticos completos: conexión rechazada, ruta incorrecta y proceso vivo sin datos preparados. Evidencias, pistas y soluciones; sin cuenta ni tarjeta.
Resuelve causa, evidencia, corrección mínima y prueba funcional antes de abrir la solución. Después realiza la práctica real.
El servidor usa 18991 y el cliente intenta 18992.
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.Clasifica la frontera: proceso, red, contrato, datos o compatibilidad.
Contrasta la petición y el estado antes de proponer un cambio: Servidor: 127.0.0.1:18991
Usar el puerto 18991 de la instancia, sin abrir puertos públicos.
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.
La conexión funciona, pero el cliente pide /health.
Evidencias ficticias preparadas; no se ejecutan servicios en el navegador
GET /health →404 {error:ruta}
Contrato: GET /healthz
Mismo host y puerto funcionan.Clasifica la frontera: proceso, red, contrato, datos o compatibilidad.
Contrasta la petición y el estado antes de proponer un cambio: GET /health →404 {error:ruta}
Solicitar /healthz sin cambiar puertos o desactivar seguridad.
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.
El proceso responde y todavía no existe la tabla de datos.
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.Clasifica la frontera: proceso, red, contrato, datos o compatibilidad.
Contrasta la petición y el estado antes de proponer un cambio: GET /healthz →200 {vivo:true}
Crear la base docente con iniciar, conservando el proceso y la verificación.
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.
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"
)
En Windows puedes usar py -3.12 en lugar de python. En macOS/Linux utiliza python3 si corresponde.
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.
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 /readyzNo borres datos de otros proyectos para repetir. Un archivo de base distinto permite otro ensayo.
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.
Cambia el puerto del servidor y del cliente de forma coherente; repite los tres resultados y explica qué has aprendido sin copiar las soluciones.
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.
Repite con datos distintos antes de marcarlo como practicado. Esta es una autoevaluación, no una certificación.
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 temarioFuente: 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.