2011-12-21 21 views
19

Tengo dos instancias iKaaro ejecutándose en los puertos 8080 y 9080, donde la instancia 9080 es solo de lectura.nginx proxy_pass en función de si el método de solicitud es POST, PUT o DELETE

No estoy seguro de cómo usar nginx, por ejemplo, si el método de solicitud es POST, PUT, DELETE y luego enviar a instancia de escritura (8080) else enviar a instancia de 9080.

He hecho algo usando la ubicación usando la expresión regular, pero esto no es correcto.

De http://wiki.nginx.org/HttpLuaModule veo que hay los 'constantes método HTTP' que se puede llamar, por lo que es correcto para añadir un bloque de ubicación como:

location ~* "(ngx.HTTP_POST|ngx.HTTP_DELETE|ngx.HTTP_PUT)" { 
    proxy_pass http://127.0.0.1:8080; 

Gracias

+0

¿Puede explicar la pregunta un poco mejor? ¿Has probado esa configuración? ¿Estás teniendo algún error con él (cuáles)? – kikito

Respuesta

33

que acabo de hacer una prueba rápida, y esto funcionó para mí:

server { 
    location/{ 
    # This proxy_pass is used for requests that don't 
    # match the limit_except 
    proxy_pass http://127.0.0.1:8080; 

    # For requests that *aren't* a PUT, POST, or DELETE, 
    # pass to :9080 
    limit_except PUT POST DELETE { 
     proxy_pass http://127.0.0.1:9080; 
    } 
    } 
} 
+1

esto es incluso más corto – khinester

+1

tampoco se basa en ningún módulo de terceros – kolbyjack

+2

No funciona para mí en nginx 1.7.6 .. –

10

Asumo que tiene el conceptos básicos en su lugar. I.E., ha instalado Lua 5.1, o mejor aún, LuaJIT 2.0, en su servidor, compiló Nginx con el módulo ngx_lua y configuró ngx_lua según sea necesario.

Con esto en su lugar, esto va a hacer el trabajo:

location /test { 
    content_by_lua ' 
     local reqType = ngx.var.request_method 
     if reqType == ngx.HTTP_POST 
      OR reqType == ngx.HTTP_DELETE 
      OR reqType == ngx.HTTP_PUT 
     then 
      res = ngx.location.capture("/write_instance") 
     else 
      res = ngx.location.capture("/read_instance") 
     end 
     ngx.say(res.body) 
    '; 
} 
location /write_instance { 
    internal; 
    proxy_pass http://127.0.0.1:8080; 
} 
location /read_instance { 
    internal; 
    proxy_pass http://127.0.0.1:9080; 
} 

ACTUALIZACIÓN

pensé que tal vez estabas en concreto utilizando Lua en un ámbito más amplio. El siguiente ejemplo también funcionaría con el mismo principio que limit_except.

location /test { 
    if ($request_method !~* GET) { 
     # For Write Requests 
     proxy_pass http://127.0.0.1:8080; 
    } 
    # For Read Requests 
    proxy_pass http://127.0.0.1:9080; 
} 

Ambos "si" y el bloque "limit_except" crear de manera efectiva un bloque de ubicación anidada y una vez que los partidos de condición, se ejecuta sólo el controlador de contenido ("PROXY_PASS") del bloque de ubicación interior así creada.

No entiendo completamente esto es por qué si a veces se dice que es "malo", pero en este caso el comportamiento "malo", común a "if" y "limit_except", puede ser exactamente lo que quiere.

¡Tres opciones para que elija!

Sin embargo, tenga en cuenta que tendrá que observar que no es mordido por el comportamiento "malo" con cualquiera de las opciones "if" o "limit_except" si necesita establecer otras directivas.

I.E., si establece una directiva dentro del bloque "if" o "limit_except", es posible que no esté activa fuera de él y, de forma similar, algo que se ajustó afuera puede heredarse dentro. Por lo tanto, debe tener en cuenta cómo se heredan los valores predeterminados, o no, según sea el caso, con ambos enfoques.

Todos los posibles problemas enumerados en la página If is Evil se aplican igualmente a "if" y "limit_except" aquí. El enfoque de scripting basado en Lua evitará muchos de los peligros potenciales como se sugiere en esa página.

¡Buena suerte!

+0

gracias por esto tiene sentido. – khinester

+0

gracias por la explantación detallada, así que tengo que tener cuidado si el IfiSEvil debería necesitar ejecutar otras directivas. Es posible que necesite, ya que también necesito incluir una URL específica, como location ~ * "(login | new_content)" {... pero intentaré resolverlo y volver aquí con mi archivo nginx.conf para ver si se puede mejorar – khinester

+0

Intenta separar las consultas por problema específico. Supongo que con las tres opciones que tiene, la pregunta específica sobre cómo se han respondido exhaustivamente las solicitudes de ruta en Nginx basadas en el método de solicitud. Puede "if" directamente o "limit_except", que es un tipo de instrucción if que tiene en cuenta los problemas potenciales, o utilizar un método de guiones como el ejemplo de Lua proporcionado para evitar estos problemas. Es posible que desee considerar aceptar una u otra de las respuestas dadas y hacer una nueva pregunta si hay otros problemas. – Dayo

1

En caso de que alguien en busca de una manera de hacer simplemente las condiciones de método de la petición, la sintaxis es:

if ($request_method = DELETE) { 
    . . . 
} 
+1

.. sin embargo, debo mencionar que el uso de IF en config no es recomendado por Equipo de nginx: http://wiki.nginx.org/IfIsEvil – Sych

1

Yo recomendaría la función de mapa nginx. Esto va fuera de su bloque de ubicación:

map $request_method $destination { 
    default 8080; 
    PUT 9080; 
    POST 9080; 
    DELETE 9080; 
} 

A continuación, en el bloque de ubicación:

proxy_pass http://127.0.0.1:$destination 

Esto es todo expresiones regulares también, por lo que puede hacer cosas como:

map $request_method $cookie_auth $destination { 
    default 8080; 
    "^POST " 9080; 
    "^PUT someAuthCookieValue" 9080; 
} 

Además este evita el uso de si lo hace en absoluto. Es bastante impresionante. Lo usé para dirigir todo el tráfico de escritura en un clúster de WordPress a un socket FastCGI TCP en un nodo remoto, pero enviaba tráfico de lectura a un socket FastCGI UNIX local.

Cuestiones relacionadas