2011-06-13 29 views
14

Tengo una aplicación Sinatra ejecutándose en nginx (utilizando thin como un proxy de respaldo) y estoy usando declaraciones redirect '/<path>' en Sinatra. Sin embargo, cuando accedo al sitio en https, esos redireccionamientos me envían al http://localhost/<path> en lugar de a https://localhost/<path> como deberían.Cómo reparar Sinatra redirigiendo https a http bajo nginx

Actualmente, nginx pasa el control al fina con este comando proxy_pass http://thin _cluster, donde thin_cluster es

upstream thin_cluster { server unix:/tmp/thin.cct.0.sock; } 

¿Cómo puedo solucionar este problema?

+0

¿Agregar 'proxy_set_header X-Forwarded-Proto $ scheme;' después de su línea 'proxy_pass' ayuda? – matt

+0

Debería escribir eso como una respuesta ... solucionó mi problema. ¡Gracias! –

Respuesta

22

Con el fin de Sinatra a montar correctamente la URL utilizada para redirecciones, que tiene que ser capaz de determinar si la solicitud usa ssl, de modo que la redirección se puede hacer usando http o https según corresponda.

Obviamente, la llamada real a thin no está utilizando ssl, ya que esto está siendo manejado por el servidor web front-end, y la solicitud de proxy está en claro. Por lo tanto, necesitamos una forma de decirle a Sinatra que debe tratar la solicitud como segura, incluso si no está realmente usando SSL.

En última instancia, el código que determina si la solicitud debe tratarse como segura está en los métodos Rack::Request#ssl? y Rack::Request#scheme. Los métodos scheme examinan el hash env para ver si hay una o varias entradas presentes. Uno de estos es HTTP_X_FORWARDED_PROTO que corresponde al encabezado HTTP X-Forwarded-Proto. Si esto está establecido, entonces el valor se usa como esquema de protocolo (http o https).

Así que si agregamos este encabezado HTTP a la solicitud cuando se envía un proxy desde nginx al back-end, Sinatra podrá determinar correctamente cuándo redirigir a https. En nginx podemos agregar encabezados a las solicitudes de proxy con proxy_set_header, y el esquema está disponible en el $scheme variable.

por lo que añadir la línea

proxy_set_header X-Forwarded-Proto $scheme; 

a la configuración de nginx después de la línea proxy_pass debe hacer que funcione.

+0

Por alguna razón, esto arruinó el campo Host en mis encabezados, enviando todos mis redirect_to a dominios no válidos. Agregar "proxy_set_header Host $ host" lo solucionó. (Mi aplicación se está ejecutando bajo un sub-uri, y me pregunto si eso es un problema.) – bioneuralnet

+2

@bioneuralnet también puede usar 'X-Forwarded-Host', que verifica en rack antes de comprobar el encabezado' Host'. No parece que nginx agregue automáticamente estos encabezados, pero Apache lo hace en mod_proxy. – matt

+1

Sí, supongo que eso también funcionaría. Encontré una explicación interesante en http://wiki.nginx.org/HttpProxyModule#proxy_set_header.Estaba configurando el host proxy_set_header en el bloque http, para usar con todas mis aplicaciones. En función de su publicación, agregué proxy_set_header X-Forwarded-Proto en la ubicación @myapp. De acuerdo con los documentos, las "directivas proxy_set_header emitidas en niveles superiores solo se heredan cuando no se han emitido directivas proxy_set_header en un nivel determinado". Así que mi llamada "local" proxy_set_header en @myapp estaba borrando mis llamadas "global" proxy_set_header, a pesar de que eran para diferentes campos. – bioneuralnet

1

Puede obligar a todos los enlaces a ir a https en la capa nginx. en nginx.conf:

server{ 
    listen 80; 
    server_name example.com; 
    rewrite ^(.*) https://$server_name$1 redirect; 
}  

Esto es bueno tener también para asegurar que sus peticiones son siempre https

+0

Esto es útil ... pero no responde la pregunta que hice. Ya tengo esta funcionalidad funcionando si el servidor se ejecuta en modo solo HTTPS; Mi problema ocurre cuando quiero aceptar tanto HTTPS como HTTP. –