Original article: HTTP Networking in JavaScript – Handbook for Beginners

HTTP es la columna vertebral del internet moderno. En este curso basado en texto, aprenderás cómo funciona el protocolo HTTP y cómo se usa en el desarrollo web del mundo real.

Todos los ejemplos de código para este curso están en JavaScript, pero los conceptos de redes que aprenderás aquí aplican generalmente para todos los lenguajes de código. Si no estás familiarizado con JavaScript todavía, puede ver mi curso de JS aquí.

He incluido todo el material de aprendizaje que necesitarás aquí en este artículo, pero si te gustaría una experiencia más práctica, puedes tomar la versión interactiva de este curso con desafíos de código en Boot.dev aquí.

También he publicado una versión en vídeo gratuito de este curso en el canal de Youtube de freeCodeCamp (en inglés):

Si te gusta este vídeo, puedes revisar mis otros tutoriales en mi canal de Youtube Boot.dev aquí.

Con eso dicho, ¡comencemos a aprender sobre HTTP!

Tabla de Contenidos

  1. ¿Por qué HTTP?
  2. ¿Qué es DNS?
  3. ¿Qué son los URIs?
  4. Async/Await
  5. Manejo de Errores
  6. Cabeceras de HTTP
  7. ¿Qué es JSON?
  8. Métodos HTTP
  9. Rutas URL y Parámetros
  10. ¿Qué es HTTPs?

¿Por qué HTTP?

Comunicando en la web

Instagram sería bastante terrible si tuvieras que copiar manualmente tus fotos al teléfono de tu amigo cuando quisieras compartirlos. Las aplicaciones modernas necesitan ser capaz de comunicar información entre los dispositivos por internet.

  • Gmail no solo almacena tus emails en variables en tu computadora, los almacena en computadoras en sus centros de datos.
  • No pierdes los mensajes de Slack si tiras tu computadora en un lago – esos mensajes existen en los servidores de Slack.

¿Cómo funciona la comunicación web?

Cuando dos computadores se comunican entre ellos, necesitan usar las mismas reglas. Como hablante inglés no me puedo comunicar verbalmente con un hablante japonés, y de forma similar, dos computadoras necesitan hablar el mismo lenguaje para comunicarse.

Este "lenguaje" que las computadoras usan se llama un protocolo. El protocolo más popular para la comunicación web es HTTP, el cual significa Protocolo de Transferencia de Hipertexto.

Interactuando con un servidor

En este curso, un montón de ejemplos de código interactuarán con el PokeAPI. Provee datos sobre Pokemón.

Aquí hay algo de código que devuelve una lista de Pokemón de la PokeAPI:

const pokemonResp = await getItemData()

logPokemons(pokemonResp.results)

async function getItemData() {
  const response = await fetch('https://pokeapi.co/api/v2/pokemon/', {
    method: 'GET',
    mode: 'cors',
    headers: {
      'Content-Type': 'application/json'
    }
  })
  return response.json()
}

function logPokemons(pokemons) {
  for (const pokemon of pokemons) {
    console.log(pokemon.name)
  } 
}

Cuando ejecutas este código, notarás que ninguno de los datos que se imprimen en la consola fue generado, ¡dentro de nuestro código! Eso se debe a que los datos que devolvimos se envían por internet desde nuestros servidores por medio de HTTP. No te preocupes, explicaré más sobre eso más tarde.

Solicitudes y Respuestas HTTP

El núcleo de HTTP es un simple sistema de solicitud-respuesta. La computadora "solicitando", también conocido como el "cliente", le pide a otra computadora algo de información. Esa computadora, el "servidor" devuelve una respuesta con la información que fue solicitada.

ReFw6nN

Hablaremos sobre las especificaciones de cómo se formatean las "solicitudes" y "respuestas" luego. Por ahora, solo imagínalo como un simple sistema de pregunta-y-respuesta.

  • Solicitud: "¿Cuáles son los ítems en el juego Fantasy Quest?"
  • Respuesta: Una lista de los ítems en el juego Fantasy Quest

HTTP potencia a los sitios web

Como discutimos, HTTP, o el Protocolo de Transferencia de Hipertexto, es un protocolo diseñado para transferir información entre computadoras.

Hay otros protocolos para comunicarse por el internet, pero HTTP es el mas popular y es particularmente genial para los sitios web y aplicaciones web.

Cada vez que visitas un sitio web, tu navegador realiza una solicitud HTTP a ese servidor del sitio web. El servidor responde con todo el texto, imágenes, e información de estilo que tu navegador necesita para renderizar su lindo sitio web.

EflKJzq

URLs HTTP

Un URL, o Localizador de Recursos Uniforme, es esencialmente la dirección de otra computadora, o "servidor" en el internet. Parte de la URL específica cómo alcanzar el servidor, y parte de él le dice al servidor qué información queremos - pero mas sobre eso luego.

Por ahora, es importante entender que una URL representa una pieza de información en otra computadora a la que queremos acceder. Podemos obtener acceso a él haciendo una solicitud, y leyendo la respuesta con el que el servidor responde.

Cómo usar las URLs en HTTP

El http:// al principio de una URL de un sitio web específica que el protocolo http será usado para comunicación.

6jiaXBn

Otros protocolos de comunicación usan URLs también, (por ello "Localizador de Recursos Uniforme"). Por eso necesitamos ser específicos cuando hacemos solicitudes HTTP prefijando la URL con http://.

Repaso sobre Solicitudes y Respuestas

  • Un "cliente" es una computadora haciendo una solicitud HTTP
  • Un "servidor" es una computadora respondiendo a una solicitud HTTP
  • Una computadora puede ser un cliente, un servidor, ambos, o ninguno. "Cliente" y "servidor" son solo palabras que usamos para describir que están haciendo las computadoras dentro de un sistema de comunicación
  • Los clientes envían solicitudes y recibe respuestas
  • Los servidores reciben solicitudes y envían respuestas

La API Fetch de JavaScript

En este curso, estaremos usando la API fetch incorporada de JavaScript para hacer solicitudes HTTP.

La función fetch() se pone a nuestra disposición por el lenguaje JavaScript ejecutándose en el navegador. Todo lo que tenemos que hacer es proveerle los parámetros que requiere.

Cómo usar Fetch

const response = await fetch(url, settings)
const responseData = await response.json()

Iremos en profundidad sobre las diversas cosas que suceden en esta llamada fetch estándar después, pero cubramos algunas bases por ahora.

  • response es el dato que es devuelto del servidor
  • url es la URL a la que le estamos haciendo una solicitud
  • settings es un objeto que contiene algunas opciones específicas de solicitud
  • La palabra clave await le dice a JavaScript que espere hasta que la solicitud vuelva del servidor antes de continuar
  • response.json() conviertes los datos de respuesta del servidor en un objeto de JavaScript

Mira si puedes encontrar el problema en este fragmento de código:

const pokemonResp = getItemData()

logPokemons(pokemonResp.results)

// el bug (error) está arriba de esta línea

async function getItemData() {
  const response = await fetch('https://pokeapi.co/api/v2/pokemon/', {
    method: 'GET',
    mode: 'cors',
    headers: {
      'Content-Type': 'application/json'
    }
  })
  return response.json()
}

