En aquest cas d'estudi, dissenyarem i desenvoluparem una API RESTful per a una botiga en línia. Aquest projecte ens permetrà aplicar els conceptes apresos en els mòduls anteriors i veure com es poden implementar en un escenari real.

Objectius del cas d'estudi

  1. Dissenyar l'arquitectura de l'API: Definir els recursos, les URIs, els mètodes HTTP i els codis d'estat.
  2. Desenvolupar l'API: Implementar l'API utilitzant un framework popular.
  3. Provar l'API: Assegurar-nos que l'API funciona correctament i compleix amb els requisits.
  4. Documentar l'API: Crear una documentació clara i completa per a l'API.

  1. Disseny de l'arquitectura de l'API

Recursos i URIs

Els recursos principals de la nostra botiga en línia seran:

  • Productes: Informació sobre els productes disponibles.
  • Categories: Classificació dels productes.
  • Usuaris: Informació sobre els clients.
  • Comandes: Informació sobre les comandes realitzades pels clients.
Recurs URI Base
Productes /products
Categories /categories
Usuaris /users
Comandes /orders

Mètodes HTTP

Utilitzarem els següents mètodes HTTP per interactuar amb els recursos:

Operació Mètode HTTP URI Descripció
Obtenir productes GET /products Obtenir una llista de productes
Crear producte POST /products Afegir un nou producte
Obtenir producte GET /products/{id} Obtenir un producte específic
Actualitzar producte PUT /products/{id} Actualitzar un producte
Eliminar producte DELETE /products/{id} Eliminar un producte
Obtenir categories GET /categories Obtenir una llista de categories
Crear categoria POST /categories Afegir una nova categoria
Obtenir categoria GET /categories/{id} Obtenir una categoria específica
Actualitzar categoria PUT /categories/{id} Actualitzar una categoria
Eliminar categoria DELETE /categories/{id} Eliminar una categoria
Obtenir usuaris GET /users Obtenir una llista d'usuaris
Crear usuari POST /users Afegir un nou usuari
Obtenir usuari GET /users/{id} Obtenir un usuari específic
Actualitzar usuari PUT /users/{id} Actualitzar un usuari
Eliminar usuari DELETE /users/{id} Eliminar un usuari
Obtenir comandes GET /orders Obtenir una llista de comandes
Crear comanda POST /orders Afegir una nova comanda
Obtenir comanda GET /orders/{id} Obtenir una comanda específica
Actualitzar comanda PUT /orders/{id} Actualitzar una comanda
Eliminar comanda DELETE /orders/{id} Eliminar una comanda

Codis d'estat HTTP

Utilitzarem els següents codis d'estat HTTP per indicar el resultat de les operacions:

Codi d'estat Descripció
200 OK Operació realitzada correctament
201 Created Recurs creat correctament
400 Bad Request Sol·licitud incorrecta
401 Unauthorized No autoritzat
404 Not Found Recurs no trobat
500 Internal Server Error Error del servidor

  1. Desenvolupament de l'API

Configuració de l'entorn de desenvolupament

Per aquest cas d'estudi, utilitzarem Node.js amb Express, un framework popular per al desenvolupament d'APIs RESTful.

Instal·lació de Node.js i Express

# Instal·lació de Node.js (si no està instal·lat)
$ sudo apt-get install nodejs
$ sudo apt-get install npm

# Creació d'un nou projecte
$ mkdir online-store-api
$ cd online-store-api
$ npm init -y

# Instal·lació d'Express
$ npm install express

Creació d'un servidor bàsic

// server.js
const express = require('express');
const app = express();
const port = 3000;

app.use(express.json());

app.get('/', (req, res) => {
  res.send('Benvingut a la botiga en línia!');
});

app.listen(port, () => {
  console.log(`Servidor escoltant a http://localhost:${port}`);
});

Gestió de peticions i respostes

Afegirem rutes per gestionar les peticions als recursos definits anteriorment.

// routes/products.js
const express = require('express');
const router = express.Router();

let products = [];

// Obtenir tots els productes
router.get('/', (req, res) => {
  res.status(200).json(products);
});

// Crear un nou producte
router.post('/', (req, res) => {
  const product = req.body;
  products.push(product);
  res.status(201).json(product);
});

// Obtenir un producte específic
router.get('/:id', (req, res) => {
  const product = products.find(p => p.id === parseInt(req.params.id));
  if (!product) return res.status(404).send('Producte no trobat');
  res.status(200).json(product);
});

// Actualitzar un producte
router.put('/:id', (req, res) => {
  const product = products.find(p => p.id === parseInt(req.params.id));
  if (!product) return res.status(404).send('Producte no trobat');

  product.name = req.body.name;
  product.price = req.body.price;
  res.status(200).json(product);
});

// Eliminar un producte
router.delete('/:id', (req, res) => {
  const productIndex = products.findIndex(p => p.id === parseInt(req.params.id));
  if (productIndex === -1) return res.status(404).send('Producte no trobat');

  products.splice(productIndex, 1);
  res.status(200).send('Producte eliminat');
});

module.exports = router;

Integració de les rutes al servidor principal

// server.js
const express = require('express');
const app = express();
const port = 3000;

app.use(express.json());

const productsRouter = require('./routes/products');
app.use('/products', productsRouter);

