{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "350fb575",
   "metadata": {},
   "source": [
    "<p>\n",
    "<font size='5' face='Georgia, Arial'>IIC2233 Apunte Programación Avanzada</font><br>\n",
    "<font size='1'> Modificado en 2019-1 al 2026-2 por Equipo Docente IIC2233. </font>\n",
    "</p>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0f1aa21e",
   "metadata": {},
   "source": [
    "# Tabla de contenidos\n",
    "\n",
    "1. [WebServices](#webservices)\n",
    "2. [API (*Application Programming Interface*)](#api-application-programming-interface)\n",
    "3. [URL (*Uniform Resource Locator*)](#url-uniform-resource-locator)\n",
    "4. [HTTP (*Hypertext Transfer Protocol*)](#http-hypertext-transfer-protocol)\n",
    "5. [TLS (*Transport Layer Security*)(BONUS)](#tls-transport-layer-security)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f78de0fb-2877-4abe-afeb-8f444005333b",
   "metadata": {},
   "source": [
    "## WebServices"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4ece352b",
   "metadata": {},
   "source": [
    "En nuestro primer acercamiento al uso de networking, revisaremos la comunicación entre dos dispositivos mediante la **web**.\n",
    "\n",
    "***Web services*** es el conjunto de aplicaciones cliente-servidor que se comunican a través de la web mediante un protocolo diseñado para ello. Podemos ver este tipo de servicios como aplicaciones que pueden ser accedidas por otras aplicaciones a través de una red de computadores (internet).\n",
    "\n",
    "Por ejemplo, cuando nuestro navegador (cliente) consume un sitio web (servidor), por cada **llamada al servidor**, una aplicación escrita en algún lenguaje de programación **envía una respuesta** en [HTML](https://es.wikipedia.org/wiki/HTML) (el lenguaje que se utiliza para definir la estructura de un sitio web) para que nuestro navegador la despliegue. Los _web services_ funcionan de forma similar, donde la salida está dirigida a una **aplicación que consume** esta información. Para que la comunicación sea posible, el formato de los mensajes debe ser conocido por ambas partes, para que la información pueda ser interpretada correctamente."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6912f199",
   "metadata": {},
   "source": [
    "## API (*Application Programming Interface*)\n",
    "\n",
    "En general se conoce como **API** al conjunto de funciones que son expuestas por un servicio para ser utilizadas por otros programas. Podemos ver al servicio como una clase, y a la API como el conjunto de métodos de esa clase. El servicio puede ser un *web service* o cualquier paquete que exponga una interfaz, por ejemplo una librería de Python. Sin embargo, en este capítulo cuando hablemos de API nos estaremos refiriendo a los métodos expuestos por un servicio web (un *web service*).\n",
    "\n",
    "Una gran parte de los servicios actuales exponen una API, y permiten que otras aplicaciones se conectan a ellas. De esta manera podemos construir aplicaciones que utilizan servicios que se encuentren en computadores remotos, e interactuar con ellos.\n",
    "\n",
    "En una red de computadores, cada página web de internet es almacenada en un computador remoto que ejecuta un proceso servidor. Un servidor remoto es simplemente un programa que escuchas *requests* (solicitudes) y envía *responses* (respuestas) de acuerdo a un protocolo.\n",
    "\n",
    "Tú puedes utilizar tu propio computador para servir un sitio web. De hecho, los desarrolladores de *software* usan sus propios computadores como servidores locales al crear sitios web antes de publicarlos al mundo.\n",
    "\n",
    "Cuando escribes https://www.spotify.com en tu navegador, este envía una *request* a un servidor remoto de Spotify. Una vez que tu navegador recibe la respuesta del servidor, este la interpreta y despliega una página para ti.\n",
    "\n",
    "Para el navegador (cliente), el servidor de Spotify es una API. Esto significa que cada vez que tú visitas una página en la web, tú interactúas con alguna API en un servidor remoto. Una API no es lo mismo que un servidor remoto, pero es la parte de este que recibe las *requests* y envía *responses* (respuestas).\n",
    "\n",
    "Si cada objeto tecnológico de tu casa expusiera una API, podrías controlarla completamente desde tu celular o desde cualquier programa en Python u otro lenguaje (ver más en [internet de las cosas](https://es.wikipedia.org/wiki/Internet_de_las_cosas)).\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "92e60eca",
   "metadata": {},
   "source": [
    "## URL (*Uniform Resource Locator*)\n",
    "\n",
    "Una **URL** es la dirección que identifica de forma única un recurso en la web. Toda request HTTP comienza por construir o conocer la URL del recurso al que se quiere acceder.\n",
    "\n",
    "### Estructura de una URL\n",
    "\n",
    "```\n",
    "https://api.ejemplo.com:8080/users/42/posts?page=2&limit=10#comentarios\n",
    "└──┬──┘ └──────┬───────┘└─┬─┘└─────┬──────┘└──────┬──────┘└────┬─────┘\n",
    " esquema      host       puerto    ruta         parámetros    fragmento\n",
    "```\n",
    "\n",
    "| Componente | Ejemplo | Descripción |\n",
    "|------------|---------|-------------|\n",
    "| **Esquema** (*scheme*) | `https` | Protocolo a usar (`http`, `https`, `ftp`, …). |\n",
    "| **Host** | `api.ejemplo.com` | Nombre de dominio o dirección IP del servidor. |\n",
    "| **Puerto** | `8080` | Puerto TCP. Opcional: si se omite se usa el puerto por defecto del esquema (`80` para HTTP, `443` para HTTPS). |\n",
    "| **Ruta** (*path*) | `/users/42/posts` | Identifica el recurso dentro del servidor. |\n",
    "| **Query string** | `page=2&limit=10` | Parámetros clave-valor que modifican la solicitud. Van después de `?`, separados por `&`. |\n",
    "| **Fragmento** (*fragment*) | `#comentarios` | Sección dentro del documento. Solo lo usa el navegador; **no se envía al servidor**. |"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "911e5d8b",
   "metadata": {},
   "source": [
    "## HTTP (*Hypertext Transfer Protocol*)\n",
    "\n",
    "Gran parte de las arquitecturas de *web services* se basan en el uso del protocolo **HTTP**. Este protocolo de aplicación está encargado de proporcionar una capa para realización de transacciones y así permitir la comunicación entre clientes y servidores. HTTP trabaja como un protocolo ***request-response*** en donde el cliente hace una solicitud (*request*) y el servidor responde con la información solicitada (*response*).\n",
    "\n",
    "HTTP es un protocolo en el que el servidor no guarda ninguna información de las conexiones. Por ejemplo, al acceder a métodos de un servicio web que requiere identificación del cliente, este deberá en cada consulta enviar **algo** que acredite su identidad.\n",
    "\n",
    "El funcionamiento de este protocolo se basa en la definición de **métodos o verbos** que indican la acción a desarrollar por un determinado recurso. Los recursos pueden ser datos existentes en el servidor (por ejemplo, archivos) o bien una salida generada dinámicamente. La versión HTTP/1.1 (RFC 9112) define **nueve** métodos:\n",
    "\n",
    "- `GET`: recupera una representación de un recurso sin cambiar nada en el servidor.\n",
    "- `HEAD`: igual que `GET`, pero el servidor solo devuelve los *headers*, sin *body*. Útil para verificar si un recurso existe.\n",
    "- `POST`: crea un recurso.\n",
    "- `PATCH`: aplica modificaciones parciales a un recurso.\n",
    "- `PUT`: reemplaza completamente un recurso existente.\n",
    "- `DELETE`: elimina un recurso.\n",
    "- `OPTIONS`: consulta qué métodos soporta el servidor para un recurso determinado.\n",
    "- `CONNECT`: establece un túnel hacia el servidor (usado por proxies HTTPS).\n",
    "- `TRACE`: realiza una prueba de bucle (*loopback*) a lo largo de la ruta hacia el servidor (principalmente para diagnóstico).\n",
    "\n",
    "Sin embargo, los métodos más utilizados son GET, POST, PATCH, PUT, DELETE.\n",
    "\n",
    "### Códigos de estado HTTP\n",
    "\n",
    "HTTP incluye un conjunto de **códigos de estado** mediante los cuales se entrega información al cliente sobre el resultado de su petición. Los códigos están agrupados en cinco categorías según su primer dígito:\n",
    "\n",
    "| Rango | Categoría       | Significado general                                         |\n",
    "|-------|-----------------|-------------------------------------------------------------|\n",
    "| 1xx   | Informacional   | La solicitud fue recibida y el proceso continúa             |\n",
    "| 2xx   | Éxito           | La solicitud fue recibida, entendida y aceptada con éxito   |\n",
    "| 3xx   | Redirección     | Se requiere acción adicional para completar la solicitud    |\n",
    "| 4xx   | Error del cliente | La solicitud contiene errores o no puede ser completada   |\n",
    "| 5xx   | Error del servidor | El servidor falló al intentar completar la solicitud     |\n",
    "\n",
    "Algunos códigos comunes de respuesta son:\n",
    "\n",
    "**2xx — Éxito**\n",
    "- (*)`200 OK`: solicitud exitosa. Es la respuesta estándar para peticiones `GET`.\n",
    "- (*)`201 Created`: recurso creado exitosamente. Típico de peticiones `POST`.\n",
    "- `204 No Content`: solicitud exitosa pero sin contenido en la respuesta. Típico de `DELETE`.\n",
    "\n",
    "**3xx — Redirección**\n",
    "- `301 Moved Permanently`: el recurso se ha movido de forma permanente a una nueva URL.\n",
    "- `304 Not Modified`: el recurso no ha cambiado; el cliente puede usar su versión en caché.\n",
    "\n",
    "**4xx — Error del cliente**\n",
    "- `400 Bad Request`: la solicitud está mal formada o contiene parámetros inválidos.\n",
    "- (*)`401 Unauthorized`: se requiere autenticación; las credenciales no fueron proporcionadas o son inválidas.\n",
    "- (*)`403 Forbidden`: la petición es válida, pero el servidor rechaza responderla (sin permisos).\n",
    "- (*)`404 Not Found`: el recurso solicitado no existe en el servidor.\n",
    "- `405 Method Not Allowed`: el método HTTP usado no está permitido para ese recurso.\n",
    "- `429 Too Many Requests`: el cliente ha enviado demasiadas solicitudes en poco tiempo (*rate limiting*).\n",
    "\n",
    "**5xx — Error del servidor**\n",
    "- (*)`500 Internal Server Error`: error genérico; algo falló dentro del servidor.\n",
    "- `502 Bad Gateway`: el servidor actuando como *proxy* recibió una respuesta inválida.\n",
    "- `503 Service Unavailable`: el servidor no está disponible temporalmente (sobrecarga o mantenimiento).\n",
    "\n",
    "En el mundo real, los códigos con (*) son los mas comunes. Para más detalle de los códigos pueden revisar el siguiente [enlace](http://www.w3schools.com/tags/ref_httpmessages.asp).\n",
    "\n",
    "Adicionalmente, tanto las *request* como las *response*: \n",
    "* Presentan un ***header***, el cual almacena información adicional a la consulta o respuesta, como es el caso de las credenciales de autentificación, almacenamiento en cache, cookies, [entre otros](https://developer.mozilla.org/docs/Web/HTTP/Reference/Headers).\n",
    "* Pueden presentar un **body**, el cual corresponde a los datos transmitidos en la consulta o respuesta.  \n",
    "  El tipo de información que almacena el *body* de un mensaje puede variar, por lo que se utiliza el *header* `Content-type` para indicar el tipo de información que almacena el *body*. Algunos de estos son:\n",
    "    * HTML (`Content-Type: text/html`)\n",
    "    * JSON (`Content-Type: application/json`)\n",
    "    * Texto plano (`Content-Type: text/plain`)\n",
    "    * Imágenes (`Content-Type: image/jpeg, image/png, image/gif` dependiendo del tipo de archivo)\n",
    "\n",
    "\n",
    "Para resumir todo lo anterior, la siguiente figura muestra un ejemplo con la estructura de los mensaje HTTP para la *request* del cliente y para la *response* desde el servidor.\n",
    "\n",
    "![](img/http_message.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "86b28d01",
   "metadata": {},
   "source": [
    "# =========BONUS=========\n",
    "\n",
    "## TLS (*Transport Layer Security*) \n",
    "\n",
    "### ¿Qué es TLS?\n",
    "\n",
    "**TLS** es el protocolo estándar para **cifrar las comunicaciones** en internet. Cuando una URL comienza con `https://` en lugar de `http://`, la conexión está protegida por TLS. Es el sucesor de SSL (*Secure Sockets Layer*), aunque ambos nombres se siguen usando indistintamente en la práctica.\n",
    "\n",
    "TLS actúa **entre la capa de aplicación y la capa de transporte**, por encima de TCP pero por debajo de HTTP, y es completamente **transparente** para la aplicación: el código que hace una petición HTTP no necesita cambiar para beneficiarse de TLS.\n",
    "\n",
    "```\n",
    "Capa de Aplicación  │  HTTP, FTP, SMTP, ...\n",
    "────────────────────┼──────────────────────\n",
    "Capa de Seguridad   │  TLS / SSL  ◄── cifrado aquí\n",
    "────────────────────┼──────────────────────\n",
    "Capa de Transporte  │  TCP\n",
    "────────────────────┼──────────────────────\n",
    "Capa de Red         │  IP\n",
    "```\n",
    "\n",
    "### ¿Qué protege TLS?\n",
    "\n",
    "TLS garantiza tres propiedades fundamentales en la comunicación:\n",
    "\n",
    "| Propiedad         | Descripción                                                                      |\n",
    "|-------------------|----------------------------------------------------------------------------------|\n",
    "| **Confidencialidad** | Los datos viajan cifrados; nadie que intercepte el tráfico puede leerlos.     |\n",
    "| **Integridad**    | Cualquier modificación de los datos en tránsito es detectada y la conexión se rechaza. |\n",
    "| **Autenticación** | El cliente puede verificar que realmente está hablando con el servidor correcto (no un impostor). |\n",
    "\n",
    "### El *handshake* TLS\n",
    "\n",
    "Antes de intercambiar datos, cliente y servidor realizan un **TLS handshake** (negociación) para establecer la conexión segura. Los pasos principales son:\n",
    "\n",
    "1. **ClientHello**: el cliente indica las versiones de TLS y los algoritmos de cifrado que soporta.\n",
    "2. **ServerHello**: el servidor elige la versión y el algoritmo a usar.\n",
    "3. **Certificado**: el servidor envía su **certificado digital** (emitido por una Autoridad Certificadora, o CA) para que el cliente verifique su identidad.\n",
    "4. **Intercambio de claves**: cliente y servidor negocian una **clave de sesión** compartida usando criptografía asimétrica (por ejemplo, con el algoritmo Diffie-Hellman).\n",
    "5. **Finished**: ambas partes confirman que el canal seguro está establecido y comienzan a enviar datos cifrados con la clave de sesión.\n",
    "\n",
    "### Certificados digitales y HTTPS\n",
    "\n",
    "Un **certificado digital** es un documento electrónico que asocia una clave pública con la identidad de su propietario (por ejemplo, el dominio `www.banco.cl`). Lo emite y firma una **Autoridad Certificadora (CA)** de confianza (como Let's Encrypt, DigiCert o Comodo).\n",
    "\n",
    "Cuando tu navegador visita `https://www.ejemplo.com`:\n",
    "1. Recibe el certificado del servidor.\n",
    "2. Verifica que esté firmado por una CA de confianza instalada en el sistema operativo.\n",
    "3. Verifica que el dominio del certificado coincida con la URL solicitada.\n",
    "4. Si todo es correcto, muestra el candado 🔒 en la barra de direcciones.\n",
    "\n",
    "### HTTP vs HTTPS\n",
    "\n",
    "| Característica            | HTTP                      | HTTPS (HTTP + TLS)          |\n",
    "|---------------------------|---------------------------|-----------------------------|\n",
    "| Cifrado                   | No                        | Sí                          |\n",
    "| Puerto por defecto        | 80                        | 443                         |\n",
    "| Integridad de datos       | No garantizada            | Garantizada                 |\n",
    "| Autenticación del servidor| No                        | Sí (mediante certificado)   |\n",
    "| Velocidad                 | Más rápido (sin overhead) | Mínimo overhead con TLS 1.3 |\n",
    "| Recomendado para          | Desarrollo local          | Cualquier uso en producción |"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
