问题
I am building an application where I need to do some analytics on the api-data combination usage. Below is my nginx configuration -
location /r/ {
rewrite /r/(.*)$ http://localhost:3000/sample/route1/$1 redirect;
post_action /aftersampleroute1/$1;
}
location /aftersampleroute1/ {
rewrite /aftersampleroute1/(.*) /stats/$1;
proxy_pass http://127.0.0.1:3000;
}
location /r/
is used to redirect the browser request http://localhost:80/r/quwjDP4us
to api /sample/route1/quwjDP4us
which uses the id quwjDP4us
to do something.
Now in the background I want to pass the id quwjDP4us
to an stats api /stats/quwjDP4us
which updates the db record for that id.
When I start nginx and make the request http://localhost:80/r/quwjDP4us
nginx successfully redirects my request to my application but doesn't make the 2nd request in the background to the stats api. What am I missing?
Note - post_action
is not included in nginx docs, is there an alternate module/directive I can use?
回答1:
As you correctly mentioned, post_action
is not documented and has always been considered an unofficial directive.
Nginx provides a new "mirror" module since version 1.13.4, described here in the documentation. So I advise you to give it a try. In your case, it would look like this –
location /r/ {
rewrite /r/(.*)$ http://localhost:3000/sample/route1/$1 redirect;
mirror /stats;
}
location = /stats {
internal;
rewrite /sample/route1/(.*) /stats/$1;
proxy_pass http://127.0.0.1:3000;
}
This will not work!
I've built a test configuration and unfortunately this will not work. It works for neither rewrite
nor return
. But it works for proxy_pass
.
Why
The explanation follows. A HTTP request sequentially passes few "phases" during processing in Nginx. The thing is that mirror
gets triggered in phase PRECONNECT
which occurs later than phase REWRITE
where rewrite
/return
end request processing. So, mirror
does not even get triggered because its processing would happen later.
In case of serving files from the location or proxying via proxy_pass
(or fastcgi_pass
, etc), the processing will finally reach REWRITE
phase and mirror
will be executed.
Phases are described in Nginx documentation here.
Workarounds
I do not see any good solution without trade-offs. You could create an extra location (returning a redirect) and proxy your request from /r/
, so that mirror
gets triggered. Something like this, depending on the rest of your configuration:
location /r/ {
# you may need setting Host to match `server_name` to make sure the
# request will be caught by this `server`.
# proxy_set_header Host $server_name;
proxy_pass http://<ip from listen>:<port from listen>/redirect/;
mirror /stats;
}
location = /redirect {
rewrite /redirect(.*)$ http://localhost:3000/sample/route1$1 redirect;
}
Certainly this is suboptimal and has extra boilerplate.
来源:https://stackoverflow.com/questions/52603090/configure-nginx-to-make-a-background-request