function logPokemons(pokemons) {
  for (const pokemon of pokemons) {
    console.log(pokemon.name)
  } 
}

Pista: No estamos esperando que los datos sean devueltos por medio de la red.

Los Clientes Web

Un cliente web es un dispositivo realizando solicitudes a un servidor web. Un cliente puede ser de cualquier tipo de dispositivo pero frecuentemente es algo con el que los usuarios interactúan físicamente. Por ejemplo:

  • Una computadora de escritorio
  • Un teléfono móvil
  • Una tablet

En un sitio web o una aplicación web, le llamamos al dispositivo del usuario el "front-end". Un cliente front-end realiza solicitudes a un servidor back-end.

zldXGet

Los Servidores Web

A este punto, la mayoría de los datos con los que has trabajado en tu código han sido simplemente generados y almacenados localmente en variables.

A medida que siempre usarás variables para almacenar y manipular datos mientras tu programa se ejecuta, la mayoría de los sitios web y aplicaciones usan un servidor web para almacenar, ordenar, y servidor esos datos de esa forma se queda por más tiempo que una sesión única, y pueden ser accedidos por múltiples dispositivos.

Escuchando y sirviendo datos

Similar a cómo un servidor en un restaurante te trae la comida a la mesa, un servidor web sirve recursos web, tales como páginas, imágenes, y otros datos. El servidor se activa y "escucha" solicitudes entrantes constantemente de esa forma en el segundo que recibe una nueva solicitud, puede enviar una respuesta apropiada.

El servidor es el back-end

Mientras el "front-end" de un sitio web o aplicación web es el dispositivo con el que el usuario interactúa, el "back-end" es el servidor que mantiene todos los datos almacenados en un lugar central. Si todavía estás confundido, mira este artículo comparando el desarrollo front-end y back-end.

Un servidor es solo una computadora

"Servidor" es solo el nombre que le damos a una computadora que está tomando el rol de servidor de servidor datos por medio de una conexión red.

Un buen servidor se activa y está disponible los 24 horas del día, los 7 días de la semana. Mientras tu laptop puede ser usado como un servidor, tiene mas sentido usar una computadora de un centro de datos que está diseñado para estar activo y ejecutándose constantemente.

¿Qué es DNS?

Direcciones Web

En el mundo real, usamos direcciones para ayudarnos a encontrar donde vive un amigo, dónde se encuentra un negocio, o dónde se está organizando una fiesta.

En computación, los clientes web encuentran otras computadoras a través de internet usando el Protocolo de Internet o direcciones IP.

Una dirección IP es una etiqueta numérica que sirve dos funciones principales:

  1. Dirección de ubicación
  2. Identificación de Red

Nombres de Dominio y Direcciones IP

Cada dispositivo conectado al internet tiene una dirección IP única. Cuando buscamos por internet, los dominios a la que navegamos todos están asociados con una dirección IP particular.

Por ejemplo, this URL de Wikipedia apunta a una página sobre cerdos en miniatura: https://es.wikipedia.org/wiki/Minicerdo. La porción de dominio del URL es es.wikipedia.org. es.wikipedia.org se convierte a una dirección IP específica, y esa dirección IP le dice a tu computadora exactamente a dónde comunicarse con esa página de Wikipedia.

Cloudflare es una compañía tech que provee un servidor HTTP público interesante que podemos usar para buscar la dirección IP de cualquier dominio. Mira este fragmento de código:

async function fetchIPAddress(domain) {
  const resp = await fetch(`https://cloudflare-dns.com/dns-query?name=${domain}&type=A`, {
    headers: {
      'accept': 'application/dns-json'
    }
  })
  const respObject = await resp.json()
  for (const record of respObject.Answer) {
    return record.data
  }
  return null
}

const domain = 'api.boot.dev'
const ipAddress = await fetchIPAddress(domain)
if (!ipAddress) {
  console.log('Algo estuvo mal en fetchIPAddress')
} else {
  console.log(`Direccion IP encontrado para el dominio ${domain}: ${ipAddress}`)
}

Para repasar, un "nombre de dominio" es parte de un URL. Es la parte que le dice a la computadora dónde se encuentra el servidor en el internet siendo convertido en una dirección IP numérica.

Cubriremos cómo es usado exactamente una dirección IP por tu computadora para encontrar una ruta al servidor en un curso de redes después. Por ahora, es importante entender que una dirección IP es lo que tu computadora está usando en un nivel bajo para comunicarse en una red.

Desplegar un sitio web real al internet es en realidad bastante sencillo. Involucra solamente un par de pasos:

  1. Crear un servidor que hospeda tus archivos del sitio web y conectarlo al internet
  2. Adquirir un nombre de dominio
  3. Conectar el nombre de dominio a la dirección IP de tu servidor
  4. ¡Tu servidor es accesible por medio de internet!
vjjPt2a

Como discutimos, el "nombre de dominio" o "nombre de hospedaje" es parte de una URL. Llegaremos a las otras partes de un URL luego.

Por ejemplo, la URL https://example.com/path tiene un nombre de host de example.com. Las porciones https:// y /path no son parte del mapeo nombre de dominio -> dirección IP que hemos estado aprendiendo.

Usando la API URL en JavaScript

La API URL está incorporado en JavaScript. Puedes crear un nuevo objeto URL como esto:

const urlObj = new URL('https://example.com/example-path')

Y luego puedes extraer solo el nombre de host:

const urlObj.hostname

Repaso de DNS

Así que hemos hablado sobre nombres de dominio y cuál es su propósito, pero no hemos hablado sobre el sistema que es usado para hacer esa conversión.

DNS, o el "Sistema de Nombre de Dominio", es el directorio de teléfono del internet. Los humanos se conectan a los sitios web a través de nombres de dominio, como Boot.dev.

El DNS "resuelve" estos nombres de dominio para encontrar las direcciones IP asociadas de esa forma los clientes web pueden cargar los recursos para la dirección específica.

yvfSbVL

¿Cómo funciona el DNS?

Iremos en mas detalle sobre DNS en un futuro curso, pero para darte una idea simplificada de cómo funciona, introduzcamos ICANN. ICANN es una organización sin fines de lucro que gestiona el DNS para todo el internet.

Cuando tu computadora intenta resolver un nombre de dominio, contacta con uno de los "servidores raíz" de ICANN cuyo dirección está incluida en tu configuración de red de la computadora.

Desde ahí, el servidor puede reunir los registros de dominio para un nombre de dominio específico desde su base de datos de DNS distribuido.

Si ves al DNS como una guía telefónica, ICANN sería el editor que mantiene la guía telefónica en impresión y disponible.

Sub-dominios

Aprendimos cómo un nombre de dominio se traduce a una dirección IP, el cual es solo una computadora en una red - frecuentemente el internet.

Un sub-dominio prefija un nombre de dominio, permitiendo a un dominio encaminar el tráfico de red a muchos servidores y recursos distintos.

Por ejemplo, el sitio web Boot.dev está hospedado en una computadora distinta de nuestro blog. Nuestro blog, encontrado en blog.boot.dev está hospedado en nuestro sub-dominio "blog".

¿Qué son los URIs?

