Objeto Application
El objeto app denota convencionalmente la aplicación Express.
Créalo llamando a la función express() de nivel superior exportada por el módulo Express:
var express = require('express');var app = express();
app.get('/', function (req, res) { res.send('hello world');});
app.listen(3000);Propiedades
app.locals
Las variables locales de la aplicación se proporcionan a todas las plantillas renderizadas dentro de la aplicación. Esto es útil para proporcionar funciones de ayuda a las plantillas, así como datos a nivel de aplicación.
app.locals.title = 'My App';app.locals.strftime = require('strftime');El objeto app.locals es una Function de JavaScript,
que cuando se invoca con un objeto fusiona las propiedades en sí mismo, proporcionando
una forma sencilla de exponer objetos existentes como variables locales.
app.locals({ title: 'My App', phone: '1-250-858-9990', email: 'me@myapp.com',});
console.log(app.locals.title);// => 'My App'
console.log(app.locals.email);// => 'me@myapp.com'Una consecuencia de que el objeto app.locals sea en última instancia un objeto Function de JavaScript es que no debes reutilizar propiedades nombradas existentes (nativas) para tus propios nombres de variables, como name, apply, bind, call, arguments, length, constructor.
app.locals({ name: 'My App' });
console.log(app.locals.name);// => return 'app.locals' in place of 'My App' (app.locals is a Function !)// => if name's variable is used in a template, a ReferenceError will be returned.La lista completa de propiedades nombradas nativas se puede encontrar en muchas especificaciones. La especificación de JavaScript introdujo propiedades originales, algunas de las cuales todavía son reconocidas por los motores modernos, y la especificación de EcmaScript luego construyó sobre ella y normalizó el conjunto de propiedades, agregando nuevas y eliminando las obsoletas. Revisa las propiedades de Functions y Objects si te interesa.
Por defecto Express expone solo una variable local a nivel de aplicación, settings.
app.set('title', 'My App');// use settings.title in a viewapp.routes
El objeto app.routes alberga todas las rutas definidas mapeadas
por el verbo HTTP asociado. Este objeto puede usarse para capacidades de introspección,
por ejemplo Express lo usa internamente no solo para enrutamiento sino para proporcionar valores por defecto
app.options() is used. Your application or framework may
also remove routes by simply by removing them from this object.
La salida de console.log(app.routes):
{ get: [ { path: '/', method: 'get', callbacks: [Object], keys: [], regexp: /^\/\/?$/i }, { path: '/user/:id', method: 'get', callbacks: [Object], keys: [{ name: 'id', optional: false }], regexp: /^\/user\/(?:([^\/]+?))\/?$/i } ], delete: [ { path: '/user/:id', method: 'delete', callbacks: [Object], keys: [Object], regexp: /^\/user\/(?:([^\/]+?))\/?$/i } ] }settings
Las siguientes configuraciones se proporcionan para alterar el comportamiento de Express:
envModo de entorno, por defecto process.env.NODE_ENV o "development"trust proxyHabilita el soporte de proxy inverso, deshabilitado por defectojsonp callback nameCambia el nombre predeterminado del callback de ?callback=json replacerCallback reemplazador de JSON, null por defectojson spacesEspacios de respuesta JSON para formato, por defecto 2 en desarrollo, 0 en produccióncase sensitive routingHabilita la sensibilidad a mayúsculas y minúsculas, deshabilitado por defecto, tratando "/Foo" y "/foo" como igualesstrict routingHabilita el enrutamiento estricto, por defecto "/foo" y "/foo/" son tratados igual por el routerview cacheHabilita el caché de compilación de plantillas de vista, habilitado en producción por defectoview engineLa extensión de motor predeterminada a usar cuando se omiteviewsLa ruta del directorio de vistas, por defecto "process.cwd() + '/views'"
Métodos
app.set(name, value)
Asigna la configuración name al valor value.
app.set('title', 'My Site');app.get('title');// => "My Site"app.get(name)
Obtiene el valor de la configuración name.
app.get('title');// => undefined
app.set('title', 'My Site');app.get('title');// => "My Site"app.enable(name)
Establece la configuración name en true.
app.enable('trust proxy');app.get('trust proxy');// => trueapp.disable(name)
Establece la configuración name en false.
app.disable('trust proxy');app.get('trust proxy');// => falseapp.enabled(name)
Verifica si la configuración name está habilitada.
app.enabled('trust proxy');// => false
app.enable('trust proxy');app.enabled('trust proxy');// => trueapp.disabled(name)
Verifica si la configuración name está deshabilitada.
app.disabled('trust proxy');// => true
app.enable('trust proxy');app.disabled('trust proxy');// => falseapp.configure([env], callback)
Invoca condicionalmente callback cuando env coincide con app.get('env'),
es decir, process.env.NODE_ENV. Este método se mantiene por razones de compatibilidad, y es efectivamente
una sentencia if como se ilustra en los siguientes fragmentos. Estas funciones no
son necesarias para usar app.set() y otros métodos de configuración.
// all environmentsapp.configure(function () { app.set('title', 'My Application');});
// development onlyapp.configure('development', function () { app.set('db uri', 'localhost/dev');});
// production onlyapp.configure('production', function () { app.set('db uri', 'n.n.n.n/prod');});Es efectivamente azúcar sintáctica para:
// all environmentsapp.set('title', 'My Application');
// development onlyif (app.get('env') === 'development') { app.set('db uri', 'localhost/dev');}
// production onlyif (app.get('env') === 'production') { app.set('db uri', 'n.n.n.n/prod');}app.use([path], function)
Usa la function de middleware dada, con una path de montaje opcional,
por defecto "/".
var express = require('express');var app = express();
// simple loggerapp.use(function (req, res, next) { console.log('%s %s', req.method, req.url); next();});
// respondapp.use(function (req, res, next) { res.send('Hello World');});
app.listen(3000);La ruta de "montaje" se elimina y no es visible
para la function de middleware. El efecto principal de esta característica es que
el middleware montado puede operar sin cambios en el código independientemente de su ruta de
"prefijo".
Precaución
Una ruta coincidirá con cualquier ruta que siga a su ruta inmediatamente con un "/" o un ".". Por ejemplo: app.use('/apple', ...) coincidirá con /apple, /apple/images, /apple/images/news, /apple.html, /apple.html.txt, y así sucesivamente.
Aquí hay un ejemplo concreto, toma el caso de uso típico de servir archivos en ./public
usando el middleware express.static():
// GET /javascripts/jquery.js// GET /style.css// GET /favicon.icoapp.use(express.static(path.join(__dirname, 'public')));Digamos por ejemplo que quieres prefijar todos los archivos estáticos con "/static", podrías
usar la característica de "montaje" para soportar esto. Las funciones de middleware montadas no
se invocan a menos que req.url contenga este prefijo, momento en el que
se elimina cuando se invoca la función. Esto afecta solo a esta función,
el middleware subsiguiente verá req.url con "/static" incluido
a menos que también estén montadas.
// GET /static/javascripts/jquery.js// GET /static/style.css// GET /static/favicon.icoapp.use('/static', express.static(path.join(__dirname, 'public')));El orden en que el middleware se "define" usando app.use() es
muy importante, se invocan secuencialmente, por lo tanto esto define la precedencia
del middleware. Por ejemplo usualmente express.logger() es el primer
middleware que usarías, registrando cada solicitud:
app.use(express.logger());app.use(express.static(path.join(__dirname, 'public')));app.use(function (req, res) { res.send('Hello');});Ahora supón que quieres ignorar el registro de solicitudes para archivos estáticos, pero
continuar registrando rutas y middleware definidos después de logger(),
simplemente mueve static() arriba:
app.use(express.static(path.join(__dirname, 'public')));app.use(express.logger());app.use(function (req, res) { res.send('Hello');});Otro ejemplo concreto sería servir archivos desde múltiples directorios, dando precedencia a "./public" sobre los demás:
app.use(express.static(path.join(__dirname, 'public')));app.use(express.static(path.join(__dirname, 'files')));app.use(express.static(path.join(__dirname, 'uploads')));app.engine(ext, callback)
Registra el callback del motor de plantillas dado como ext
Por defecto hará require() del motor basándose en la
extensión del archivo. Por ejemplo si intentas renderizar
un archivo "foo.jade" Express invocará lo siguiente internamente,
y almacenará en caché el require() en llamadas subsiguientes para aumentar
el rendimiento.
app.engine('jade', require('jade').__express);Para motores que no proporcionan .__express listo para usar -
o si deseas "mapear" una extensión diferente al motor de plantillas
puedes usar este método. Por ejemplo mapear el motor de plantillas EJS a
archivos ".html":
app.engine('html', require('ejs').renderFile);En este caso EJS proporciona un método .renderFile() con
la misma firma que Express espera: (path, options, callback),
aunque ten en cuenta que aliasa este método como ejs.__express internamente
por lo que si usas extensiones ".ejs" no necesitas hacer nada.
Algunos motores de plantillas no siguen esta convención, la
La librería consolidate.js fue creada para mapear todos los motores de plantillas populares de node para seguir esta convención, permitiendo así que funcionen sin problemas dentro de Express.
var engines = require('consolidate');app.engine('haml', engines.haml);app.engine('html', engines.hogan);app.param([name], callback)
Mapea lógica a los parámetros de ruta. Por ejemplo cuando :user
está presente en una ruta puedes mapear la lógica de carga de usuario para proporcionar
automáticamente req.user a la ruta, o realizar validaciones
sobre la entrada del parámetro.
El siguiente fragmento ilustra cómo el callback
es muy parecido a middleware, soportando operaciones asíncronas, sin embargo
proporciona el valor adicional del parámetro, aquí llamado id.
Luego se realiza un intento de cargar el usuario, asignando req.user,
de lo contrario pasando un error a next(err).
app.param('user', function (req, res, next, id) { User.find(id, function (err, user) { if (err) { next(err); } else if (user) { req.user = user; next(); } else { next(new Error('failed to load user')); } });});Alternativamente puedes pasar solo un callback, en cuyo
caso tienes la oportunidad de alterar la API de app.param().
Por ejemplo express-params
define el siguiente callback que te permite restringir parámetros a una
expresión regular dada.
Este ejemplo es un poco más avanzado, verificando si el segundo argumento es una expresión regular, devolviendo el callback que actúa muy parecido al ejemplo del parámetro "user".
app.param(function (name, fn) { if (fn instanceof RegExp) { return function (req, res, next, val) { var captures; if ((captures = fn.exec(String(val)))) { req.params[name] = captures; next(); } else { next('route'); } }; }});El método ahora podría usarse para validar efectivamente parámetros, o también analizarlos para proporcionar grupos de captura:
app.param('id', /^\d+$/);
app.get('/user/:id', function (req, res) { res.send('user ' + req.params.id);});
app.param('range', /^(\w+)\.\.(\w+)?$/);
app.get('/range/:range', function (req, res) { var range = req.params.range; res.send('from ' + range[1] + ' to ' + range[2]);});app.VERB(path, [callback…], callback)
Los métodos app.VERB() proporcionan la funcionalidad de enrutamiento
en Express, donde VERB es uno de los verbos HTTP, como
por ejemplo app.post(). Se pueden proporcionar múltiples callbacks, todos son tratados
equitativamente, y se comportan como middleware, con la única excepción de que
estos callbacks pueden invocar next('route') para omitir los
callback(s) de ruta restantes. Este mecanismo puede usarse para realizar pre-condiciones
en una ruta y luego pasar el control a las rutas subsiguientes cuando no hay razón para proceder
con la ruta coincidente.
El siguiente fragmento ilustra la definición de ruta más simple posible. Express traduce las cadenas de ruta a expresiones regulares, usadas internamente para coincidir con las solicitudes entrantes. Las cadenas de consulta no se consideran al realizar estas coincidencias, por ejemplo "GET /" coincidiría con la siguiente ruta, al igual que "GET /?name=tobi".
app.get('/', function (req, res) { res.send('hello world');});También se pueden usar expresiones regulares, y pueden ser útiles si tienes restricciones muy específicas, por ejemplo lo siguiente coincidiría con "GET /commits/71dbb9c" así como con "GET /commits/71dbb9c..4c084f9".
app.get(/^\/commits\/(\w+)(?:\.\.(\w+))?$/, function (req, res) { var from = req.params[0]; var to = req.params[1] || 'HEAD'; res.send('commit range ' + from + '..' + to);});También se pueden pasar varios callbacks, útil para reutilizar middleware que carga recursos, realiza validaciones, etc.
app.get('/user/:id', user.load, function () { // ...});Estos callbacks también pueden pasarse dentro de arrays, estos arrays se aplanan simplemente al pasarse:
var middleware = [loadForum, loadThread];
app.get('/forum/:fid/thread/:tid', middleware, function () { // ...});
app.post('/forum/:fid/thread/:tid', middleware, function () { // ...});app.all(path, [callback…], callback)
Este método funciona igual que los métodos app.VERB(),
sin embargo coincide con todos los verbos HTTP.
Este método es extremadamente útil para
mapear lógica "global" para prefijos de ruta específicos o coincidencias arbitrarias.
Por ejemplo si colocas la siguiente ruta al principio de todas las demás
definiciones de rutas, requeriría que todas las rutas a partir de ese punto
requerirían autenticación, y cargarían automáticamente un usuario. Ten en mente
que estos callbacks no tienen que actuar como puntos finales, loadUser
puede realizar una tarea, luego next() para continuar coincidiendo con rutas
subsiguientes.
app.all('*', requireAuthentication, loadUser);O el equivalente:
app.all('*', requireAuthentication);app.all('*', loadUser);Otro gran ejemplo de esto es la funcionalidad "global" con lista blanca. Aquí el ejemplo es muy parecido al anterior, sin embargo solo restringiendo rutas prefijadas con "/api":
app.all('/api/*', requireAuthentication);app.render(view, [options], callback)
Renderiza una view con un callback que responde con
la cadena renderizada. Esta es la variante a nivel de aplicación de res.render(),
y por lo demás se comporta de la misma manera.
app.render('email', function (err, html) { // ...});
app.render('email', { name: 'Tobi' }, function (err, html) { // ...});app.listen()
Vincula y escucha conexiones en el host y puerto dados, este método es idéntico a http.Server#listen() de node.
var express = require('express');var app = express();app.listen(3000);El app devuelto por express() es de hecho una
Function de JavaScript, diseñada para pasarse a los servidores http de node como callback
para manejar solicitudes. Esto te permite proporcionar tanto versiones HTTP como HTTPS de
tu app con la misma base de código fácilmente, ya que la app no hereda de estos,
es simplemente un callback:
var express = require('express');var https = require('https');var http = require('http');var app = express();
http.createServer(app).listen(80);https.createServer(options, app).listen(443);El método app.listen() es simplemente un método de conveniencia definido como,
si deseas usar HTTPS o proporcionar ambos, usa la técnica anterior.
app.listen = function () { var server = http.createServer(this); return server.listen.apply(server, arguments);};