2010-12-07 11 views
46

Quiero ser capaz de alojar varias aplicaciones NodeJS bajo el mismo dominio, sin utilizar subdominios (como google.com/reader en lugar de images.google.com). El problema es que siempre escribo la primera parte de la url, p. "/ reader" en Express/NodeJS.¿Es posible establecer una URL base para la aplicación NodeJS?

¿Cómo puedo configurar una aplicación Express para que la URL base sea something.com/myapp?

Así que en lugar de:

app.get("/myapp", function (req, res) { 
    // can be accessed from something.com/myapp 
}); 

que puedo hacer:

// Some set-up 
app.base = "/myapp" 

app.get("/", function (req, res) { 
    // can still be accessed from something.com/myapp 
}); 

También me gustaría configurar staticProvider de Conectar a comportarse de la misma manera (en este momento el valor predeterminado es servir archivos estáticos a something.com/js o something.com/css en lugar de something.com/myapp/js)

+2

Tal vez usted puede actualizar la respuesta, ya que no está actualizado? –

Respuesta

15

Por el momento esto no es compatible, y no es fácil agregarlo a su propio.

Todo el enrutamiento está enterrado en el interior del código del servidor, y como beneficio adicional, no hay exposición de las rutas propias.

Rebusqué en la fuente y también revisé la última versión de Express y el middleware Connect, pero todavía no hay soporte para tal funcionalidad, debe abrir un problema ya sea en Connect o .

Mientras tanto ...

Patch lo mismo, aquí es una forma rápida y fácil con una sola línea de código cambiado.

En ~/.local/lib/node/.npm/express/1.0.0/package/lib/express/servers.js, la búsqueda de:

// Generate the route 
this.routes[method](path, fn); 

Esto debería ser alrededor de la línea 357, sustituir eso con:

// Generate the route 
this.routes[method](((self.settings.base || '') + path), fn); 

Ahora sólo tiene que añadir el ajuste:

app.set('base', '/myapp'); 

Estos trabajos bien con las rutas que son cadenas simples, para el soporte de RegEx usted hav Para piratear el middleware del enrutador usted mismo, mejor presente un problema en ese caso.

En lo que respecta al proveedor estático, solo agregue /mypapp al configurarlo.

actualización

hizo trabajar con RegExp también:

// replace 
this.routes[method](baseRoute(self.settings.base || '', path), fn); 

// helper 
function baseRoute(base, path) { 
    if (path instanceof RegExp) { 
     var exp = RegExp(path).toString().slice(1, -1); 
     return new RegExp(exp[0] === '^' ? '^' + base + exp.substring(1) : base + exp); 

    } else { 
     return (base || '') + path; 
    } 
} 

Sólo probado esto con un puñado de expresiones, por lo que este no se ha probado 100% pero en teoría debería funcionar.

Actualización 2

presentó un problema con el parche:
https://github.com/visionmedia/express/issues/issue/478

+0

Actualización: se corrigió el parche roto de cadenas simples. –

+0

Gracias por la respuesta completa. La solución para parchar trabajos express. Sin embargo, pasar un parámetro a staticProvider solo establece el directorio raíz donde se encuentran los archivos estáticos, no la url a la que se sirven. Supongo que se puede hacer un parche similar que elimine/myapp de la url. –

+0

Sobrescribir una biblioteca de terceros no es aconsejable ya que cada vez que actualice a una nueva versión también necesitará volver a agregar su código. – Intervalia

103

El router Express puede manejar esto desde 4,0

http://expressjs.com/api#router
http://bulkan-evcimen.com/using_express_router_instead_of_express_namespace.html

var express = require('express'); 
var app = express(); 
var router = express.Router(); 

// simple logger for this router's requests 
// all requests to this router will first hit this middleware 
router.use(function(req, res, next) { 
    console.log('%s %s %s', req.method, req.url, req.path); 
    next(); 
}); 

// this will only be invoked if the path ends in /bar 
router.use('/bar', function(req, res, next) { 
    // ... maybe some additional /bar logging ... 
    next(); 
}); 

// always invoked 
router.use(function(req, res, next) { 
    res.send('Hello World'); 
}); 

app.use('/foo', router); 

app.listen(3000); 

respuesta anterior (antes de expresar 4.0):

El módulo expreso-espacio de nombres (muerto) que se utiliza para hacer el truco:

https://github.com/visionmedia/express-namespace

require('express-namespace'); 

app.namespace('/myapp', function() { 
     app.get('/', function (req, res) { 
      // can be accessed from something.com/myapp 
     }); 
}); 
+14

Nota para las personas de Google: esta es la respuesta correcta aunque no esté marcada. Por lo general, es mejor evitar el parche de monos en una biblioteca bien mantenida si es posible. –

