Skip to content

Instantly share code, notes, and snippets.

@4141done
Last active February 23, 2023 17:39
Show Gist options
  • Save 4141done/e23c52cd9803b366212dfcc2226c12d6 to your computer and use it in GitHub Desktop.
Save 4141done/e23c52cd9803b366212dfcc2226c12d6 to your computer and use it in GitHub Desktop.
Example of choosing an upstream based on request body and proxying with subrequest
#user nobody;
worker_processes 1;
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid logs/nginx.pid;
load_module modules/ngx_http_js_module.so;
error_log /tmp/dev.log debug;
events {
worker_connections 1024;
}
http {
js_import script from script.js;
include mime.types;
default_type application/json;
js_var $machine;
js_var $nodename;
js_var $redirectKey;
log_format my_custom_log_format ‘$machine - $nodename’;
server {
listen 4000;
access_log /tmp/nginx-access.log my_custom_log_format;
location /foo {
js_content script.handleRequest;
}
location /upstream_one {
js_content script.upstreamOne;
}
location /upstream_two {
return 200 "this is upstream two";
}
}
}
async function handleRequest (r) {
// Since this handler is invoked with `js_content`, r.requestText
// is guaranteed to be present
const body = r.requestText;
// some logic to process the body
// the below variable is a stand-in for the result of that
// processing
const parsedRequestBody = {
machine: "the machine",
nodename: "the nodename",
redirectKey: "upstream_one" // change this to see different upstreams
};
for (const key in parsedRequestBody) {
r.variables[key] = parsedRequestBody[key];
}
// Here's the redirect. r.subrequest mirrors the headers
// and body of the parent response to the target of the subrequest
let upstreamResponse;
if (parsedRequestBody.redirectKey === "upstream_one") {
upstreamResponse = await r.subrequest("/upstream_one");
} else {
upstreamResponse = await r.subrequest("/upstream_two");
}
// The following code passes the response from the upstream back including
// status, body, and headers
// Doing this makes sure headers added in the upstream get passed back
r.headersOut = Object.assign(r.headersOut, upstreamResponse.headersOut);
// Mirror the upstream response status and body
r.return(upstreamResponse.status, upstreamResponse.responseText);
}
// Just adding this as a njs handler so we can easily see what the upstream
// will receive in terms of body and headers
function upstreamOne(r) {
r.error(`headers received in upstream_one: ${JSON.stringify(r.rawHeadersIn)}`);
r.error(`body received in upstream_one: ${r.requestText}`);
r.headersOut['upstream-one-added'] = "Upstream one added this header";
r.return(200, "This is the body of the response from upstream_one");
}
export default { handleRequest, upstreamOne };
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment