Buscar..


Introducción

Express es un marco de aplicación web Node.js mínimo y flexible, que proporciona un conjunto robusto de características para crear aplicaciones web.

El sitio web oficial de Express es expressjs.com . La fuente se puede encontrar en GitHub .

Sintaxis

  • app.get (ruta [, middleware], devolución de llamada [, devolución de llamada ...])
  • app.put (ruta [, middleware], devolución de llamada [, devolución de llamada ...])
  • app.post (ruta [, middleware], devolución de llamada [, devolución de llamada ...])
  • aplicación ['eliminar'] (ruta [, middleware], devolución de llamada [, devolución de llamada ...])
  • app.use (ruta [, middleware], devolución de llamada [, devolución de llamada ...])
  • app.use (devolución de llamada)

Parámetros

Parámetro Detalles
path Especifica la parte de la ruta o la URL que manejará la devolución de llamada dada.
middleware Una o más funciones que serán llamadas antes de la devolución de llamada. Esencialmente un encadenamiento de múltiples funciones de callback de callback . Útil para un manejo más específico, por ejemplo, autorización o manejo de errores.
callback Una función que se utilizará para manejar solicitudes a la path especificada. Se llamará como callback(request, response, next) , donde request , response y next se describen a continuación.
request devolución de llamada Un objeto que encapsula detalles sobre la solicitud HTTP a la que se llama la devolución de llamada para que la maneje.
response Un objeto que se utiliza para especificar cómo debe responder el servidor a la solicitud.
next Una devolución de llamada que pasa el control a la siguiente ruta coincidente. Acepta un objeto de error opcional.

Empezando

Primero deberá crear un directorio, acceder a él en su shell e instalar Express usando npm ejecutando npm install express --save

Cree un archivo y app.js nombre app.js y agregue el siguiente código que crea un nuevo servidor Express y le agrega un punto final ( /ping ) con el método app.get :

const express = require('express');

const app = express();

app.get('/ping', (request, response) => {
    response.send('pong');
});

app.listen(8080, 'localhost');

Para ejecutar su script use el siguiente comando en su shell:

> node app.js

Su aplicación aceptará conexiones en el puerto localhost 8080. Si se omite el argumento del nombre de host para app.listen , el servidor aceptará las conexiones en la dirección IP de la máquina, así como en el host local. Si el valor del puerto es 0, el sistema operativo asignará un puerto disponible.

Una vez que se ejecuta el script, puede probarlo en un shell para confirmar que obtiene la respuesta esperada, "pong", desde el servidor:

> curl http://localhost:8080/ping
pong

También puede abrir un navegador web, navegar a la url http: // localhost: 8080 / ping para ver el resultado

Enrutamiento básico

Primero crea una aplicación expresa:

const express = require('express');
const app = express();

Entonces puedes definir rutas como esta:

app.get('/someUri', function (req, res, next) {})

Esa estructura funciona para todos los métodos HTTP y espera una ruta como primer argumento y un controlador para esa ruta, que recibe los objetos de solicitud y respuesta. Entonces, para los métodos HTTP básicos, estas son las rutas

// GET www.domain.com/myPath
app.get('/myPath', function (req, res, next) {})

// POST www.domain.com/myPath
app.post('/myPath', function (req, res, next) {})

// PUT www.domain.com/myPath
app.put('/myPath', function (req, res, next) {})

// DELETE www.domain.com/myPath
app.delete('/myPath', function (req, res, next) {})

Puede consultar la lista completa de verbos compatibles aquí . Si desea definir el mismo comportamiento para una ruta y todos los métodos HTTP, puede usar:

app.all('/myPath', function (req, res, next) {}) 

o

app.use('/myPath', function (req, res, next) {})

o

app.use('*', function (req, res, next) {})

// * wildcard will route for all paths

Puedes encadenar tus definiciones de ruta para un solo camino

app.route('/myPath')
  .get(function (req, res, next) {})
  .post(function (req, res, next) {})
  .put(function (req, res, next) {})

También puede agregar funciones a cualquier método HTTP. Se ejecutarán antes de la devolución de llamada final y tomarán los parámetros (req, res, next) como argumentos.

