
# Express | Método POST - Peticiones en el `body`
## Introducción
Las aplicaciones web simples funcionan con una comunicación unidireccional desde el navegador al servidor. El navegador emite una solicitud y el servidor devuelve un recurso (HTML, CSS, js). Esto es lo que llamamos solicitudes "GET". Puede pensar en las solicitudes `GET` como una solicitud HTTP en la que desea *obtener* algo.
En esta lección, aprenderemos cómo enviar datos desde el navegador al servidor y cómo el servidor recibe esos parámetros y los usa para realizar operaciones.
### Introducción al método `POST`
Cuando navegamos, continuamente realizamos solicitudes desde el navegador al servidor. La mayoría de las solicitudes serán solicitudes GET (es decir, dame este HTML/CSS/imágenes) ... pero a veces necesitamos enviar datos al servidor:
- Para crear una cuenta de usuario
- Agregar un nuevo tweet
- Actualización del perfil de LinkedIn
Estas acciones tienen algo en común: **envían datos para crear o actualizar recursos en el servidor.**
HTML nos ofrece dos formas en las que podemos realizar solicitudes: `GET` y `POST`.
:::info
En realidad, HTTP define varios métodos de solicitud pero en el navegador, sin el uso de Javascript, solo podemos usar dos de ellos: `GET` y `POST`.
Cuando solicitamos un recurso (http://example.com/image.png), el navegador realiza una solicitud `GET` al servidor con esa URL. Podemos enviar información a través de la cadena de consulta al final de la URL (https://dummyimage.com/200x300?text=sent-via-query-string) pero la cantidad y complejidad de los datos que podemos enviar a través de este método es muy limitado.
Para enviar más información, o para evitar que la información se muestre en la barra de direcciones del navegador y se almacene en el historial del navegador, necesitamos usar formularios html para enviar los datos en el cuerpo de una solicitud `POST`.
:::
Cuando solicitamos un recurso (http://example.com/image.png), creará implícitamente una solicitud `GET` al servidor con esa URL. No obstante, aquí no enviamos ninguna información. Para enviar la información, normalmente necesitamos usar [formularios html](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form).
Veamos un ejemplo:
```htmlmixed=
<!-- Simple form which will send a GET request -->
<form action="example.com/user-data">
<label for="first-name-input">Nombre:</label>
<input id="first-name-input" type="text" name="firstName">
<input type="submit" value="Save Name">
</form>
```
Si escribimos "Juan" en el campo de entrada y enviamos este formulario, el navegador generará una nueva solicitud para:
```
http://example.com/user-data?firstName=Juan
```
Y luego el servidor podrá identificar la ruta `/user-data` y extraer todos los parámetros enviados después de `?`, Como `firstName=Juan` en el ejemplo anterior.
Este enfoque funciona y, a veces, es útil, pero existen dos problemas/limitaciones principales con el uso de `GET`:
1. No podemos enviar grandes parámetros con GET (como una foto, por ejemplo).
2. La información confidencial (contraseñas) se almacenará en el historial de su navegador y estará visible.
Debido a esto, `POST` se inventó como un método alternativo para enviar datos al servidor:
```htmlmixed=
<!-- Simple form which will send a POST request -->
<form action="example.com/user-data" method="post">
<label for="first-name-input">Nombre:</label>
<input id="first-name-input" type="text" name="firstName">
<input type="submit" value="Save Name">
</form>
```
Si escribimos "Juan" en el campo de entrada y enviamos este formulario, el navegador generará una nueva solicitud para:
```
http://example.com/user-data
```
Esta vez, `firstName=Juan` no estará en la URL, sino que el navegador agregará todos los parámetros del formulario como parte de la solicitud HTTP que enviamos al servidor.
En esta lección, vamos a practicar el envío de parámetros `GET` y `POST` desde HTML, cómo recibirlos en el servidor y enviar una respuesta.
Pero antes de entrar en eso, veamos algunas diferencias entre `GET` y `POST`:
| CATEGORÍA | GET | POST
|:--------:|-----|--------
| **Método HTTP** | Corresponde al verbo [HTTP GET](https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.3) | Corresponde al verbo [HTTP POST](https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.5)
| **Cuándo utilizar** | Obtener datos | Actualizar/crear datos
| **Método del formulario** | `<form method="get">` | `<form method="post">`
| **Datos del formulario** | Campos anexados a la URL de acción con un '?' | Campos incluidos en el cuerpo del formulario y enviados al servidor
| **Historial** | Los parámetros permanecen en el historial del navegador porque forman parte de la URL | Los parámetros no se guardan en el historial del navegador
| **Marcar como favorito** | Se puede marcar como favorito | No se puede marcar como favorito
| **Privacidad** | El método `GET` no debe utilizarse al enviar contraseñas u otra información confidencial | El método `POST` se utiliza al enviar contraseñas u otra información confidencial
| **Visibilidad** | El método GET es visible para todos (se mostrará en la barra de direcciones del navegador) y tiene límites en la cantidad de información para enviar | Las variables del método POST no se muestran en la URL
## Parámetros (Params)
### Parámetros de consulta | Formulario con el método `GET`
Como se discutió anteriormente, cuando creamos un formulario, por defecto hace un `GET`, y agrega los parámetros a nuestra URL, así
```htmlmixed=
<!-- Simple form which will send a GET request -->
<form action="example.com/user-data">
<label for="first-name-input">Nombre:</label>
<input id="first-name-input" type="text" name="firstName">
<input type="submit" value="Save Name">
</form>
```
```
http://example.com/user-data?firstName=Juan
```
Nuestra tarea es recopilar la información de nuestro usuario y mostrarla en otra página. Por ahora, obtendremos su nombre, edad y superhéroe favorito.
#### Paso 1 | Mostrar un formulario
Primero, necesitamos una ruta para mostrar una nueva vista. A esta ruta lo llamaremos "get-user-info":
```javascript
/* app.js */
app.get('/get-user-info', (req, res) => {
res.render('user-info-form');
});
```
Luego, debemos crear una vista llamada `user-info-form`:
`$ touch views/user-info-form.hbs`
Y mostrar el formulario, con todos sus campos:
```htmlmixed
<!-- user-info-form.hbs -->
<form action="/display-user-info">
<label for="name-input">Name</label>
<input id="name-input" type="text" name="name">
<label for="age-input">Age</label>
<input id="age-input" type="number" name="age">
<label for="superhero-input">Favorite Superhero</label>
<input id="superhero-input" type="text" name="superhero">
<button type="submit">Submit Info!</button>
</form>
```
:::info
:bulb: Se pueden utilizar `<button type="submit">` o `<input type="submit">` como botones de envío.
:::
##### input `type`
El atributo `type` del input le permite al formulario saber cuál será la entrada. **Todos los valores se enviarán como una cadena**, pero el `type` puede cambiar el aspecto de algunas entradas.
Todos los tipos de entrada se pueden encontrar [aquí](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input) en MDN.
##### input `id`
El atributo `id` está en la etiqueta. La etiqueta `for` se adjunta al `id` del `input`.
:::info
:zap: Esto hace que si hace clic en el `label`, el `inpiut` hará `focus`.
:::
##### input `name`
El `name` es el atributo más importante en el `input`. Así es como enviamos información desde el formulario al servidor.
#### Paso 2 | Usar el parámetro de consulta
El formulario está haciendo una solicitud `GET` a una ruta llamada` display-user-info`, por lo que tenemos que crear una ruta para manejar esa información y hacer algo con ella.
```javascript
app.get('/display-user-info', (req, res) => {
});
```
Entonces, podemos acceder a la información a través de `req.query`:
```javascript
app.get('/display-user-info', (req, res) => {
let name = req.query.name;
let age = req.query.age;
let superhero = req.query.superhero;
res.send(`
Your name is ${name}
Your age is ${age}
Your favorite superhero is ${superhero}
`)
});
```
¿Qué sucedió? Nuestro formulario tomó todos nuestros campos de entrada y los agregó como `query parameters`.

Eso significa que luego podemos acceder a esos datos en la ruta que recibe la solicitud en el servidor.
Pero, ¿qué sucede cuando tenemos información confidencial que no queremos que se muestre en la barra de URL o que el usuario pueda manipularla fácilmente?
### Parámetros de formulario | Método `POST`
Creemos nuestra primera solicitud `POST`. A menudo, con una solicitud `POST`, nuestro flujo se verá así:
```flow
st=>start: Mostrar el formulario al usuario
op=>operation: El usuario ingresa los datos en el formulario
op2=>operation: El usuario envía los datos
op3=>operation: El formulario hace una petición POST
op4=>operation: El servidor intenta hacer login
op4=>operation: El usuario es redirigido (a la home page, newsfeed, etc)
e=>end: Termina
st->op->op2->op3->op4->end
```
#### Paso 1 | Mostrar un formulario
Creemos una nueva ruta, esto mostrará un formulario al usuario:
```javascript
app.get('/login', (req, res) => {
res.render('login')
});
```
Como habrás notado, estamos renderizando "login". Debemos crear `login.hbs`:
```
$ touch views/login.hbs
```
Y dentro del `login.hbs`, creamos nuestro primer formulario:
```htmlmixed
<form action="/login" method="POST">
</form>
```
##### Método
El *método* es lo que le dice a nuestro formulario que haga una solicitud `POST`. Cuando creamos un formulario de inicio de sesión o enviamos alguna información, siempre debemos usar un "POST". Esto evita que el usuario vuelva a enviar información y es la semántica adecuada.
#### Form cont.
```htmlmixed
<form action="/login" method="POST">
<label for="email">Email</label>
<input id="email" type="text" name="email">
<label for="password">Password</label>
<input id="password" type="password" name="password">
<button type="submit">
Login
</button>
</form>
```
Hacemos click en `submit`! ¿Qué pasa?
#### Paso 2 | La ruta `POST`
En el ejemplo anterior, obtenemos un **404** porque no tenemos una ruta con un método de `POST` y una acción de`/login`. ¡Vamos a crearlo!
```javascript
app.post('/login', (req, res) => {
res.send('You\'ve logged in!');
});
```
Espera un segundo ... ¡nunca iniciamos sesión! ¿Cómo accedemos a la información que el usuario ingresó en el formulario en el servidor?
##### Las peticiones en el `Body` / `Parámetros`
`req` contiene información sobre la solicitud, incluido el correo electrónico y la contraseña que el usuario ingresó en el formulario.
Desafortunadamente, estos datos no se pueden leer de forma predeterminada en Express con una solicitud `POST`.
*Necesitamos el, [`bodyParser`](https://github.com/expressjs/body-parser)*!
Primero, instalamos `bodyParser`:
```
$ npm install --save body-parser
```
Después, agregamos a nuestro archivo:
```javascript
// ...
const bodyParser = require('body-parser');
// ...
app.use(bodyParser.urlencoded({ extended: true }));
```
`bodyparser` hace precisamente eso. Analiza el `body` de nuestra solicitud y nos lo da en el `req.body`:
```javascript
app.post('/login', (req, res) => {
res.send(req.body);
});
```
Ahora tenemos un objeto JavaScript simple con el que interactuar!
```javascript
app.post('/login', (req, res) => {
let email = req.body.email;
let password = req.body.password;
res.send(`Email: ${email}, Password: ${password}`);
});
```
¿Que pasó aquí? Nuestro formulario envía sus datos en el cuerpo de la solicitud al servidor. `bodyParser` lo captura y lo convierte en un objeto JavaScript:

**Ejercicio**
Agregamos un poco de lógica a nuestra ruta `post`.
Si el email es `ucom@gmail.com` y la contraseña es`password`, mostramos un mensaje que dice "Bienvenido"; de lo contrario, mostramos un mensaje que diga "Adiós".
**Código inicial**
```javascript
app.post('/login', (req, res) => {
// What ES6 feature could we use to clean these two lines up?
let email = req.body.email;
let password = req.body.password;
if (/* fill in this condition*/){
// render "Welcome"
} else {
// render go away
}
});
```
## Middleware
Cuando se realiza una solicitud a nuestro servidor Express, en realidad no va directamente a la ruta. Muchas veces, nuestra ruta es en realidad la última parada.
Hemos utilizado un par de paquetes hasta ahora, incluido `bodyParser`. Estos paquetes se denominan *Middlewares*.
> El término middleware se utiliza para describir productos separados que sirven como pegamento entre dos aplicaciones.
>
> El middleware a veces se denomina `cañería` porque conecta dos lados de una aplicación y pasa datos entre ellos.
En este caso, los dos lados de la aplicación consisten en (1) el cliente que realiza una solicitud y (2) el servidor que maneja esa solicitud.
El siguiente diagrama ilustra cómo nuestra aplicación maneja realmente una solicitud.

1. La petición pasa por `cookieParser`
2. La petición pasa por `bodyParser`
3. La petición pasa por `logger`
4. La petición pasa por `authentication`
5. Finalmente, nuestra solicitud llega a nuestra ruta y devuelve la llamada.
¿Como funciona esto? Creemos un ejemplo simple para ilustrar esto.
Primero, creemos una ruta de prueba:
```javascript
app.get('/test', (req, res) => {
res.send("We made it to test!");
});
```
Entonces, creemos nuestro propio middleware :
```javascript
// ...
app.use(myFakeMiddleware)
// ...
function myFakeMiddleware(){
console.log("myFakeMiddleware was called!");
}
```
Hacemos una petición a `localhost:3000/test`:

¡Pero el navegador no carga nada! ¿Por qué?
### El patron de los `Middleware`
`app.use()` es una función que agrega un middleware a nuestra pila de middlewares. Todos los middlewares se llaman, uno tras otro, y finalmente terminan con la ruta.
El problema es que no estamos llamando a nuestro próximo middleware. La cadena está rota y hay una obstrucción en la tubería.
Las funciones que funcionan como middlewares reciben 2-4 argumentos y uno de ellos es siempre el *next()* middleware que debemos llamar.
Agreguemos eso a nuestra función:
```javascript
function myFakeMiddleware(_, _, next){
console.log("myFakeMiddleware was called!");
next();
}
```
Pasamos `next` como nuestro tercer argumento, luego, cuando nuestro middleware termina de registrar, lo llamamos.
Visitamos `localhost:3000/test`.
#### Pasando información
A menos que simplemente estemos registrando la solicitud, muchas veces necesitaremos pasar información a través de nuestro middleware.
Express sugiere adjuntar cualquiera de sus datos al objeto `request`. Esto estará disponible en todos los middleware y en la ruta. Echemos un vistazo a este ejemplo de `middleware` falso:
```javascript
function myFakeMiddleware(req, _, next){
console.log("myFakeMiddleware was called!");
req.secretValue = "swordfish";
next();
}
```
Después de llamar a nuestro middleware `myFakeMiddleware`, podemos acceder fácilmente al objeto *req*. En este ejemplo, podemos acceder a `secretValue`:
```javascript
app.get('/test', (req, res) => {
let mySecret = req.secretValue;
res.send(mySecret);
});
```
Muchas veces no diseñaremos un middleware propio, Express ya tiene un [enorme ecosistema de middlewares](https://expressjs.com/en/resources/middleware.html), pero es muy útil comprender cómo se procesa la solicitud.
Existen algunos paquetes de Node extremadamente útiles (algunos de los cuales son middlewares) que lo ayudarán a desarrollar aplicaciones.
## Apuntes finales
Observe que el `GET` y` POST` tienen el mismo nombre de ruta, `/login`. Esto está bien porque el **método** los convierte en *dos rutas completamente diferentes*.
Cuando hacemos la solicitud `GET`, se mostrará un formulario.
Cuando el formulario realiza una solicitud `POST`, se enviará para realizar la lógica de inicio de sesión.
## Recursos extra
- [body-parser Docs](https://github.com/expressjs/body-parser)
- [Anatomy of an HTTP request in Node](https://nodejs.org/en/docs/guides/anatomy-of-an-http-transaction/)