Brevemente tocamos los URLs anteriormente, pero ahora indaguemos un poco más profundo en el tema.

Un URI, o Identificador de Recursos Uniforme, es una secuencia de caracteres única que identifica a un recurso que es (casi siempre) accedido por medio del internet.

Así como JavaScript tiene reglas de sintaxis, de la misma forma los URIs. Estas reglas ayudan en asegurar la uniformidad así cualquier programa puede interpretar el significado de la URI de la misma forma.

Los URIs vienen en dos tipos principales:

Nos enfocaremos específicamente en los URLs en este curso, pero es importante saber que los URLs son solamente un tipo de URI.

VzqzckC

Los URLs tienen bastante secciones, algunas de las cuales son requeridos, otros no. Usemos la API URL para convertir una URL e imprimir todas las distintas partes. Aprenderemos mas sobre cada parte luego, por ahora, separemos y mostremos un URL.

function printURLParts(urlString) {
  const urlObj = new URL(urlString)
  console.log(`protocolo: ${urlObj.protocol}`)
  console.log(`nombre de usuario: ${urlObj.username}`)
  console.log(`contraseña: ${urlObj.password}`)
  console.log(`nombre de host: ${urlObj.hostname}`)
  console.log(`puerto: ${urlObj.port}`)
  console.log(`nombre de la ruta: ${urlObj.pathname}`)
  console.log(`buscar: ${urlObj.search}`)
  console.log(`hash: ${urlObj.hash}`)
}

const fantasyQuestURL = 'http://dragonslayer:pwn3d@fantasyquest.com:8080/maps?sort=rank#id'
printURLParts(fantasyQuestURL)

Disección adicional de un URL

Hay 8 partes principales de un URL, aunque no todas las secciones están presentes siempre. Cada pieza juega un rol específico en ayudar a los cliente localizar el recurso especificado.

Las 8 secciones son:

iI3sUVh
  • El protocolo es requerido
  • Los nombres de usuarios y contraseñas son opcionales
  • Un dominio es requerido
  • El puerto predeterminado para un protocolo dado es usado si uno no fue provisto
  • La ruta ( / ) predeterminada es usada si uno no es provisto
  • Una solicitud es opcional
  • Un fragmento es opcional

No te obsesiones en memorizar esto

Ya que los nombres para las diferentes secciones son usados con frecuencia indistintamente, y ya que no todas las partes del URL están siempre presentes, puede ser difícil mantener las cosas en orden.

¡No te preocupes en memorizar esto! Intenta familiarizarte con estos conceptos de URL desde un alto nivel. Como cualquier buen desarrollador, puedes buscarlo nuevamente la próxima vez que necesites saber más.

El Protocolo

El "protocolo", también referido como el "esquema", es el primero componente de un URL. Su finalidad es definir las reglas mediante los cuales se muestran los datos que se comunican, se codifican, o se formatean.

Algunos ejemplos de distintos protocolos de URL:

  • http
  • ftp
  • mailto
  • https

Por ejemplo:

  • http://example.com
  • mailto:noreply@fantasyquest.app

No todos los esquemas requieren un "//"

El "http" en un URL siempre es seguido por ://. Todos los URLs tienen el dos puntos, pero la parte // se incluye solamente para los esquemas que tienen un componente de autoridad.

Como puedes ver arriba, el esquema mailto no usa un componente de autoridad, ya que no necesita las barras.

Puertos de URL

El puerto en un URL es un punto de virtual donde las conexiones de red son hechas. Los puertos son manejados por un sistema operativo de la computadora y son enumerados desde 0 a 65,535.

Cada vez que te conectas a otra computadora por medio de una red, te estás conectando a un puerto específico en esa computadora, el cual está siendo escuchado por una pieza de software específica en esa computadora. Un puerto puede ser usado solamente por un programa a la vez, por eso hay demasiados puertos posibles.

El componente puerto de un URL no es visible frecuentemente cuando se navega en sitios normales en internet, porque el 99% del tiempo estás usando los puertos predeterminados para los esquemas HTTP y HTTPS: 80 y 443, respectivamente.

Cada vez que no estés usando un puerto predeterminado, necesitas especificarlo en el URL. Por ejemplo, el puerto 8080 es usado frecuentemente por desarrolladores web cuando están ejecutando su servidor en "modo en prueba" de esa forma no usan el puerto "80" de "producción".

h3kBsRC

Rutas de URL

En los primeros días de internet, la ruta de un URL con frecuencia era un reflejo de la ruta del archivo en el servidor al recurso que el cliente estaba solicitando.

Por ejemplo, si el sitio web https://exampleblog.com tendría un servidor web ejecutándose en su directorio /home, entonces una solicitud al URL https://exampleblog.com/site/index.html podría esperar que el archivo index.html desde dentro del directorio /home/site sea devuelto.

Los sitios web solían ser muy sencillos. Eran solo una colección de documentos de texto almacenados en un servidor. Un simple servidor de software podría manejar solicitudes HTTP entrantes y responder con los documentos de acuerdo al componente ruta de las URLs.

En estos días, no siempre es sobre el sistema de archivos

En muchos servidores web modernos, una ruta de URL no es un reflejo de la jerarquía del sistema de archivos del servidor. Las rutas en las URLs son esencialmente otro tipo de parámetro que puede ser pasado al servidor cuando se hace una solicitud.

Convencionalmente, dos rutas de URL distintas deberían denotar diferentes recursos. Por ejemplo, distintas páginas en un sitio web, o tal vez diferentes tipos de datos desde un servidor de juegos.

Parámetros de Solicitud

Los parámetros de Solicitud en un URL no siempre están presentes. En el contexto de los sitios web, los parámetros de solicitud con frecuencia son usados para hacer analíticas de marketing o para cambiar una variable en la página web. Con los URLs de sitios web, los parámetros de solicitud raramente cambian que página estás viendo, aunque frecuentemente cambiarán el contenido de la página.

Con eso dicho, los parámetros de solicitud pueden ser usados para cualquier cosa que el servidor elija, tal como la ruta de URL.

Cómo usa Google los parámetros de solicitud

  1. Abre una nueva pestaña y ve a google.com
  2. Busca "hello world"
  3. Mira a tu URL actual. Debería comenzar con https://www.google.com/search?q=hello+world
  4. Cambia el URL para que diga https://www.google.com/search?q=hello+universe
  5. Presiona "enter"

Deberías ver nuevos resultados de búsqueda para la solicitud "hello universe". Google eligió usar los parámetros de solicitud para representar el valor de tu solicitud de buśqueda. Esto tiene sentido - cada página de resultado de búsqueda es esencialmente la misma página en lo que respecta la estructura y el formato - solo te muestra diferentes resultados basado en la solicitud de búsqueda.

Async/Await

Probablemente estés familiarizado con código síncrono, el cual significa código que se ejecuta en secuencia. Cada línea de código se ejecuta en orden, uno después del otro.

03FFGu0


Ejemplo de código síncrono:

console.log("Me imprimo primero");
console.log("Me imprimo segundo");
console.log("Me imprimo tercero");

El Código asíncrono o async se ejecuta en paralelo. Esto significa que el código mas abajo se ejecuta al mismo tiempo que una línea de código anterior todavía se está ejecutando. Una buena forma de visualizar esto es con la función setTimeout() de JavaScript.

