如何让Nginx根据静态JSON内容返回对应状态码?
Got it, let's solve this. Right now your Nginx config serves a static /etc/health.json file at /health with a default 200 OK status, but you want to map the status value in that JSON to a matching HTTP status code. Below are two practical solutions depending on your setup:
Option 1: Use Nginx's Native JS Module (ngx_http_js_module)
This works if your Nginx version is 1.15.8 or newer and was compiled with the --with-http_js_module flag (verify with nginx -V). No extra dependencies needed.
Step 1: Update Your Nginx Config
Replace your existing /health location block with this:
location /health { default_type "application/json"; js_content health_check; } # Point to our custom JS script js_include health.js;
Step 2: Create the Health Check Script
In your Nginx config directory (usually /etc/nginx/), create a file named health.js with this code:
function health_check(r) { // Read the static JSON file const fs = require('fs'); const healthContent = fs.readFileSync('/etc/health.json', 'utf8'); const healthData = JSON.parse(healthContent); // Map JSON status to HTTP status codes switch (healthData.status) { case 'up': r.status = 200; // OK break; case 'down': r.status = 503; // Service Unavailable break; case 'maintenance': r.status = 503; // Add custom mappings here as needed break; default: r.status = 400; // Bad Request for unknown statuses } // Send the JSON content to the client r.sendHeader(); r.send(healthContent); r.finish(); }
Step 3: Reload Nginx
Make the changes take effect with:
sudo nginx -s reload
Option 2: Use OpenResty's Lua Module (ngx_http_lua_module)
If you're already using OpenResty (a Nginx distribution with Lua support), this is a lightweight, flexible option.
Update Your Nginx Config
Replace your /health location block with this:
location /health { default_type "application/json"; content_by_lua_block { -- Read the static JSON file local file_handle = io.open("/etc/health.json", "r") local json_content = file_handle:read("*a") file_handle:close() -- Parse JSON using OpenResty's built-in cjson local health_status = require("cjson").decode(json_content) -- Set HTTP status based on JSON value if health_status.status == "up" then ngx.status = ngx.HTTP_OK elseif health_status.status == "down" then ngx.status = ngx.HTTP_SERVICE_UNAVAILABLE else ngx.status = ngx.HTTP_BAD_REQUEST end -- Send the original JSON content ngx.say(json_content) } }
Reload OpenResty
Apply the config change:
sudo openresty -s reload
Quick Notes
- If your
health.jsoncontent never changes, you can skip scripting entirely: just addreturn 200;to your original location block if it's alwaysup. Use the script solutions only if the JSON content might dynamically switch between statuses. - Make sure the Nginx/OpenResty process has read permissions for
/etc/health.json(runsudo chmod 644 /etc/health.jsonif needed). - Feel free to adjust the status code mappings to fit your use case (e.g., return 206 for a
degradedstatus).
内容的提问来源于stack exchange,提问作者Bara' ayyash

