POST subrequest body doesn't get passed to fastcgi #8

Closed
edo888 opened this Issue Feb 26, 2012 · 4 comments

Projects

None yet

2 participants

@edo888
edo888 commented Feb 26, 2012

Hi,

Here is my config

location /hello {
default_type text/plain;
echo_subrequest POST '/test' -q 'foo=Foo&bar=baz' -b 'request_body=test&test=3';
}

location /test {
# default example works
#echo "querystring: $query_string";
#echo "method: $echo_request_method";
#echo "body: $echo_request_body";
#echo "content length: $http_content_length";
#echo '///';

fastcgi_pass   127.0.0.1:1234;
include        fastcgi_params;
fastcgi_param  SCRIPT_FILENAME  /root/test.php;

#deny all;

}

In test.php file I have this:

On echo $HTTP_RAW_POST_DATA; ?>

When I make a request with the default example I can see

curl 'http://localhost/hello'
querystring: foo=Foo&bar=baz
method: POST
body: request_body=test&test=3
content length: 24
///

When I make the same request with fastcgi I can see

curl 'http://localhost/hello'
Array
(
[foo] => Foo
[bar] => baz
)
Array
(
)

So, as you can see GET params are passed. No request_body or POST params though.

I expect it to output:
Array
(
[foo] => Foo
[bar] => baz
)
Array
(
[request_body] => test
[test] => 3
)
request_body=test&test=3

Is this a bug or it is by design?

I'm using v0.37 which comes with nginx 1.1.13.

@agentzh
Member
agentzh commented Feb 27, 2012

There's no bug in ngx_echo nor ngx_fastcgi. Your config has two problems:

  1. You should set the "Content-Type: application/x-www-form-urlencoded" request header for your POST subrequest, or the PHP _POST table will just ignore the request body altogether. So your /hello location should be fixed as follows:

    location /hello {
    default_type text/plain;

    more_set_input_headers
            'Content-Type: application/x-www-form-urlencoded';
    
    echo_subrequest POST '/test' -q 'foo=Foo&bar=baz'
            -b 'request_body=test&test=3';
    

    }

Here we use the more_set_input_headers directive provided by the

ngx_headers_more module to set the request header. (see http://wiki.nginx.org/HttpHeadersMoreModule)

  1. There is a bug in the "fastcgi_params" config file shipped by the standard Nginx distribution which always passes the ''main'' request's request method (i.e., "GET" in your example) to the FastCGI backend rather than the current (sub)request (i.e., "POST" in your sample). The offensive line is

    fastcgi_param REQUEST_METHOD $request_method;

This line should be fixed as following

 fastcgi_param  REQUEST_METHOD     $echo_request_method;

That is, using the $echo_request_method variable provided by the ngx_echo module (see
http://wiki.nginx.org/HttpEchoModule#.24echo_request_method )

After fixing the two issues discussed above, your example works as expected on my side:

Array
(
    [foo] => Foo
    [bar] => baz
)
Array
(
    [request_body] => test
    [test] => 3
)

If you have any further questions, please let me know :)

Best regards,
-agentzh

@edo888
edo888 commented Feb 27, 2012

OK, thanks, I've already got that and set fastcgi_param REQUEST_METHOD POST;

I was reading your echo module source code to understand how to make a post subrequest and didn't find the tail of how you pass the request body to the subrequest.

In my module's body filter I do this:

if(ngx_http_subrequest(r, &uri, &query_string, &sr, NULL, 0) != NGX_OK)
return NGX_ERROR;

// adjust subrequest
ngx_str_t method_name = ngx_string("POST");
sr->method = NGX_HTTP_POST;
sr->method_name = method_name;

Then I don't understand how should I pass the request body. I have tried populating sr->request_body->bufs with sample chain with dummy buffs, but it doesn't seem to get passed to the subrequest.

Am I right that if I populate sr->request_body->bufs they will be written to subrequest request body?

Thanks in advance.

@agentzh
Member
agentzh commented Feb 27, 2012

On Mon, Feb 27, 2012 at 10:19 PM, edo888
reply@reply.github.com
wrote:

Then I don't understand how should I pass the request body. I have tried populating sr->request_body->bufs with sample chain with dummy buffs, but it doesn't seem to get passed to the subrequest.

I think you should also set the Content-Length request header
(including r->headers_in->content_length_n).

Regards,
-agentzh

@edo888
edo888 commented Feb 27, 2012

WOW, super, thanks a lot!!! I was struggling about this a lot.

@agentzh agentzh closed this Oct 12, 2013
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment