Use the ngx.location.capture() method to perform a subrequest to a predefined location block. Then, from within the location block, perform the external, FastCGI request. Because the subrequest itself isn't actually a network operation, but is performed purely within nginx C-based environment, there's very little overhead. Further, because the FastCGI request and other "proxy_pass"-type requests are event-based, nginx can operate as an efficient intermediary.
As an example, you could have the following:
location / {
access_by_lua '
response = ngx.location.capture("/my-subrequest-handler")
if response.status == 404 then
return ngx.exit(401) -- can't find/authenticate user, refuse request
end
ngx.say(response.status)
';
# other nginx config stuff here as necessary--perhaps another fastcgi_pass
# depending upon the status code of the response above...
}
location = /my-subrequest-handler {
internal; # this location block can only be seen by nginx subrequests
fastcgi_pass localhost:9000; # or some named "upstream"
fastcgi_pass_request_body off; # send client request body upstream?
fastcgi_pass_request_headers off; # send client request headers upstream?
fastcgi_connect_timeout 100ms; # optional; control backend timeouts
fastcgi_send_timeout 100ms; # same
fastcgi_read_timeout 100ms; # same
fastcgi_keep_conn on; # keep request alive
include fastcgi_params;
}
In the above example, even though I'm performing a subrequest to "/my-subrequest-handler", the actual URL passed to the FastCGI process is the one requested by the HTTP client calling into nginx in the first place.
Note that that ngx.location.capture is a synchronous, but non-blocking operation which means that your code execution stops until a response is received, but the nginx worker is free to perform other operations in the meantime.
There are some really cool things that you can do with Lua to modify the request and response at any point in the nginx pipeline. For example, you could change the original request by adding headers, removing headers, even transforming the body. Perhaps the caller wants to work with XML, but the upstream application only understands JSON, we can convert to/from JSON when calling the upstream application.
Lua is not built into nginx by default. Instead it's a 3rd party module that must be compiled in. There's a flavor of nginx called OpenResty that builds in Lua+LuaJIT along with a few other modules that you may or may not need.