// GET www.domain.com/myPath
app.get('/myPath', myFunction, function (req, res, next) {})

Sus devoluciones de llamada finales se pueden almacenar en un archivo externo para evitar poner demasiado código en un archivo:

// other.js
exports.doSomething = function(req, res, next) {/* do some stuff */};

Y luego en el archivo que contiene tus rutas:

const other = require('./other.js');
app.get('/someUri', myFunction, other.doSomething);

Esto hará que su código sea mucho más limpio.

Obteniendo información de la solicitud

Para obtener información de la url de solicitud (observe que req es el objeto de solicitud en la función de controlador de rutas). Considere la definición de esta ruta /settings/:user_id y este ejemplo particular /settings/32135?field=name

// get the full path
req.originalUrl // => /settings/32135?field=name

// get the user_id param
req.params.user_id // => 32135     

// get the query value of the field
req.query.field // => 'name'

También puede obtener los encabezados de la solicitud, como este

req.get('Content-Type')
// "text/plain"

Para simplificar la obtención de otra información puede usar middlewares. Por ejemplo, para obtener la información del cuerpo de la solicitud, puede usar el middleware del analizador del cuerpo , que transformará el cuerpo de la solicitud sin formato en un formato utilizable.

var app = require('express')();
var bodyParser = require('body-parser');

app.use(bodyParser.json()); // for parsing application/json
app.use(bodyParser.urlencoded({ extended: true })); // for parsing application/x-www-form-urlencoded

Ahora supongamos una petición como esta

PUT /settings/32135
{
  "name": "Peter"
}

Puedes acceder al nombre publicado así

req.body.name
// "Peter"

De manera similar, puede acceder a las cookies desde la solicitud, también necesita un middleware como el analizador de cookies.

req.cookies.name

Aplicación express modular

Para hacer expreso de aplicaciones web modulares utilizan las fábricas de enrutadores:

Módulo:

// greet.js
const express = require('express');

module.exports = function(options = {}) { // Router factory
    const router = express.Router();

    router.get('/greet', (req, res, next) => {
        res.end(options.greeting);
    });

    return router;
};

Solicitud:

// app.js
const express = require('express');
const greetMiddleware = require('./greet.js');

express()
    .use('/api/v1/', greetMiddleware({ greeting:'Hello world' }))
    .listen(8080);

Esto hará que su aplicación sea modular, personalizable y su código reutilizable.

Al acceder a http://<hostname>:8080/api/v1/greet la salida será Hello world

Ejemplo mas complicado

Ejemplo con servicios que muestra ventajas de middleware factory.

Módulo:

// greet.js
const express = require('express');

module.exports = function(options = {}) { // Router factory
    const router = express.Router();
    // Get controller
    const {service} = options;

    router.get('/greet', (req, res, next) => {
        res.end(
            service.createGreeting(req.query.name || 'Stranger')
        );
    });

    return router;
};

Solicitud:

// app.js
const express = require('express');
const greetMiddleware = require('./greet.js');

class GreetingService {
    constructor(greeting = 'Hello') {
        this.greeting = greeting;
    }

    createGreeting(name) {
        return `${this.greeting}, ${name}!`;
    }
}

express()
    .use('/api/v1/service1', greetMiddleware({
        service: new GreetingService('Hello'),
    }))
    .use('/api/v1/service2', greetMiddleware({
        service: new GreetingService('Hi'),
    }))
    .listen(8080);

Al acceder a http://<hostname>:8080/api/v1/service1/greet?name=World la salida será Hello, World y acceder a http://<hostname>:8080/api/v1/service2/greet?name=World la salida será Hi, World .

Usando un motor de plantillas

Usando un motor de plantillas

El siguiente código configurará Jade como motor de plantillas. (Nota: Jade ha sido renombrada a pug partir de diciembre de 2015).

const express = require('express');  //Imports the express module
const app = express();  //Creates an instance of the express module

const PORT = 3000; //Randomly chosen port

app.set('view engine','jade'); //Sets jade as the View Engine / Template Engine
app.set('views','src/views'); //Sets the directory where all the views (.jade files) are stored.

//Creates a Root Route
app.get('/',function(req, res){
    res.render('index');  //renders the index.jade file into html and returns as a response. The render function optionally takes the data to pass to the view.
});

//Starts the Express server with a callback
app.listen(PORT, function(err) {
    if (!err) {
        console.log('Server is running at port', PORT);
    } else {
        console.log(JSON.stringify(err));
    }
});

De manera similar, también se pueden usar otros motores de plantilla, como los Handlebars ( hbs ) o ejs . Recuerde a npm install el motor de plantillas también. Para Handlebars usamos el paquete hbs , para Jade tenemos un paquete de jade y para EJS, tenemos un paquete ejs .

Ejemplo de plantilla EJS

Con EJS (como otras plantillas Express), puede ejecutar el código del servidor y acceder a las variables de su servidor desde su HTML.
En EJS se hace usando " <% " como etiqueta de inicio y " %> " como etiqueta final, las variables pasadas como parámetros de render pueden accederse usando <%=var_name%>
Por ejemplo, si tiene una matriz de suministros en su código de servidor
puedes recorrerlo usando

<h1><%= title %></h1>
   <ul>
<% for(var i=0; i<supplies.length; i++) { %>
    <li>
        <a href='supplies/<%= supplies[i] %>'>
            <%= supplies[i] %>
        </a>
    </li>
<% } %>

Como puede ver en el ejemplo, cada vez que cambia entre el código del lado del servidor y el HTML, debe cerrar la etiqueta EJS actual y abrir una nueva más adelante. Aquí queríamos crear li dentro del comando for así que necesitamos cerrar nuestra etiqueta EJS. al final del for y crear una nueva etiqueta solo para los corchetes
otro ejemplo
Si queremos que la versión predeterminada de entrada sea una variable del lado del servidor, usamos <%=
por ejemplo:

 Message:<br>
<input type="text" value="<%= message %>" name="message" required>

Aquí, la variable de mensaje que se pasa desde el lado del servidor será el valor predeterminado de su entrada, tenga en cuenta que si no pasó la variable de mensaje desde el lado del servidor, EJS generará una excepción. Puede pasar parámetros usando res.render('index', {message: message}); (para el archivo ejs llamado index.ejs).

En las etiquetas EJS también puede usar if , while o cualquier otro comando javascript que desee.

API JSON con ExpressJS

var express = require('express');
var cors = require('cors'); // Use cors module for enable Cross-origin resource sharing

var app = express();
app.use(cors()); // for all routes

var port = process.env.PORT || 8080;

app.get('/', function(req, res) {
    var info = {
        'string_value': 'StackOverflow',
        'number_value': 8476
    }
    res.json(info);

    // or
    /* res.send(JSON.stringify({
        string_value: 'StackOverflow',
        number_value: 8476
    })) */

  //you can add a status code to the json response
   /* res.status(200).json(info) */
})

app.listen(port, function() {
    console.log('Node.js listening on port ' + port)
})

En http://localhost:8080/ output object

{
    string_value: "StackOverflow",
    number_value: 8476
}

Sirviendo archivos estáticos

Cuando se crea un servidor web con Express, a menudo se requiere que sirva una combinación de contenido dinámico y archivos estáticos.

Por ejemplo, puede tener index.html y script.js que son archivos estáticos guardados en el sistema de archivos.

Es común usar una carpeta llamada 'pública' para tener archivos estáticos. En este caso, la estructura de la carpeta puede verse como:

project root
├── server.js
├── package.json 
└── public
    ├── index.html
    └── script.js

Esta es la forma de configurar Express para servir archivos estáticos:

const express = require('express');
const app = express();

app.use(express.static('public'));

Nota: una vez que la carpeta esté configurada, index.html, script.js y todos los archivos en la carpeta "pública" estarán disponibles en la ruta raíz (no debe especificar /public/ en la url). Esto se debe a que, Express busca los archivos relativos a la carpeta estática configurada. Puede especificar el prefijo de la ruta virtual como se muestra a continuación:

app.use('/static', express.static('public'));

hará que los recursos estén disponibles bajo el prefijo /static/ .

