How to proxy_pass POST with headers

#1

Hi,

I’m using Typo3 as CMS with Apache on Ubuntu 10.04. I’m trying to set
Nginx as a reverse proxy with a typo3 extension evo_nginx_boost that
uses memcached. I have everything running on the same machine, Nginx on
port 80 and apache behind a firewall on port 8085 and memcached behind a
on port 11211.

So far I have got everything else working just fine except sending any
POST information, ex. logging in, etc. This causes browser to try to
fetch images, etc. behind firewall (port 8085) and also Typo3 doesn’t
know how to parse the url to right place (it’s creating nice urls.
Instead of foo.bar/index.php?id=123 it uses
foo.bar/this/is/the/file.html)

I think that In order to get it work I would somehow need to be able to
set proxy_set_header Host $http_host;, but Nginx doesn’t let me do that
in if-statement (see below). I really don’t know how to resolve this and
googling around didn’t help me, so I would be extremely happy if anybody
could give me any feedback! Thanks!

Here is my Nginx conf for the server:

server {
listen 80;
server_name foo.bar;

 access_log  /var/log/nginx/localhost.access.log;
 error_log  /var/log/nginx/error.log debug;

 location / {

    set $domain "http://foo.bar";

 if ($request_method = POST)
    {
        proxy_pass  http://foo.bar:8085;
        break;
    }

# set default memcache key
       set $href $host$request_uri;

  if ($http_cookie ~* "be_typo_user")
    {
       proxy_pass  http://foo.bar:8085;
       break;
    }


  if ($http_cookie ~* "nginx_boost_fe_user=([^;]+)(?:;|$)")
    {
       set $href $host$request_uri$1;
    }

       set $memcached_key $href;

# Check if local memcached server can answer this request
       default_type text/html;
       memcached_pass 127.0.0.1:11211;

# Send to app. server if Memcached could not answer the request
      error_page 404 502 = /cache_miss$request_uri;

   }
# Main location
  location /cache_miss/
    {
      proxy_pass http://foo.bar:8085;
      proxy_set_header Host $http_host;
      proxy_set_header X-Forwarded-Host $http_host;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }

location ~ 

^/(images|javascript|js|css|flash|media|fileadmin|typo3temp|static|uploads)/
{
proxy_pass http://foo.bar:8085;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}

server {
listen 80 default_server;
server_name _;
return 301 http://foo.bar$request_uri;
}


Jaakko P.

#2

On 27 Jan 2012 14h02 WET, removed_email_address@domain.invalid wrote:

try to fetch images, etc. behind firewall (port 8085) and also Typo3
doesn’t know how to parse the url to right place (it’s creating nice
urls. Instead of foo.bar/index.php?id=123 it uses
foo.bar/this/is/the/file.html)

I think that In order to get it work I would somehow need to be able
to set proxy_set_header Host $http_host;, but Nginx doesn’t let me
do that in if-statement (see below). I really don’t know how to
resolve this and googling around didn’t help me, so I would be
extremely happy if anybody could give me any feedback! Thanks!

For starters: http://wiki.nginx.org/IfIsEvil

— appa

#3

Antnio P. P. Almeida kirjoitti 27.1.2012 kello 16.12:

For starters: http://wiki.nginx.org/IfIsEvil

This actually solved my problem!

I changed the if statement to:

if ($request_method = POST)
{
return 418;
}

and added:

error_page 418 = @post;

location @post {
proxy_pass http://foo.bar:8085;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

Now it works flawlessly!

Thanks!


Jaakko P.

#4

27 января 2012, 18:03 от Jaakko P. removed_email_address@domain.invalid:

I think that In order to get it work I would somehow need to be able to set
proxy_set_header Host $http_host;, but Nginx doesn’t let me do that in
if-statement (see below). I really don’t know how to resolve this and googling
around didn’t help me, so I would be extremely happy if anybody could give me
any feedback! Thanks!

This should work:

location / {
if ($request_method = POST) {
rewrite ^/(.*)$ /post_redirect/$1 last;
}
}

location ~ ^/post_redirect/(.*)$ {
internal;
proxy_set_header Host $http_host;
set $proxy_url http://foo.bar:8085/$1;
if ($args) {
set $proxy_url http://foo.bar:8085/$1?$args;
}
proxy_pass $proxy_url;
}

Since rewrite is guaranteed to work without side-effects
inside if blocks, the safest approach would be to first
use rewrite inside the if block (with last) to change the
URI to an internal URI and then handle the rest inside
the internal URI location block.

Max

#5

On Saturday 28 January 2012 01:27:29 Max wrote:
[…]

location ~ ^/post_redirect/(.*)$ {
internal;
proxy_set_header Host $http_host;
set $proxy_url http://foo.bar:8085/$1;
if ($args) {
set $proxy_url http://foo.bar:8085/$1?$args;
}
proxy_pass $proxy_url;
}
[…]

proxy_pass http://foo.bar:8085/$1$is_args$args;

but, actually, this would be better:

location /post_redirect/ {
internal;
proxy_pass http://foo.bar:8085/;
proxy_redirect off;
}

wbr, Valentin V. Bartenev