+2

nota además - proyecto parece estar muerta https://github.com/expressjs/express-namespace/issues/44 utilizar el router en el expreso 4 http://bulkan-evcimen.com/using_express_router_instead_of_express_namespace.html – CheapSteaks

+0

THX para la actualización, he cambiado la respuesta en consecuencia –

3

También hay problemas de fiabilidad. Si la confiabilidad es importante, una solución común es usar un proxy HTTP inverso de front-end como nginx o HAProxy. Ambos usan una arquitectura de un solo hilo y por lo tanto son muy escalables.

Luego puede tener diferentes procesos de nodo para diferentes subsitios, y si un sitio falla (excepción no detectada, pérdida de memoria, error del programador, lo que sea), el resto de los subsitios seguirán funcionando.

5

Pude lograr esto usando una combinación de espacio de nombres expresos para las rutas y una solución de la discusión de grupo de google a continuación para los recursos estáticos. Este fragmento será tratar una solicitud a /foo/javascripts/jquery.js como una solicitud para /javascripts/jquery.js:

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

Fuente: https://groups.google.com/forum/#!msg/express-js/xlP6_DX6he0/6OTY4hwfV-0J

+3

esta debe ser la respuesta, en lugar de piratear el núcleo. –

2

que estaba buscando esta característica, pero para rutas API, no para archivos estáticos. Lo que hice fue que cuando inicié el enrutador, agregué la ruta de montaje. Así que mi configuración es el siguiente Aviso

//Default configuration 
app.configure(function(){ 
    app.use(express.compress()); 
    app.use(express.logger('dev')); 
    app.set('json spaces',0); 
    app.use(express.limit('2mb')); 
    app.use(express.bodyParser()); 

    app.use('/api', app.router);  // <--- 

    app.use(function(err, req, res, callback){ 
     res.json(err.code, {}); 
    }); 
}); 

la '/ api' al llamar al router

+0

Vale la pena señalar que esta solución funciona sin problemas con expreso-recurso. Tengo varias subapps expresas que proporcionan una API debajo del prefijo/api usando esta solución y un sitio web regular en /. – diosney

5

Sólo para actualizar el hilo, ahora con Express.jsv4 puede hacerlo sin necesidad de utilizar express-namespace:

var express = require('express'), 
    forumRouter = express.Router(), 
    threadRouter = express.Router(), 
    app = express(); 

forumRouter.get('/:id)', function(req, res){ 
    res.send('GET forum ' + req.params.id); 
}); 

forumRouter.get('/:id/edit', function(req, res){ 
    res.send('GET forum ' + req.params.id + ' edit page'); 
}); 


forumRouter.delete('/:id', function(req, res){ 
    res.send('DELETE forum ' + req.params.id); 
}); 

app.use('/forum', forumRouter); 

threadRouter.get('/:id/thread/:tid', function(req, res){ 
    res.send('GET forum ' + req.params.id + ' thread ' + req.params.tid); 
}); 

forumRouter.use('/', threadRouter); 

app.listen(app.get("port") || 3000); 

¡Salud!

0

Sé que esta es una pregunta muy antigua, pero Express ha cambiado mucho desde que se publicaron la mayoría de estas respuestas, así que pensé en compartir mi enfoque.

Puede, por supuesto, usar enrutadores con Express 4 para agrupar las funciones relacionadas detrás de una ruta en particular. Esto está bien documentado y ya ha sido cubierto por otras respuestas.

Sin embargo, también es posible montar una aplicación completa en una ruta particular.A modo de ejemplo, asumamos nuestra aplicación (la que desea alojar en su /myapp) se parece a esto, en un archivo llamado myapp.js:

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

app.use(express.static(path.join(__dirname, 'public'))); 

app.get('/hello', function(req, res) { 
    res.send('Hello'); 
}); 

// Lots of other stuff here 

exports.app = app; 

En nuestro archivo principal js entonces podríamos montar toda esta solicitud en el camino /myapp:

var express = require('express'), 
    app = express(), 
    myApp = require('./myapp').app; 

app.use('/myapp', myApp); 

app.listen(3000); 

Tenga en cuenta que hemos creado aquí dos aplicaciones, una montada sobre la otra. La aplicación principal podría tener otras subaplicaciones montadas en diferentes rutas según sea necesario.

El código en myapp.js es completamente independiente de donde se montó. Es similar a la estructura utilizada por el express-generator en ese sentido.

Parte de la documentación sobre el sub-aplicaciones se puede encontrar aquí:

https://expressjs.com/en/4x/api.html#app.mountpath https://expressjs.com/en/4x/api.html#app.onmount

Cuestiones relacionadas