setTimeout acepta una función y un número de milisegundos como entradas. Espera hasta que el número de milisegundos ha transcurrido, y luego ejecuta la función que le fue dada.

Ejemplo de código asíncrono:

jsconsole.log("Me imprimo primero");
setTimeout(() => console.log("Me imprimo tercero porque estoy esperando 100 milisegundos"), 100);
console.log("Me imprimo segundo");

Intenta alterar los tiempos de espera en el código asíncrono abajo para que se impriman los mensajes en el orden correcto:

const craftingCompleteWait = 0
const combiningMaterialsWait = 0
const smeltingIronBarsWait = 0
const shapingIronWait = 0

// No toques nada debajo de esta línea

setTimeout(() => console.log('Iron Longsword Complete!'), craftingCompleteWait)
setTimeout(() => console.log('Combining Materials...'), combiningMaterialsWait)
setTimeout(() => console.log('Smelting Iron Bars...'), smeltingIronBarsWait)
setTimeout(() => console.log('Shaping Iron...'), shapingIronWait)

console.log('Firing up the forge...')

await sleep(2500)
function sleep(ms) {
  return new Promise((resolve) => setTimeout(resolve, ms))
}

Orden esperado:

  1. Firing up the forge..
  2. Smelting Iron Bars...
  3. Combining Materials...
  4. Shaping Iron...
  5. Iron Longsword Complete!

¿Por qué queremos código asíncrono?

Intentamos mantener la mayoría de nuestro código síncrono porque es mas fácil de entender, y por lo tanto frecuentemente tiene menos errores. pero a veces necesitamos que nuestro código sea asíncrono.

Por ejemplo, cada vez que actualices tus opciones de usuario en un sitio web, tu navegador necesitará comunicar esas nuevas opciones al servidor. El tiempo que toma tu solicitud de HTTP para que viaje físicamente a través de todo el cableado del internet es usualmente cerca de los 100 milisegundos. Sería una experiencia muy pobre si tu sitio web se fuera a congelar mientras esperas que la solicitud de red finalice. ¡Inclusive no serías capaz de mover el mouse mientras esperas!

Haciendo solicitudes de red de manera asíncrona, le permitimos a la página web que ejecute otro código mientras espera la respuesta HTTP que regrese. Esto mantiene a la experiencia de usuario ágil y amigable.

Como regla general, solamente deberíamos usar código asíncrono cuando lo necesitamos por razones de rendimiento. Código síncrono es mas sencillo.

03FFGu0

Promesas en JavaScript

Una Promesa en JavaScript es muy similar a hacer una promesa en el mundo real. Cuando hacemos una promesa, estamos haciendo un compromiso para algo.

Por ejemplo, Te prometo explicarte las promesas de JavaScript. Mi promesa para ti tiene dos salidas potenciales: o está concluida, lo que significa que eventualmente te expliqué las promesas, o está rechazada, lo que significa que fallé en mantener mi promesa y no te expliqué las promesas.

El Objeto Promesa representa la eventual conclusión o rechazo de nuestra promesa y mantiene los valores resultantes. Por el momento, mientras esperamos que la promesa se cumpla, nuestro código continúa ejecutándose.

Las promesas son la forma moderna más popular para escribir código asíncrono en JavaScript.

Cómo declarar una Promesa

Aquí hay un ejemplo de una promesa que resolverá y devolverá la cadena "resuelto!" o rechazara y regresará la cadena "rechazado!" después de 1 segundo.

const promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    if (getRandomBool()) {
      resolve("resuelto!")
    } else {
      reject("rechazado!")
    }
  }, 1000)
})

function getRandomBool(){
  return Math.random() < .5
}

Cómo usar una Promesa

Ahora que hemos creado una promesa, ¿cómo lo usamos?

El objeto Promise tiene .then y .catch lo cual hace más fácil el trabajo. Imagínate a .then como el seguimiento esperado a una promesa, y .catch como el seguimiento "algo estuvo mal".

Si una promesa resuelve, su función .then se ejecutará. Si la promesa rechaza, su método .catch se ejecutará.

Aquí hay un ejemplo de usar .then y .catch con la promesa que hicimos arriba:

promise.then((message) => {
    console.log(`La promesa ${message} finalmente`)
}).catch((message) => {
    console.log(`La promesa ${message} finalmente`)
})

// imprime:
// La promesa se resolvio finalmente!
// o
// la promesa se rechazo finalmente!

¿Por qué las Promesas son útiles?

Las Promesas son la forma mas limpia (pero no la única) para manejar el escenario común donde necesitamos realizar solicitudes a un servidor, que es típicamente hecho por medio de una solicitud HTTP. De hecho, la función fetch() que estuvimos usando anteriormente en el curso, ¡devuelve una promesa!

I/O, o "input/output"

Casi cada vez que usas una promesa en JavaScript será para manejar algo de I/O. I/O, o input/output, se refiere a cuando nuestro código necesita interactuar con sistema fuera (relativamente) del sencillo mundo de las variables y funciones locales.

Ejemplos comunes de I/O incluyen:

  • Solicitudes HTTP
  • Leer archivos desde el disco duro
  • Interactuar con un dispositivo Bluetooth

Las Promesas nos ayudan realizar I/O sin forzar a todo nuestro programa que se congele mientras esperamos una respuesta.

Las Promesas y la palabra clave "await"

Hemos usado la palabra clave await unas pocas veces en este curso, así que es tiempo que finalmente entendamos que está pasando por debajo.

La palabra clave await se usa para esperar a una promesa que se resuelva. Una vez que se ha resuelto, la expresión await devuelve el valor de la Promise resuelta.  

Ejemplo con el callback .then

promise.then((message) => {
  console.log(`Resuelto con ${message}`)
}).

Ejemplo de una promesa con await

const message = await promise
console.log(`Resuelto con ${message}`)

La palabra clave async

Ya que la palabra clave await puede ser usado en lugar de .then() para resolver una promesa, la palabra clave async puede ser usado en lugar de new promise() para crear una nueva promesa.

Cuando una función es prefijado con la palabra clave async, automáticamente devuelve una promesa. Esa promesa resuelve con el valor que código devuelve desde la función. Puedes imaginarte a async como que "envuelve" tu función dentro de una promesa.

Estos son equivalentes:

new Promise()

function getPromiseForUserData(){
  return new Promise((resolve) => {
    fetchDataFromServerAsync().then(function(user){
      resolve(user)
    })
  })
}

const promise = getPromiseForUserData()

Async

async function getPromiseForUserData(){
  const user = await fetchDataFromServer()
  return user
}

const promise = getPromiseForUserData()

.then() vs await

En los primeros días de los navegadores web, las promesas y la palabra clave await no existían, así que la única forma de hacer algo de manera asíncrona era usar los callbacks.

Una "función callback" es una función que le pasas a otra función. Esa función luego llama a tu callback. La función setTimeout que hemos usado atrás es un buen ejemplo.

function callbackFunction(){
  console.log("calling back now!")
}
const milliseconds = 1000
setTimeout(callbackFunction, milliseconds)

