node-header

Hacer proxy con Apache para aplicaciones node.js

Tenemos una app desarrollada en nodejs que corre en el puerto 4000 de nuestro servidor y queremos exponerla por el puerto 80 para que la gente pueda usarla. El problema obvio es que por lo general tenemos corriendo un apache, nginx o cualquier otro servidor http.

La solución es usar los módulos de proxy que incluyen cada uno de estos servidores web. Hoy puntualmente lo vamos a hacer con Apache.

Habilitamos los modulos proxy y proxy_http para permitir el reenvío de peticiones HTTP y HTTPS:
[console]
sudo a2enmod proxy
sudo a2enmod proxy_http
[/console]

Luego nos queda crear un vhost:
[console]sudo nano /etc/apache2/sites-available/mipaginaweb.com[/console]

Y ponerle lo siguiente:

[apacheconf]

ServerName mipaginaweb.com
ServerAlias www.mipaginaweb.com

ProxyRequests off

Order deny,allow
Allow from all

<location “/”>
ProxyPass http://localhost:4000/ retry=0
ProxyPassReverse http://localhost:4000/

[/apacheconf]

Habilitamos nuestro nuevo vhost:
[console]sudo a2ensite mipaginaweb.com[/console]

Hemos terminado. reiniciamos apache y a correr!
[console]sudo service apache2 restart[/console]

Bonus: si estas en un entorno de desarrollo y quieres acceder a mipaginaweb.com, edita tu archivo hosts (sudo nano /etc/hosts) y añade tu nuevo dominio:

[console]
127.0.0.1 localhost
127.0.0.1 mipaginaweb.com www.mipaginaweb.com
[/console]

12 Comments

  • jorge 06/02/2013

    tengo una pregunta
    es posible reescribir las urls antes de pasarlas a nuestro servidor node js?
    algo así como un rewriteRule, para acceder desde node solo a los querystring y no tener que procesar demasiado la url
    Espero sus comentarios

    • Capy 08/02/2013

      No se si te entiendo. me das un ejemplo?

      • jorge 09/02/2013

        Algo así:
        Sabemos que tenemos dos dominios, mipaginaweb1.com y mipaginaweb2.com
        Se supone que mipaginaweb2.com es nuestra app en node (la otra, un index html común y corriente)
        Un usuario trata de acceder a http://www.mipaginaweb2.com
        Apache lo redirecciona a http://localhost:4000/
        La pregunta es, si un usuario tratara de acceder (por ejemplo) a la página http://www.mipaginaweb2.com/users/fulanodetal
        ¿existiría alguna forma de reescribir esa url antes de redirigir, para que esta quede del siguiente modo?: mipaginaweb2.com?location=users&search=fulanodetal
        Algo así como lo que hacemos con htaccess
        Saludos, y gracias por su atención

  • Capy 09/02/2013

    aaaaaaaa ya te entendí. Bueno acá Apache es transparente, y lo único que esta haciendo reenviar la petición. no cumple ningún rol a demás de ese, ni debe hacerlo ya que el día de mañana puede que tu proxy sea nginx o varnish. Quiero decir con esto que ni si quiera deberías plantear hacer algo así desde apache, déjale eso a tu app.

    Si tu app esta hecha en express ya tenes un sistema de ruteo mucho mas fácil que la reescritura de urls.

    por ejemplo:

    Esto ya te permitiría usar url del tipo “http://www.mipaginaweb2.com/users/fulanodetal”, “http://www.mipaginaweb2.com/users/fulanodecual”

    Las reescrituras de url son pasado en nodejs, básicamente porque frameworks como expressjs ya traen de serie sistemas de routing.

    Para terminar por si no ha quedado claro: las reescrituras de url nacieron porque no era posible a nivel de aplicación definir urls del tipo /usuario/pedro y mapearla a una funcion. (PHP por ejemplo) Para lograrlo habia que pedirle al servidor web que re interpretara esa url a parámetros que se pudieran pasar a un archivo que los leyera y que llamara a una función en consecuencia.
    Y la cosa con nodejs es distinta, ya que node al ser servidor web y aplicación web al mismo tiempo es capaz de mapear directamente urls a funciones (como el ejemplo que dejé arriba).

    Saludos.

  • David Hernandez 01/05/2013

    Disculpe, soy nuevo en este mundo de node.js queria saber si tengo una pagina hecha en frames por ejemplo, y contiene un index.html en una frame y otro index.jade en otro frame, como puedo hacer para correr dicha pagina principal donde corran ambas paginas? Ya que por un servidor apache no correria los websockets del index.jade, y no tengo idea como ejecutar un html desde node.js, Gracias por su atencion

    • Capy 03/05/2013

      Hola David. Suponiendo que estas usando expressjs, fa forma de servir documentos con extensión .html es esta: http://www.hacksparrow.com/how-to-server-static-html-files-in-express-js.html

      Frames… a ver, supongamos que tenes tupagina.com/home y en esa home se renderiza una pagina que tiene dos iframe. pues lo único que tendrías que hacer es apuntar la url de cada uno de los frame a una url que hayas definido en express, y en cada una de esas nuevas rutas entregas el el .jade o .html que quieras…

      Perdón por dar una respuesta tan poco precisa, pero es que no se muy bien qué necesitas.

      Un saludo.

  • Dave Olvera 11/02/2015

    Hola que tal me preguntaba si esto del proxy es lo que necesito para redireccionar una petición a otro dominio. Por ejemplo digamos que yo tengo mi aplicación en el dominio a.com (node.js) desde esta aplicación yo hago un request a mi propio dominio, entonces desde node.js ¿Puedo hacer una segunda petición a mi dominio b.com?

    Pregunto esto porque no quiero hacer la petición directamente desde el cliente ya que es necesario que la url b.com no se mantenga expuesta.

    Saludos!!!

    • Capy 17/02/2015

      Bueno según entiendo, quieres que la gente entre en a.com y que internamente esa petición se mande a b.com para que b.com la responda y tu la devuelvas finalmente por a.com

      En ese caso es algo parecido a lo que se menciona en este post:
      mipaginaweb.com = a.com
      http://localhost:4000 = b.com

      A resumidas cuentas un dominio se esconde detrás del otro.

      Espero que lo consigas. Un saludo.

  • Super 23/05/2015

    Hola capy,

    gracias por el artículo, este me ha dado una idea respecto a un caso similar sobre el que estoy trabajando, pero al mismo tiempo me generó un problema que no he podido resolver, te explico.

    Antecedentes:
    * http server: apache2
    * tengo un localhost en el puerto el 443 (con SSL).
    * tengo varios dominios virtuales adicionales con puertos distintos sobre apache (ej: 5001, 5002 ..).
    * los dominios virtuales adicionales son cargados mediante “iframe” sobre una página perteneciente al localhost.

    Requerimiento:
    * necesito tener acceso JS desde desde el localhost a los iframes que contienen los dominios virtuales adicionales.

    Propuesta:
    * Utilizar proxys.

    Problema:
    * en los distintos dominios virtuales adicionales existen archivos de igual nombre en iguales rutas relativas, por lo que al realizar una configuración proxy mediante apache, las URL de estos archivos se sobreescriben. Ej: Dom Virtual 1: localhost:5001/index.html; Dom Virtual 2: localhost:5002/index.html.
    * la solución me debe permitir mantener los nombres originales de los archivos.

    Has tenido alguna vez un problema similar? tienes alguna sugerencia ?
    Espero q me puedas ayudar, de todas maneras muchas gracias.

    salu2!

  • jorarome 14/06/2015

    Hola Crapy, retomando la app desarrollada en nodejs que correo en el puerto 4000, que recomendacion da para sacarla a puerto 80 de varios virtualhost usando Apache?, por ejem: mipaguinaweb.com, tupaginaweb.org, lapaginaweb.com,etc. Agradezco de atenmano su comentario.

    • Capy 20/06/2015

      ¿Crapy? o_O

      Podes meter todos los alias que necesites:
      [apacheconf]
      ServerName ejemplo.com
      ServerAlias otraurl.com unamas.com etc.com
      [/apacheconf]
      Saludos.

  • Castro Garcia Jose Luis 11/10/2016

    Me sale este error:
    Job for apache2.service failed because the control process exited with error code. See “systemctl status apache2.service” and “journalctl -xe” for details.

    trabajo en Ubuntu

:).