app.get('/', (req, res) => {
  res.send('Benvingut a la botiga en línia!');
});

app.listen(port, () => {
  console.log(`Servidor escoltant a http://localhost:${port}`);
});

  1. Proves i validació

Utilitzarem Postman per provar les diferents rutes de la nostra API. Crearem col·leccions de peticions per a cada recurs i verificarem que les respostes siguin correctes.

Exemple de peticions amb Postman

  1. GET /products: Obtenir tots els productes.
  2. POST /products: Crear un nou producte.
  3. GET /products/{id}: Obtenir un producte específic.
  4. PUT /products/{id}: Actualitzar un producte.
  5. DELETE /products/{id}: Eliminar un producte.

  1. Documentació de l'API

Utilitzarem Swagger per documentar la nostra API. Swagger ens permet crear una documentació interactiva que facilita la comprensió i l'ús de l'API.

Instal·lació de Swagger

$ npm install swagger-ui-express swagger-jsdoc

Configuració de Swagger

// server.js
const express = require('express');
const app = express();
const port = 3000;

app.use(express.json());

const productsRouter = require('./routes/products');
app.use('/products', productsRouter);

const swaggerUi = require('swagger-ui-express');
const swaggerJsdoc = require('swagger-jsdoc');

const swaggerOptions = {
  swaggerDefinition: {
    info: {
      title: 'Botiga en línia API',
      version: '1.0.0',
      description: 'API per gestionar una botiga en línia',
    },
  },
  apis: ['./routes/*.js'],
};

const swaggerDocs = swaggerJsdoc(swaggerOptions);
app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerDocs));

app.get('/', (req, res) => {
  res.send('Benvingut a la botiga en línia!');
});

app.listen(port, () => {
  console.log(`Servidor escoltant a http://localhost:${port}`);
});

Documentació de les rutes amb Swagger

// routes/products.js
const express = require('express');
const router = express.Router();

let products = [];

/**
 * @swagger
 * /products:
 *   get:
 *     summary: Obtenir tots els productes
 *     responses:
 *       200:
 *         description: Llista de productes
 */
router.get('/', (req, res) => {
  res.status(200).json(products);
});

/**
 * @swagger
 * /products:
 *   post:
 *     summary: Crear un nou producte
 *     parameters:
 *       - in: body
 *         name: product
 *         description: El producte a crear
 *         schema:
 *           type: object
 *           required:
 *             - name
 *             - price
 *           properties:
 *             name:
 *               type: string
 *             price:
 *               type: number
 *     responses:
 *       201:
 *         description: Producte creat correctament
 */
router.post('/', (req, res) => {
  const product = req.body;
  products.push(product);
  res.status(201).json(product);
});

/**
 * @swagger
 * /products/{id}:
 *   get:
 *     summary: Obtenir un producte específic
 *     parameters:
 *       - in: path
 *         name: id
 *         required: true
 *         description: ID del producte
 *         schema:
 *           type: integer
 *     responses:
 *       200:
 *         description: Producte trobat
 *       404:
 *         description: Producte no trobat
 */
router.get('/:id', (req, res) => {
  const product = products.find(p => p.id === parseInt(req.params.id));
  if (!product) return res.status(404).send('Producte no trobat');
  res.status(200).json(product);
});

/**
 * @swagger
 * /products/{id}:
 *   put:
 *     summary: Actualitzar un producte
 *     parameters:
 *       - in: path
 *         name: id
 *         required: true
 *         description: ID del producte
 *         schema:
 *           type: integer
 *       - in: body
 *         name: product
 *         description: El producte a actualitzar
 *         schema:
 *           type: object
 *           properties:
 *             name:
 *               type: string
 *             price:
 *               type: number
 *     responses:
 *       200:
 *         description: Producte actualitzat correctament
 *       404:
 *         description: Producte no trobat
 */
router.put('/:id', (req, res) => {
  const product = products.find(p => p.id === parseInt(req.params.id));
  if (!product) return res.status(404).send('Producte no trobat');

  product.name = req.body.name;
  product.price = req.body.price;
  res.status(200).json(product);
});

/**
 * @swagger
 * /products/{id}:
 *   delete:
 *     summary: Eliminar un producte
 *     parameters:
 *       - in: path
 *         name: id
 *         required: true
 *         description: ID del producte
 *         schema:
 *           type: integer
 *     responses:
 *       200:
 *         description: Producte eliminat correctament
 *       404:
 *         description: Producte no trobat
 */
router.delete('/:id', (req, res) => {
  const productIndex = products.findIndex(p => p.id === parseInt(req.params.id));
  if (productIndex === -1) return res.status(404).send('Producte no trobat');

  products.splice(productIndex, 1);
  res.status(200).send('Producte eliminat');
});

module.exports = router;

Conclusió

En aquest cas d'estudi, hem dissenyat i desenvolupat una API RESTful per a una botiga en línia, aplicant els principis i pràctiques apreses en els mòduls anteriors. Hem creat una arquitectura clara, implementat les rutes necessàries, provat l'API amb Postman i documentat l'API amb Swagger. Aquest projecte ens ha permès veure com es poden aplicar els conceptes teòrics en un escenari pràctic i real.

© Copyright 2024. Tots els drets reservats