Mientras que inclusive la sintaxis .then() es generalmente más fácil de usar que los callbacks sin la API Promise, la sintaxis await los hace aun mas fácil de usar. Deberías usar async y await en vez de .then y new Promise() como regla general.

Para demostrar, ¿cuáles de estos es más fácil de entender?

fetchUser.then(function(user){
  return fetchLocationForUser(user)
}).then(function(location){
  return fetchServerForLocation(location)
}).then(function(server){
  console.log(`El servidor es ${server}`)
});
const user = await fetchUser()
const location = await fetchLocationForUser(user)
const server = await fetchServerForLocation(location)
console.log(`El servidor es ${server}`)

Ambos hacen la misma cosa, pero el ejemplo segundo es, ¡mucho mas fácil de entender! Las palabras claves async y await no fueron lanzados sino hasta después de la API .then, lo cual es la razón de por que hay todavía mucho código .then obsoleto por ahí afuera.

Manejo de Errores

Cuando algo sale mal mientras un programa se ejecuta, JavaScript usa el paradigma try/catch para manejar esos errores. Try/catch es bastante común, y Python usa un mecanismo similar.

Primero, se lanza un error

Por ejemplo, digamos que intentamos acceder a un propiedad de una variable no definida. JavaScript automáticamente "lanzará" un error.

const speed = car.speed
// El codigo se rompe con el siguiente error:
// "ReferenceError: car no está definido"

Intentando y capturando errores

Al envolver ese código en un bloque try/catch, podemos manejar el caso donde car todavía no es definido.

try {
  const speed = car.speed
} catch (err) {
  console.log(`Un error se disparó: ${err}`)
  // el codigo imprime de forma clara:
  // "Un error se disparó: ReferenceError: car no está definido"
}

Bugs vs Errores

Manejar errores por medio de try/catch no es lo mismo que depurar. Igualmente, los errores no son lo mismo que los bugs.

  • Un buen código sin bugs todavía puede producir errores que son manejados de manera cuidadosa
  • Los Bugs son, por definición, pedazitos de código que no están funcionando como se esperaba

¿Qué es Depurar?

"Depurar" un programa es el proceso de revisar tu código para encontrar donde no se está comportando como se espera. Depurar es un proceso manual realizado por el desarrollador.

Ejemplos de depuración:

  • Agregar un parámetro faltante a una llamada de función
  • Actualizar un URL roto el cual una llamada HTTP estaba intentando de alcanzar
  • Arreglar un componente selector de fechas en una aplicación que no se estaba mostrando apropiadamente

¿Qué es el Manejo de Errores?

"Manejo de errores" es código que puede manejar casos específicos esperados en tu programa. El Manejo de Errores es un proceso automatizado que diseñamos en nuestro código de producción para protegerlo de cosas como conexiones de internet débiles, mala entrada de usuario, o bugs en el código de otras personas con los que tenemos que interactuar.

Ejemplos de manejos de errores:

  • Usando un bloque try/catch para detectar un problema con entradas de usuario
  • Usando un bloque try/catch para que falle de manera segura cuando no hay una conexión de internet disponible

Brevemente, no uses try/catch para intentar manejar bugs

Si tu código tiene un bug, try/catch no te ayudará. Necesitas ir a encontrar el bug y arreglarlo.

Si algo que está fuera de tu control puede producir problemas en tu código, deberías usar try/catch u otra lógica de manejo de errores para tratarlo.

Por ejemplo, podría haber un mensaje en un juego para los usuarios para que se escriba un nuevo nombre de personaje, pero no queremos que usen puntuación. Validar sus entradas y mostrar un mensaje de error si algo está mal sería una forma de "manejar errores".

async/await hace el manejo de errores mas fácil

try y catch son la forma estándar de manejar errores en Javascript, el problema es, que la API Promise original con .then no nos permitió hacer uso de los bloques try y catch.

Afortunadamente, las palabras claves async y await lo permite - aún otra razón para elegir la nueva sintaxis.

El callback .catch() en las promesas

El método .catch() funciona de manera similar al método .then(), pero se dispara cuando un promesa es rechazada en vez de resuelta.

Ejemplo con los callbacks .then y .catch

fetchUser().then(function(user){
  console.log(`usuario buscado: ${user}`)
}).catch(function(err){
  console.log(`un error fue disparado: ${err}`)
});

Ejemplo de una promesa con await

try {
  const user = await fetchUser()
  console.log(`usuario buscado: ${user}`)
} catch (err) {
  console.log(`un error fue disparado: ${err}`)
}

Como puedes ver, la versión async/await se parece como un try/catch normal de JavaScript.

Cabeceras de HTTP

Una cabecera de HTTP permite a los clientes y servidor que pasen información adicional con cada solicitud o respuesta. Las cabeceras son pares de clave-valor que no distinguen entre mayúsculas y minúsculas que pasan metadatos adicionales sobre la solicitud o respuesta.

Las solicitudes HTTP de un navegador web llevan consigo muchas cabeceras, incluyendo pero no limitado a:

  • El tipo de cliente (por ejemplo Google Chrome)
  • El Sistema Operativo (por ejemplo Windows)
  • El idioma preferido (por ejemplo Inglés US)

Como desarrolladores, también podemos definir cabeceras personalizadas en cada solicitud.

La API Headers

La API Headers nos permite realizar varias acciones en nuestras cabeceras de solicitud y de respuesta tales como devolverlos, establecerlos, y removerlos. Podemos acceder a las cabeceras del objeto a través de las propiedades Request.headers y Response.headers.

Cómo usar las Herramientas de Desarrollo del Navegador

Los navegadores web modernos le ofrecen a los desarrolladores un conjunto poderoso de herramientas de desarrollado. Las Herramientas de Desarrollo son el mejor amigo de los desarrolladores web front-end. Por ejemplo, usando las herramientas de desarrollo puedes:

  • Ver la salida en consola de JavaScript de la página web
  • Inspeccionar el código HTML, CSS y JavaScript de la página
  • Ver solicitudes red y respuestas, juntamente con sus cabeceras

El método para acceder las herramientas de desarrollo de navegador a navegador. Si estás en Chrome, puedes hacer clic derecho en cualquier parte dentro de una página web y hacer clic en la opción "inspect". Sigue este enlace para mas información en cómo acceder a las herramientas de desarrollo.

La pestaña red

Mientras todas las pestañas dentro de las herramientas de desarrollo son muy útiles, nos estaremos enfocando en la pestaña de Red en este capitulo así podemos jugar con las cabeceras de HTTP.

La pestaña Red monitorea la actividad de red del navegador y registrar todas las solicitudes y respuestas que el navegador hace, incluyendo cuanto tiempo toma cada una de esas solicitudes y respuestas para que se procese completamente.

Si navegas a la pestaña Red y no ves ninguna solicitud aparecer, intenta refrescar la pagina.

STKdceG

¿Por qué las cabeceras son útiles?

Las cabeceras son útiles por varias razones, desde el diseño a la seguridad. Pero mas frecuentemente las cabeceras son usadas como metadatos o datos sobre la solicitud.

Así que, por ejemplo, digamos que queríamos pedir un nivel de jugador de un servidor de juegos. Necesitamos enviar el ID del jugador al servidor de esa forma sabe de qué jugador devuelve la información. Ese ID es mi solicitud, no es información sobre mi solicitud.

