Hablemos de CORS & frontend con vite
Tags: vite, cors, node, php
Published: 2023-07-23 19:20:15

---
title: Hablemos de CORS & frontend con vite
published: true
description: 
tags: vite, cors, node, php
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/17mr8wdib6t7go3zbf0d.png
# published_at: 2023-07-23 10:58 +0000
---

A menudo me encuentro desarrollando sitios con react o preact. Ultimamente preact es mi favorito, mucho mas rapido y liviano. A veces no es necesario usar un servidor real, estoy dando clases, haciendo una demo o simplemente estoy trabajando sin internet y necesito simular requests a un servidor aunque sea local.

Entonces como quiero probar mi frontend hice un simple archivo php que va a leer lo que le mande por POST y por ahora va a devolver json similar al que me va a dar el servidor real.

_(Al final del artículo hay una version node del servidor php)_

```bash
php -S 127.0.0.1 -t server.php
```

```php
<?php

$json = file_get_contents('php://input');
$data = json_decode($json, true);

if (!isset($data['username']) || !isset($data['password'])) {
    http_response_code(400);
    echo json_encode([
        'status' => 'error',
        'message' => 'Username or password not provided'
    ]);
    exit;
}

if ($data['username'] === 'nicolas' && $data['password'] === 'Correct-h0rse-Battery-staple') {
    echo json_encode([
        'status' => 'success',
        'token' => 'fake_token'
    ]);
} else {
    http_response_code(401);
    echo json_encode([
        'status' => 'error',
        'message' => 'Invalid username or password'
    ]);
}

```

Uso php porque no tiene dependencias, para una demo alcanza y sobra. Pero este código no funciona. El error que veo en la consola dice:

```
Response body is not available to scripts (Reason: CORS Failed)
```

A estas alturas, sobre todo despues de haber leido el titulo, ya sabemos por donde viene el error. Pero qué es CORS?

CORS son las siglas de Cross-Origin Resource Sharing. Es un mecanismo de seguridad que permite especificar quien puede acceder a los recursos del servidor.

Entonces lo unico que tengo que agregar a mi codigo php es un par de headers http, verdad?

```php
<?php

header('Content-Type: application/json');
header('Access-Control-Allow-Origin: http://localhost:5173');
header('Access-Control-Allow-Methods: POST');
header('Access-Control-Allow-Headers: Content-Type');
```

Mi código sigue sin funcionar! Mi request no llega al servidor, pero por que?

Aparentemetne axios está haciendo un request antes del request POST que tiene el JSON con mis credenciales. A este request se lo conoce como una "preflight request" o solicitud previa. Es un request que tiene el verbo OPTIONS y lo unico que hace es preguntar al servidor que tipos de request se puede hacer. Vamos a modificar nuestros headers y a agregaremos un pequeño if para este nuevo verbo:

```php
// headers
header('Access-Control-Allow-Methods: POST, OPTIONS');

if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
    http_response_code(200);
    exit;
}
// fake login
```

Ahora si! Ahora funciona! Generalmente los navegadores intentan asegurar la politica "Same origin" que impide que un código JavaScript en un origen (dominio, protocolo o puerto) pueda acceder a recursos en otro origen diferente.

Nuestro código `php` finalmente quedaría así:

```php
<?php

header('Content-Type: application/json');
header('Access-Control-Allow-Origin: http://localhost:5173'); // CORS
header('Access-Control-Allow-Methods: POST, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type');

if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
    http_response_code(200);
    exit;
}

$json = file_get_contents('php://input');
$data = json_decode($json, true);

if (!isset($data['username']) || !isset($data['password'])) {
    http_response_code(400);
    echo json_encode([
        'status' => 'error',
        'message' => 'Username or password not provided'
    ]);
    exit;
}

if ($data['username'] === 'nicolas' && $data['password'] === 'Correct-h0rse-Battery-staple') {
    echo json_encode([
        'status' => 'success',
        'token' => 'fake_token'
    ]);
} else {
    http_response_code(401);
    echo json_encode([
        'status' => 'error',
        'message' => 'Invalid username or password'
    ]);
}

```

Es posible que no tengas el interprete de php en tu sistema, acá podés encontrar prácticamente el mismo código en nodejs con express:

```bash
pnpm init && pnpm add express body-parser cors
```

```javascript
const express = require("express");
const bodyParser = require("body-parser");
const cors = require("cors");

const app = express();
const port = process.env.PORT || 3000;

app.use(bodyParser.json());
app.use(cors());

app.post("/login", (req, res) => {
  const { username, password } = req.body;

  if (!username || !password) {
    res
      .status(400)
      .json({ status: "error", message: "Username or password not provided" });
    return;
  }

  if (username === "nicolas" && password === "Correct-h0rse-Battery-staple") {
    res.json({ status: "success", token: "fake_token" });
  } else {
    res
      .status(401)
      .json({ status: "error", message: "Invalid username or password" });
  }
});

app.listen(port, () => {
  console.log(`Servidor Node.js ejecutándose en http://localhost:${port}`);
});
```

Créditos del cover:

- [Prompt generated with ChatGPT](https://chat.openai.com/)
- [Text to image with Scribble Diffusion](https://scribblediffusion.com/)
- [Content-Aware Scale-like with DALL.e](https://labs.openai.com/)
- [Resize and adjustments with Photopea](https://www.photopea.com/)