Carpetas multiples

Es posible definir múltiples carpetas al mismo tiempo:

app.use(express.static('public'));
app.use(express.static('images'));
app.use(express.static('files'));

Al servir los recursos Express examinará la carpeta en orden de definición. En el caso de archivos con el mismo nombre, se servirá el de la primera carpeta coincidente.

Rutas con nombre en estilo Django

Un gran problema es que las rutas con nombre valiosas no son compatibles con Express out of the box. La solución es instalar un paquete de terceros compatible, por ejemplo, express-reverse :

npm install express-reverse

Conéctalo a tu proyecto:

var app = require('express')();
require('express-reverse')(app);

Entonces úsalo como:

app.get('test', '/hello', function(req, res) {
  res.end('hello');
});

La desventaja de este enfoque es que no puede usar el módulo route Express como se muestra en Uso de enrutador avanzado . La solución es pasar su app como un parámetro a su fábrica de enrutadores:

require('./middlewares/routing')(app);

Y utilízalo como:

module.exports = (app) => {
    app.get('test', '/hello', function(req, res) {
      res.end('hello');
    });
};

A partir de ahora, puede resolverlo, cómo definir funciones para combinarlas con espacios de nombres personalizados especificados y apuntar a los controladores apropiados.

Manejo de errores

Manejo básico de errores

De forma predeterminada, Express buscará una vista de 'error' en el directorio /views para renderizar. Simplemente cree la vista 'error' y colóquela en el directorio de vistas para manejar los errores. Los errores se escriben con el mensaje de error, el estado y el seguimiento de la pila, por ejemplo:

vistas / error.pug

html
  body
      h1= message
      h2= error.status
      p= error.stack

Manejo avanzado de errores

Defina sus funciones de middleware para el manejo de errores al final de la pila de funciones de middleware. Estos tienen cuatro argumentos en lugar de tres (err, req, res, next) por ejemplo:

app.js

// catch 404 and forward to error handler
app.use(function(req, res, next) {
    var err = new Error('Not Found');
    err.status = 404;

    //pass error to the next matching route.
    next(err);
});

// handle error, print stacktrace
app.use(function(err, req, res, next) {
    res.status(err.status || 500);

    res.render('error', {
        message: err.message,
        error: err
    });
});

Puede definir varias funciones de middleware de manejo de errores, tal como lo haría con las funciones de middleware regulares.

Usando middleware y la próxima devolución de llamada

Express pasa la next devolución de llamada a cada controlador de ruta y función de middleware que puede usarse para romper la lógica de rutas individuales a través de múltiples controladores. next() llamar a next() sin argumentos, se indica a Express que continúe con el siguiente middleware o controlador de ruta que coincida. Llamar a next(err) con un error activará cualquier middleware de controlador de errores. La llamada next('route') pasará por alto cualquier middleware posterior en la ruta actual y saltará a la siguiente ruta coincidente. Esto permite desacoplar la lógica del dominio en componentes reutilizables que son autónomos, más sencillos de probar y más fáciles de mantener y cambiar.

Múltiples rutas coincidentes

Las solicitudes a /api/foo o a /api/bar ejecutarán el controlador inicial para buscar el miembro y luego pasar el control al controlador real para cada ruta.

app.get('/api', function(req, res, next) {
  // Both /api/foo and /api/bar will run this
  lookupMember(function(err, member) {
    if (err) return next(err);
    req.member = member;
    next();
  });
});

app.get('/api/foo', function(req, res, next) {
  // Only /api/foo will run this
  doSomethingWithMember(req.member);
});

app.get('/api/bar', function(req, res, next) {
  // Only /api/bar will run this
  doSomethingDifferentWithMember(req.member);
});

Manejador de errores

Los manejadores de errores son middleware con la function(err, req, res, next) firma function(err, req, res, next) . Se pueden configurar por ruta (por ejemplo, app.get('/foo', function(err, req, res, next) ) pero, por lo general, un solo controlador de errores que presente una página de error es suficiente.

app.get('/foo', function(req, res, next) {
  doSomethingAsync(function(err, data) {
    if (err) return next(err);
    renderPage(data);
  });
});

// In the case that doSomethingAsync return an error, this special
// error handler middleware will be called with the error as the 
// first parameter.
app.use(function(err, req, res, next) {
  renderErrorPage(err);
});

Middleware

Cada una de las funciones anteriores es en realidad una función de middleware que se ejecuta siempre que una solicitud coincide con la ruta definida, pero cualquier número de funciones de middleware se puede definir en una sola ruta. Esto permite que el middleware se defina en archivos separados y que la lógica común se reutilice a través de múltiples rutas.

app.get('/bananas', function(req, res, next) {
  getMember(function(err, member) {
    if (err) return next(err);
    // If there's no member, don't try to look
    // up data. Just go render the page now.
    if (!member) return next('route');
    // Otherwise, call the next middleware and fetch
    // the member's data.
    req.member = member;
    next();
  });
}, function(req, res, next) {
  getMemberData(req.member, function(err, data) {
    if (err) return next(err);
    // If this member has no data, don't bother
    // parsing it. Just go render the page now.
    if (!data) return next('route');
    // Otherwise, call the next middleware and parse
    // the member's data. THEN render the page.
    req.member.data = data;
    next();
  });
}, function(req, res, next) {
  req.member.parsedData = parseMemberData(req.member.data);
  next();
});

app.get('/bananas', function(req, res, next) {
  renderBananas(req.member);
});

En este ejemplo, cada función de middleware estaría en su propio archivo o en una variable en otra parte del archivo para que pueda reutilizarse en otras rutas.

Manejo de errores

Los documentos básicos se pueden encontrar aquí

app.get('/path/:id(\\d+)', function (req, res, next) { // please note: "next" is passed
    if (req.params.id == 0) // validate param
        return next(new Error('Id is 0')); // go to first Error handler, see below

    // Catch error on sync operation
    var data;
    try {
        data = JSON.parse('/file.json');
    } catch (err) {
        return next(err);
    }

    // If some critical error then stop application
    if (!data)
        throw new Error('Smth wrong');

    // If you need send extra info to Error handler
    // then send custom error (see Appendix B)
    if (smth)
        next(new MyError('smth wrong', arg1, arg2))

    // Finish request by res.render or res.end
    res.status(200).end('OK');
});    

// Be sure: order of app.use have matter
// Error handler
app.use(function(err, req, res, next)) {
    if (smth-check, e.g. req.url != 'POST') 
        return next(err); // go-to Error handler 2.

    console.log(req.url, err.message);

    if (req.xhr) // if req via ajax then send json else render error-page
        res.json(err);
    else 
        res.render('error.html', {error: err.message});  
});

// Error handler 2
app.use(function(err, req, res, next)) {
    // do smth here e.g. check that error is MyError
    if (err instanceof MyError) {
        console.log(err.message, err.arg1, err.arg2);
    }     
    ...
    res.end();
});

Apéndice A

// "In Express, 404 responses are not the result of an error, 
// so the error-handler middleware will not capture them." 
// You can change it.
app.use(function(req, res, next) {
    next(new Error(404)); 
});

apéndice B

// How to define custom error
var util = require('util');
...
function MyError(message, arg1, arg2) {
    this.message = message;
    this.arg1 = arg1;
    this.arg2 = arg2;
    Error.captureStackTrace(this, MyError);
}
util.inherits(MyError, Error);
MyError.prototype.name = 'MyError';

Hook: Cómo ejecutar código antes de cualquier solicitud y después de cualquier resolución

app.use() y middleware pueden usarse para "antes" y una combinación de los eventos de cierre y finalización pueden usarse para "después".

app.use(function (req, res, next) {
    function afterResponse() {
        res.removeListener('finish', afterResponse);
        res.removeListener('close', afterResponse);

        // actions after response
    }
    res.on('finish', afterResponse);
    res.on('close', afterResponse);

    // action before request
    // eventually calling `next()`
    next();
});
...
app.use(app.router);

Un ejemplo de esto es el middleware del registrador , que se agregará al registro después de la respuesta de forma predeterminada.