Un buen ejemplo de un caso de uso para las cabeceras es autenticación. Con frecuencia las credenciales de un usuario son incluidas en las cabeceras de solicitud. Las credenciales no tienen que ver mucho con la solicitud en sí misma, sino simplemente autoriza al solicitador ser admitido de hacer la solicitud en cuestión.

¿Qué es JSON?

Notación de Objeto de JavaScript, o JSON, es un estándar para representar datos estructurados basado en la sintaxis de objetos de JavaScript.

JSON es comúnmente usado para transmitir datos en aplicaciones web usando HTTP. Las solicitudes HTTP con fetch() que estuvimos usando en este curso han estado devolviendo datos como JSON.

Sintaxis de JSON

Porque ya entendimos cómo lucen los objetos de JavaScript, entender JSON es fácil. JSON es solo un objeto de JavaScript en cadenas. Lo siguiente son datos en JSON válidos:

{
    "movies": [
        {
            "id": 1,
            "genre": "Action",
            "title": "Iron Man",
            "director": "Jon Favreau"
        },
        {
            "id": 2,
            "genre": "Action",
            "title": "The Avengers",
            "director": "Joss Whedon"
        }
    ]
}

Cómo convertir Respuestas HTTP a JSON

JavaScript nos provee algunas herramientas fáciles para ayudarnos a trabajar con JSON. Después de hacer una solicitud HTTP con la API fetch(), obtenemos un objeto Response. Ese objeto respuesta nos ofrece algunos métodos que nos ayudan en interactuar con la respuesta.

Un método como tal es el método .json(). El método .json() toma el stream respuesta devuelto por una solicitud con fetch y devuelve una Promesa que se convierte en un objeto JavaScript desde el cuerpo JSON de la respuesta HTTP.

const resp = await fetch(...)
const javascriptObjectResponse = await resp.json()

Es importante notar que el resultado del método .json() NO es JSON. Es el resultado de tomar datos JSON desde el cuerpo de la respuesta HTTP y convertir la entrada en un Objeto JavaScript.

Revisión de JSON

JSON es una representación en cadena de un objeto JavaScript, lo cual lo hace perfecto para guardar en un archivo o enviarlo en una solicitud HTTP.

Recuerda, un objeto JavaScript es algo que existe solamente dentro de tus variables del programa. Si queremos enviar un objeto fuera de nuestro programa, por ejemplo, a través de internet en una solicitud HTTP, necesitamos convertirlo a JSON primero.

No es usado solo en JavaScript

Solo porque JSON significa Notación de Objeto de JavaScript no significa que ¡solamente es usado por JavaScript! JSON es un estándar común que es reconocido y soportado por todos los lenguajes principales de programación.

Por ejemplo, aunque la API back-end de Boot.dev está escrito en Go, todavía usamos JSON como el formato de comunicación entre el front-end y el back-end.

A propósito, este curso ha tratado sobre interactuar con servidores back-end desde una perspectiva de front-end. Pero si estás interesado sobre cómo te puedes convertir en un ingeniero back-end, mira esta guía que he preparado. Como referencia, le toma a la mayoría de gente entre 6-18 meses para aprender lo suficiente para tener su primer trabajo de back-end.

Casos de uso de JSON Comunes

  • En solicitudes HTTP y cuerpos de respuesta
  • Como formatos para archivos de texto. Archivos .json son usados frecuentemente como archivos de configuración
  • En bases de datos NoSQL como MongoDB, ElasticSearch, y Firestore

Cómo pronunciar JSON

Lo pronuncio "Yey-sawn", pero también he oído a la gente pronunciarlo "Yason", justo como su nombre.

Cómo enviar JSON

JSON no es algo que obtenemos del servidor, también podemos enviar datos JSON.

En JavaScript, dos de los métodos principales a los que tenemos acceso son JSON.parse(), y JSON.stringify().

JSON.stringify()

JSON.stringify() es útil particularmente para enviar JSON.

Como podrías esperar, el método stringify() de JSON hace lo opuesto de convertir. Toma un objeto JavaScript o un valor como entrada y lo convierte en una cadena. Esto es útil cuando necesitamos serializar los objetos en cadenas para enviarlos a nuestro servidor o almacenarlos en una base de datos.

Aquí hay un fragmento de código que envía una carga útil (payload en inglés) JSON a un servidor remoto:

async function sendPayload(data, headers) {
  const response = await fetch(url, {
    method: 'POST',
    mode: 'cors',
    headers: headers,
    body: JSON.stringify(data)
  })
  return response.json()
}

Cómo convertir JSON

El método JSON.parse() toma una cadena JSON como entrada y construye el valor/objeto JavaScript descrito por la cadena. Esto nos permite trabajar con el JSON como si fuese un objeto JavaScript normal.

Viendo que los objetos JSON tienen una estructura tipo árbol, puede ser útil para saber cómo recorrerlos recursivamente si es necesario.

const json = '{"title": "Avengers Endgame", "Rating":4.7, "inTheaters":false}';
const obj = JSON.parse(json)

console.log(obj.title)
// Avengers Endgame

XML

No podemos hablar sobre JSON sin mencionar a XML. Lenguaje de Marcado Extensible, o XML es un formato basado en texto para representar información estructurada, así como JSON - solo que se ve un poco distinto.

XML es un lenguaje de marcado como HTML, pero es mas generalizado en el hecho de que no usa etiquetas predefinidas. Así como las claves de objetos JSON puede ser llamados de cualquier forma, las etiquetas XML también pueden tener cualquier nombre.

<root>
  <id>1</id>
  <genre>Action</genre>
  <title>Iron Man</title>
  <director>Jon Favreau</director>
</root>

Los mismos datos en formato JSON:

{
  "id": "1",
  "genre": "Action",
  "title": "Iron Man",
  "director": "Jon Favreau"
}

¿Por qué usar XML?

XML y JSON ambos logran tareas similares, así que, ¿cuál deberías usar?

XML solía ser usado para las mismas cosas que JSON hoy en día es usado. Archivos de configuración, cuerpos HTTP, y otros casos de uso de transferencia de datos pueden funcionar sin problemas usando JSON o XML. Este es mi consejo: hablando de forma general, si JSON funciona, deberías preferirlo por sobre XML en estos días. JSON es mas liviano, mas fácil de leer, y tiene mejor soporte en la mayoría de lenguajes de programación modernos.

Hay algunos casos donde XML podría ser lo mejor, o tal vez inclusive la opción necesaria, pero esos casos serán raros.

Métodos HTTP

HTTP define un conjunto de métodos que usamos cada vez que hacemos una solicitud. Hemos usado algunos de estos métodos en ejercicios previos, pero es tiempo de profundizarlos para entender las diferencias y casos de uso que hay por detrás de los distintos métodos.

El método GET

El método GET se usa para "obtener" una representación de un recurso especificado. No estás quitando los datos del servidor, sino que obtienes una representación, o copia, del recurso en su estado actual.

Una solicitud get es considerado un método seguro para llamar mútiples veces porque no altera el estado del servidor.

Como hacer una Solicitud GET usando la API Fetch

El método fetch() acepta un parámetro objeto init opcional como su segundo argumento que podemos usar para definir cosas como:

  • method: El método HTTP de la solicitud, como GET
  • headers: Las cabeceras para enviar
  • mode: Usado para seguridad, hablaremos sobre esto en cursos futuros
  • body: El cuerpo de la solicitud. Frecuentemente codificado como JSON

Ejemplo de una solicitud GET usando fetch:

await fetch(url, {
  method: 'GET',
  mode: 'cors',
  headers: {
    'sec-ch-ua-platform': 'macOS'
  }
})

¿Por qué usamos métodos HTTP?

Como mencionamos antes, el propósito primario de los métodos HTTP es indicar al servidor lo que queremos hacer con el recurso que intentamos interactuar.

Al final del día, un método HTTP es solo una cadena, como GET, POST, PUT, o DELETE. Pero por convención, los desarrolladores back-end casi siempre escribe su código de servidor de manera que los métodos corresponden con diferentes acciones "CRUD".

Las acciones "CRUD" son:

  • Create (Crear)
  • Read (Leer)
  • Update (Actualizar)
  • Delete (Eliminar)

La mayor parte de la lógica en la mayoría de las aplicaciones web es la lógica "CRUD". La interfaz web permite a los usuarios crear, leer, actualizar y eliminar varios recursos.

Imagínate un sitio de red social - los usuarios básicamente crean, leen, actualizan y eliminar sus post sociales. También están creando, leyendo, actualizando y eliminando sus cuentos de usuario. ¡Es CRUD hasta el final!

Como sucede, los 4 métodos HTTP mas comunes se mapean muy bien a las acciones CRUD:

  • POST = crear
  • GET = leer
  • PUT = actualizar
  • DELETE = eliminar

Solicitudes POST

Una solicitud POST HTTP envía datos a un servidor, típicamente para crear un nuevo recurso. El body de la solicitud es el payload que está siendo enviado al servidor con la solicitud. Su tipo es indicado por la cabecera Content-Type.

Cómo agregar un body

El body de la solicitud es el payload que está siendo enviado al servidor con la solicitud. Su tipo es indicado por la cabecera Content-Type - para nosotros, eso va a ser JSON.

Las solicitudes POST no son generalmente seguros para llamar múltiples veces, porque altera el estado del servidor. No querrías crear accidentalmente 2 cuentas para el mismo usuario, por ejemplo.

await fetch(url, {
  method: 'POST',
  mode: 'cors',
  headers: {
    'Content-Type': 'application/json'
  },
  body: JSON.stringify(data)
})

Códigos de Estado HTTP

Ahora que entendemos cómo escribir solicitudes HTTP desde cero, necesitamos aprender cómo asegurar que el servidor está haciendo lo que queremos.

Anteriormente en el curso, aprendimos cómo acceder a las herramientas de desarrollo del navegador y usar esas herramientas para inspeccionar las solicitudes HTTP. Podemos usar el mismo proceso para verificar las solicitudes que estamos haciendo y verificar lo que están haciendo así podemos abarcar problemas potenciales.

Cuando se mira a las solicitudes, podemos ver el Código de Estado de la solicitud para obtener alguna información si la solicitud fue exitosa o no.

  • 100-199: Respuestas informativas. Estos son muy raros
  • 200-299: Respuestas exitosas. Con suerte, ¡la mayoría de las respuestas son 200's!
  • 300-399: Mensajes de redirección. Estos sin típicamente invisibles porque el navegador o el cliente HTTP automáticamente hará la redirección
  • 400-499: Errores de cliente. Verás a estos frecuentemente, especialmente cuando intentes depurar una aplicación cliente
  • 500-599: Errores de servidor. Verás a estos a veces, usualmente solo si hay un error en el servidor

Aquí hay algunos de los códigos de estado mas comunes, pero puedes ver una lista completa aquí si estás interesado.

  • 200 - OK. Este es de lejos el código mas común, significa que todo funcionó como se esperaba.
  • 201 - Creado. Esto significa que un recurso fue creado exitosamente. Típicamente en respuesta a una solicitud POST.
  • 301 - Movido permanentemente. Esto significa que el recurso fue movido a un nuevo lugar, y la respuesta incluirá donde se encuentra ese nuevo lugar. Los sitios web frecuentemente usan redirecciones 301 cuando cambian su nombre de domino, por ejemplo.
  • 400 - Mala solicitud. Un error general indicando al cliente que cometió un error en la solicitud.
  • 403 - No autorizado. Esto significa que el cliente no tiene los permisos correctos. Tal vez no incluyeron una cabecera de autorización requerida, por ejemplo.
  • 404 - No encontrado. Verás esto en sitios web con bastante frecuencia. Significa que el recurso no existe.
  • 500 - Error de servidor Interno. Esto significa que algo estuvo mal en el servidor, posiblemente un error en su final.

No necesitas memorizarlos

Necesitas saber lo básico, como "2XX está bien", "4XX es un error de cliente", y "5XX es un error de servidor". Con eso dicho, no necesitas memorizar todos los códigos, son fáciles de buscar.

FJl2z9O

¡Miremos algunos códigos de estado!

La propiedad .status en un objeto Response te dará el código. Aquí hay un ejemplo:

async function getStatusCode(url, headers) {
  const response = await fetch(url, {
    method: 'GET',
    mode: 'cors',
    headers: headers
  })
  return response.status
}

Método PUT

El método PUT HTTP crea un nuevo recurso o reemplaza una representación del recurso objetivo con los contenidos del body de la solicitud. En corto, actualiza la propiedad de una solicitud.

await fetch(url, {
   method: 'PUT',
   mode: 'cors',
   headers: {
   'Content-Type': 'application/json'
   },
   body: JSON.stringify(data)
})

POST vs PUT

Tal vez estás pensando que PUT es similar a POST o PATCH, y francamente, tendrías razón. La principal diferencia es que PUT está destinado a ser idempotente, significa que múltiples solicitudes PUT idénticos deberían tener el mismo efecto en el servidor.

En contraste, varias solicitudes POST idénticas tendrían efectos secundarios adicionales, tales como crear múltiples copias del recurso.

Patch vs PUT HTTP

Podrías encontrarte con los métodos PATCH de vez en cuando. Si bien no es tan común como los otros métodos, como PUT, es importante conocerlo y saber qué hace. El método PATCH pretende modificar parcialmente un recurso.

Larga historia corta, PATCH no es tan popular como PUT, y muchos servidores, inclusive si permiten actualizaciones parciales, aún usará el método PUT para eso.

HTTP Delete

El método DELETE hace exactamente lo que esperarías: es usado convencionalmente eliminar un recurso especificado.

// Esto elimina la ubicación con ID: 52fdfc07-2182-454f-963f-5f0f9a621d72
const url = 'https://example-api.com/locations/52fdfc07-2182-454f-963f-5f0f9a621d72'

await fetch(url, {
  method: 'DELETE',
  mode: 'cors'
})

Rutas URL y Parámetros

La Ruta URL viene justo después del dominio (o puerto si uno es provisto) en una cadena URL.

En esta URL, la rua es /root/next: http://testdomain.com/root/next.

Qué significaban las rutas en el internet primitivo

