nginx Tips: Modifying Response Body, Cookies, and Redirects

Common nginx + Lua Configuration Techniques

  1. Routing Requests to a Specific URL The following configuration forwards incoming requests to a backend service running on a different host and port:
location /api/auth/login {
    proxy_pass http://backend-server:30900/api/auth/login;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

  1. Forwarding Cookies and Rewriting Cookie Path When a backend service returns a Cookie with a subdirectory path (e.g., /usermanager), the frontend application cannot read it. This example rewrites the cookie path to the root directory:
location /userportal/login {
    proxy_pass http://user-service:7200/userportal/login;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    
    header_filter_by_lua_block {
        local response_cookies = ngx.resp.get_headers()["Set-Cookie"]
        
        if response_cookies then
            if type(response_cookies) == "string" then
                local rewritten = string.gsub(response_cookies, "Path=/userportal", "Path=/")
                ngx.header["Set-Cookie"] = rewritten
                return
            end
            
            for index, cookie_value in ipairs(response_cookies) do
                response_cookies[index] = string.gsub(cookie_value, "Path=/userportal", "Path=/")
            end
            ngx.header["Set-Cookie"] = response_cookies
        end
    }
}

  1. Modifying Response Body to Replace Internal URLs Some backend endpoints (such as OAuth redirect callbacks) return internal URLs that are not accessible from outside the network. This configuration intercepts the response and replaces internal hostnames with public-facing addresses:
location /api/oauth/token {
    proxy_pass http://auth-service:30900/api/oauth/token;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_read_timeout 360;
    proxy_buffering off;
    
    body_filter_by_lua_block {
        local chunk_data, end_of_file = ngx.arg[1], ngx.arg[2]
        local context = ngx.ctx
        
        if not context.payload then
            context.payload = ""
        end
        context.payload = context.payload .. chunk_data
        ngx.arg[1] = nil
        
        if end_of_file then
            local json_parser = require "cjson"
            local parse_success, json_data = pcall(json_parser.decode, context.payload)
            
            if not parse_success then
                return
            end
            
            if json_data.status == "302" and type(json_data.message) == "string" then
                ngx.log(ngx.ERR, "Original URL: ", json_data.message)
                local external_url = string.gsub(json_data.message, "http://[^/]+", "http://public-host:28080")
                json_data.message = external_url
                
                ngx.log(ngx.ERR, "Transformed URL: ", json_data.message)
                local modified_response = json_parser.encode(json_data)
                ngx.arg[1] = modified_response
            else
                ngx.arg[1] = context.payload
            end
        end
    }
}

  1. Selectiev URL Redirection This configuration redirects specific frontend resource requests to a unified prefix path, ensuring compatibility between internal and external access patterns:
location / {
    rewrite_by_lua_block {
        local request_path = ngx.var.uri
        if request_path:match("^/asr/bundle.js") or request_path:match("^/favicon.ico") then
            ngx.req.set_uri("/gateway" .. request_path)
        end
    }
    
    proxy_pass http://backend-server:30900/;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_read_timeout 360;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "Upgrade";
}

These techniques leverage nginx's integration with Lua to perform dynamic request and response modifications without requiring changes to the backend application code.

Posted on Sat, 20 Jun 2026 17:35:01 +0000 by Tbull