Versionado
Parte de la sección API REST del Journey de Node.js de Coddy. Lección 15 de 18.
Cambiar la forma de una respuesta rompe todos los clientes que ya la usan. Una versión en la ruta permite que los clientes antiguos y nuevos convivan: /api/v1/orders hoy, /api/v2/orders cuando cambie la forma. Las rutas que se mueven responden con una redirección:
GET /api/orders/5 → 308 Location: /api/v1/orders/5
POST /api/orders → 308 Location: /api/v1/ordersLos códigos 301 y 302 permiten que los clientes repitan una solicitud POST como GET, lo que descarta el cuerpo. 308 indica «repite allí la misma solicitud», incluidos el método y el cuerpo. Dentro de un middleware montado, req.url ha perdido la ruta de montaje, mientras que req.originalUrl la conserva completa:
// en app.use('/api/orders', ...) para GET /api/orders/5?full=1
req.url // '/5?full=1'
req.originalUrl // '/api/orders/5?full=1'Desafío
Fácil- Monta el enrutador de tareas en
/api/v1/tasks. - Cada ruta antigua
/api/tasksresponde con 308 hacia la misma ruta bajo/api/v1, incluida la consulta. - Las tareas nuevas reciben
Location: /api/v1/tasks/<id>.
Envía GET /api/tasks/2, POST /api/tasks con { "title": "Order new chairs" }, después GET /api/v1/tasks/2.
Pruébalo tú mismo
import express from 'express';
import { sendError } from './errors.js';
import taskRoutes from './routes/tasks.js';
const BOARD_ORIGIN = 'https://board.example.com';
const app = express();
app.use(express.json());
// Permite que las páginas de BOARD_ORIGIN llamen a esta API desde el navegador.
app.use((req, res, next) => {
res.set('Access-Control-Allow-Origin', BOARD_ORIGIN);
res.set('Access-Control-Allow-Credentials', 'true');
if (req.method === 'OPTIONS') {
res.set('Access-Control-Allow-Methods', 'GET, POST, PUT, PATCH, DELETE');
res.set('Access-Control-Allow-Headers', 'Content-Type');
return res.status(204).end();
}
next();
});
app.use(express.static('public'));
app.use('/api/tasks', taskRoutes);
// Los errores de las rutas llegan aquí. Un cuerpo que no es JSON válido es un error del
// cliente (400); cualquier otro error es nuestro (500).
app.use((err, req, res, next) => {
if (err.type === 'entity.parse.failed') {
return sendError(res, 400, 'invalid_json', 'The body is not valid JSON');
}
console.error(err);
sendError(res, 500, 'server_error', 'Something went wrong');
});
app.listen(3000, () => {
console.log('Task tracker API on port 3000');
});