En los primeros días del internet, y a veces aún hoy en día, muchos servidores web simplemente servían archivos sin procesar desde el sistema de archivos del servidor.

Por ejemplo, si quería ser capaz de acceder algunos documentos de texto, podría comenzar un servidor web en mi directorio documentos. Si hacías una solicitud a mi servidor, serías capaz de acceder a distintos documentos usando la ruta que coincidía con mi estructura de archivos local.

Si tendría un archivo en mi /documentos/hello.txt local, podrías accederlo haciendo una solicitud GET a http://example.com/documentos/hello.txt.

Cómo son usados las rutas hoy en día

La mayoría de los servidores web modernos no usan ese simple mapeo de ruta URL -> ruta de archivo. Técnicamente, una ruta URL es solo una cadena con el que el servidor web puede hacer lo que quiera, y los sitios web modernos toman ventaja de esa flexibilidad.

Algunos ejemplos comunes de para qué se usan las rutas incluyen:

  • La jerarquía de las páginas en un sitio web, si refleja o no una estructura de archivos del servidor
  • Los parámetros se pasan en una solicitud HTTP, como un ID de un recurso
  • La versión de la API
  • El tipo de recurso siendo solicitado

APIs RESTful

Transferencia de Estado Representacional, o REST, es una convención popular que el servidor HTTP sigue. No todas las APIs HTTP son "APIs REST", o "RESTful", pero es muy común.

Los servidores RESTful siguen un conjunto de reglas flexibles que facilita construir APIs web predecibles y confiables. REST es más o menos un conjunto de convenciones sobre cómo HTTP debería ser usado.

Separado y agnóstico

La gran idea detrás de REST es que los recursos son transferidos por medio de interacciones de cliente/servidor reconocidas y agnósticas del lenguaje.

Un estilo RESTful significa que la implementación del cliente y del servidor puede ser hecho independientemente el uno del otro, siempre y cuando algunos estándares sencillos, como los nombres de los recursos disponibles, han sido establecidos.

Sin estado

Una arquitectura RESTful es sin estado. Esto significa que el servidor no necesita saber en qué estado está el cliente, ni el cliente necesita saber en qué estado está el servidor.

Statelessness en REST es re-asegurado al interactuar con recursos en vez de comandos. Ten en mente, esto no significa que las aplicaciones son sin estado - al contrario, ¿qué significaría "actualiza un recurso" si el servidor no mantenía registro de su estado?

Las Rutas en REST

En una API RESTful, la última sección del path de un URL debería especificar cuál recurso está siendo accedido. Luego, como hablamos en la sección "métodos", dependiendo en si la solicitud es un GET, POST, PUT o DELETE, el recurso es leído, creado, actualizado, o eliminado.

Por ejemplo, en el PokeAPI:

La primer parte de la ruta especifica que estamos interactuando con una API en vez de un sitio web. La siguiente parte especifica la versión, en este caso, versión 2, o v2.

Finalmente, la última parte denota qué recurso está siendo accedido, sea un location o pokemon.

Parámetros de Solicitud URL

Los parámetros de solicitud de URL aparecen después en la estructura URL pero no siempre están presentes - son opcionales. Por ejemplo:

https://www.google.com/search?q=boot.dev

q=boot.dev es un parámetro de solicitud. Como las cabeceras, los parámetros de solicitud son pares clave / valor. En este caso, q es la clave y boot.dev es el valor.

La Documentación de un Servidor HTTP

Te estarás preguntando:

¿Cómo se supone que memorice cómo funcionan todos estos servidores distintos???

Las buenas noticias es que no lo necesitas. Cuando trabajas con un servidor back-end, es la responsabilidad de los desarrolladores del servidor que te provean con instrucciones, o documentación que explica cómo interactuar con él.

Por ejemplo, la documentación debería decirte:

  • El dominio del servidor
  • Los recursos con los que interactuas (rutas HTTP)
  • Los parámetros de solicitud soportados
  • Los métodos HTTP soportados
  • Cualquier otra cosa que necesitarás saber para trabajar con el servidor
GIlWhYF


El servidor tiene control

Como mencionamos antes, el servidor tiene control total sobre cómo la ruta en un URL es interpretado y usado en una solicitud. Lo mismo es para los parámetros de solicitud.

No todos los servidores soportan parámetros de solicitud para cada tipo de solicitud, depende, así que necesitarás consultar la documentación.

Múltiples Parámetros de Solicitud

Mencionamos que los parámetros de solicitud son pares clave/valor - que significa que podemos tener múltiples pares.

http://example.com?firstName=lane&lastName=wagner

En el ejemplo de arriba:

  • firstName = lane
  • lastName = wagner

El ? separa los parámetros de solicitud del resto del URL. El & luego es usado para separar cada par de parámetros solicitud después de eso.

Por ejemplo, haz que esta solicitud que limite el número de Pokemons devuelto del PokeAPI a 2:

https://pokeapi.co/api/v2/location/?limit=2

¿Qué es HTTPs?

el protocolo de Transferencia de Hipertexto Seguro o HTTPS es una extensión del protocolo HTTP. HTTPS protege la transferencia de datos entre el cliente y el servidor encriptando toda la comunicación.

HTTPS permite a un cliente para que comparta información sensitiva sin peligro con el servidor a través de una solicitud HTTP, tales como información de tarjeta de crédito, contraseñas, o números de cuentas de banco.

HTTPS requiere que el cliente use SSL o TLS para proteger las solicitudes y el tráfico encriptando la información en la solicitud. HTTPS es solo HTTP con seguridad extra.

iOkQUdG
HTTP vs HTTPS

HTTPS mantiene tus mensajes privados, pero no tu identidad

No cubriremos cómo funciona la encriptación en este curso, pero lo haremos en próximos cursos. Por ahora, es importante notar que mientras HTTPS encripta lo que estás diciendo, no protege necesariamente quién eres. Herramientas como VPNs son necesarios para permanecer en línea de manera anónima.

HTTPS se asegura que estás hablando a la persona correcta (o servidor)

Además de encriptar la información dentro de una solicitud, HTTPS usa firmas digitales para probar que te estás comunicando con el servidor con el que piensas.

Si un hacker fuera a interceptar una solicitud HTTPS tocando un cable de red, no serían capaz de pretender exitosamente que son el servidor web de tu banco.

Asumiendo que un servidor soporta HTTPs, lo usas para cambiar simplemente el protocolo en tu su URL de solicitud: https://boot.dev

¿Quieres poner en práctica lo que has aprendido con un proyecto?

Mira esta guía de proyecto donde construirás un web crawler en JavaScript desde cero. Te hará usar la API Fetch y convirtiendo datos JSON, ¡como un pro! No necesitas construir el proyecto, pero es una excelente forma de practicar lo que has aprendido.

¡Felicidades en llegar hasta el final!

Si estás interesado en hacer las asignaciones de código interactivos y cuestionarios para este curso puedes revisar el curso de Aprender HTTP en Boot.dev.

Este curso es una parte de mi trayectoria profesional desarrollador full back-end, hecho de otros cursos y proyectos si te interesa verlos.

Si quieres ver otro contenido que creo relacionado al desarrollo web, mira algunos de mis enlaces abajo: