Proxy_pass fails after calling $r->has_request_body()

Hi, I’m trying to parse a request in a perl handler, extract a value
from it and use that to set a variable for use in a proxy_pass mapping.
GET requests work fine, but POST’s fail. I suspect that the proxy_pass
is trying re-read the request body. Is there a better way to
accomplish do this?

location ^~ /@map/ {
internal;
perl ProxyMap::handler;
}

location ^~ /@backend/ {
internal;
proxy_pass http://backend/;
}

package ProxyMap;
sub handler {
my $r = shift;
return OK if $r->has_request_body(&handle_request);
return handle_request($r);
}

this is reduced to the simplest example I could make

sub handle_request {
my $r = shift;
my $backend = ‘backend’;
my $uri = $r->uri;
$uri =~ s/@map/@$backend/;
$r->internal_redirect($uri);
return OK;
}
1;

On Thu, Dec 20, 2007 at 05:58:43AM +0100, Ben Grimm wrote:

return handle_request($r);

1;
No, proxy_pass should not read the body in this case. I will look.

Other ways:

  1. You have not to check $r->has_request_body(): you may call
    $r->internal_redirect at once.

  2. in 0.6.21+ you may use a variable in proxy_pass:

    location ^~ /@map/ {
    proxy_pass http://$backend;
    }

and set the variable using perl_set.

Igor S. wrote:

  1. in 0.6.21+ you may use a variable in proxy_pass:

    location ^~ /@map/ {
    proxy_pass http://$backend;
    }

Sorry, after paring my example down it looks really contrived. The
$backend variable on the perl side is actually set by calling another
sub which does regex matches on $r->uri, $r->args, and finally
$r->request_body to find a value. It takes the first instance it finds
and uses it as an index to a CDB_File database. The value from the CDB
is used to select the proxy.

and set the variable using perl_set.

That would work except that I can’t see how to use the perl_set
construct to read the request body (that was my first approach). When
the handler returns after calling has_request_body(), the value if the
perl_set variable is undefined and nginx wants the callback to return an
http response – not a value to stuff into a variable.

Having request_body only accessible after a callback has become a thorn
in my side :wink: It would certainly be easier if I could direct nginx to
just read the request body before it calls my code.

Thanks,
Ben