Solo asegúrese de que este "middleware" se use antes de app.router ya que el orden sí importa.


La publicación original está aquí

Manejo de solicitudes POST

Al igual que usted maneja las solicitudes de obtención en Express con el método app.get, puede usar el método app.post para manejar las solicitudes posteriores.

Pero antes de que pueda manejar las solicitudes POST, necesitará usar el middleware body-parser del body-parser . Simplemente analiza el cuerpo de POST , PUT , DELETE y otras solicitudes.

Body-Parser middleware Body-Parser analiza el cuerpo de la solicitud y lo convierte en un objeto disponible en req.body

var bodyParser = require('body-parser');

const express = require('express');

const app = express();

// Parses the body for POST, PUT, DELETE, etc.
app.use(bodyParser.json());

app.use(bodyParser.urlencoded({ extended: true }));

app.post('/post-data-here', function(req, res, next){

    console.log(req.body); // req.body contains the parsed body of the request.

});

app.listen(8080, 'localhost');

El siguiente es un ejemplo para configurar y leer cookies utilizando el módulo de análisis de cookies :

var express = require('express');
var cookieParser = require('cookie-parser'); // module for parsing cookies
var app = express();
app.use(cookieParser());

app.get('/setcookie', function(req, res){
    // setting cookies
    res.cookie('username', 'john doe', { maxAge: 900000, httpOnly: true });
    return res.send('Cookie has been set');
});

app.get('/getcookie', function(req, res) {
    var username = req.cookies['username'];
    if (username) {
        return res.send(username);        
    }

    return res.send('No cookie found');
});

app.listen(3000);

Middleware personalizado en Express

En Express, puede definir middlewares que se pueden usar para verificar solicitudes o configurar algunos encabezados en respuesta.

app.use(function(req, res, next){ });    // signature

Ejemplo

El siguiente código agrega user al objeto de solicitud y pasa el control a la siguiente ruta coincidente.

var express = require('express');
var app = express();

//each request will pass through it
app.use(function(req, res, next){
    req.user = 'testuser';
    next();    // it will pass the control to next matching route
});

app.get('/', function(req, res){
    var user = req.user;
    console.log(user); // testuser
    return res.send(user);
});

app.listen(3000);

Manejo de errores en Express

En Express, puede definir un controlador de errores unificado para el manejo de errores ocurridos en la aplicación. Defina entonces el controlador al final de todas las rutas y el código lógico.

Ejemplo

var express = require('express');
var app = express();

//GET /names/john
app.get('/names/:name', function(req, res, next){
    if (req.params.name == 'john'){
        return res.send('Valid Name');
    } else{
        next(new Error('Not valid name'));    //pass to error handler
    }
});

//error handler
app.use(function(err, req, res, next){
    console.log(err.stack);    // e.g., Not valid name
    return res.status(500).send('Internal Server Occured');
});

app.listen(3000);

Añadiendo middleware

Las funciones de middleware son funciones que tienen acceso al objeto de solicitud (req), al objeto de respuesta (res) y a la siguiente función de middleware en el ciclo de solicitud-respuesta de la aplicación.

Las funciones de middleware pueden ejecutar cualquier código, realizar cambios en los objetos de res y req , finalizar el ciclo de respuesta y llamar al middleware siguiente.

Un ejemplo muy común de middleware es el módulo cors . Para agregar soporte CORS, simplemente instálelo, solicítelo y ponga esta línea:

app.use(cors());

Antes de cualquier enrutador o funciones de enrutamiento.

Hola Mundo

Aquí creamos un servidor básico hello world usando Express. Rutas:

  • '/'
  • '/ wiki'

Y para el descanso le dará "404", es decir, página no encontrada.

'use strict';

const port = process.env.PORT || 3000;

var app = require('express')();
    app.listen(port);

app.get('/',(req,res)=>res.send('HelloWorld!'));
app.get('/wiki',(req,res)=>res.send('This is wiki page.'));
app.use((req,res)=>res.send('404-PageNotFound'));

Nota: Hemos colocado la ruta 404 como la última ruta, ya que Express apila las rutas en orden y las procesa para cada solicitud de forma secuencial.



Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow