lua-nginx-module icon indicating copy to clipboard operation
lua-nginx-module copied to clipboard

[question] Guide to make sub-request with using variable

Open phoedos opened this issue 11 months ago • 1 comments

Service is integrated with external system which periodically send us wrong service requests. In order to reduce system overload it was written LUA block to check if request id valid or not. case1: test This test scenario works fine on test:

server {
...
    location ~ ^/request/[^/]+/rq/(?<request_id>[^/]+)$ {

    access_by_lua_block {
        local request_id = ngx.var.request_id
        local api_res = ngx.location.capture("/api_call", {
           method = ngx.HTTP_GET,
           vars = { request_id = request_id }
        })
        local api_status_code = api_res.status
        ngx.var.api_status_code = api_res.status

         -- Handle the API response
         if api_res.status == 404 then
                ngx.log(ngx.ERR, "Request not found: ", request_id)
                ngx.exit(404) -- Not Found
         end
		}
	}

    location /api_call {
         internal;
         proxy_pass http://backend:8080/api/rq/$request_id/status;
	}
...

Variable $request_id grepped as regexp location and passed to internal api call. Then, logic can be adjusted according to if condition.

case2: production In production I faced with http/2+ which is unsupported with LUA. Thus it was decicded to make a location on Prod nginx and forward requests to service nginx host. prod nginx part:

...
     location ~ ^/request/[^/]+/rq/(?<request_id>[^/]+)$ {
        proxy_pass http://internal:81;
        proxy_set_header X-Original-URI $request_uri;
        proxy_set_header X-Request-ID $request_id;
        proxy_http_version 1.1;
      }

internal host:

server {
       listen      81;
       server_name  internal;
       access_log /var/log/nginx/internal/access.log extended;
       error_log /var/log/nginx/internal/error.log;

       location / {

            access_by_lua_block {
                -- Fetch the headers
                local x_original_uri = ngx.req.get_headers()["X-Original-URI"]
                local x_request_id = ngx.req.get_headers()["X-Request-ID"]

              -- Log the headers
                if not x_original_uri or not x_request_id then
                 ngx.log(ngx.ERR, "Missing headers: X-Original-URI or X-Request-ID")
                 ngx.exit(400) -- Bad Request
                end

				local api_res = ngx.location.capture("/api_call", {
				method = ngx.HTTP_GET,
				vars = { request_id = request_id }
				})
			

			-- Handle the API response
				if api_res.status == 404 then
					ngx.log(ngx.ERR, "Request not found: ", request_id)
					ngx.exit(404) -- Not Found
				end
			}
		}

        # Proxy location for API calls
        location = /api_call {
            internal;
            proxy_pass http://backend:8080/api/rq/$x_request_id/status;
        }
}

Here I face with nginx: [emerg] unknown "x_request_id" variable. Tried to define variable as

set x_request_id '';

then config test is pass but face with errors "no such directory" in /usr/share/nginx/html/(requestid)

Is it possible to guide how to correctly pass x_request_id variable for /api_call proxy_pass for case2 ?

phoedos avatar Jan 15 '25 08:01 phoedos

I also have this scenario, and my approach is to use the headers parameter instead of the vars parameter.

dukexie avatar Aug 16 '25 03:08 dukexie