Nginx/njs API KEY验证问题:js_content冲突与subrequest传参异常
问题解答
问题1 同一location中js_content与proxy_pass同时配置时proxy_pass始终执行的原因
- 根本原因是Nginx采用多阶段请求处理模型,
js_content和proxy_pass都属于content阶段的内容处理指令,同一location块下的多个content阶段指令并不会按配置顺序做分支判断执行。js_content对应的njs函数执行时,如果你没有显式调用r.return()、r.internalRedirect()这类方法主动结束当前请求的响应流程,Nginx会认为当前内容处理器未完成响应生成,就会继续执行后续配置的proxy_pass逻辑,哪怕你在js代码中已经设置了401状态码也不会中断。 - 和“location块中if指令是邪恶的”根源不完全一致:两者底层都是基于Nginx的阶段处理模型,不是像普通脚本一样逐行顺序执行、支持分支中断,但if指令的问题本质是rewrite阶段的指令执行逻辑问题,和content阶段的handler执行逻辑的直接原因不同。
问题2 r.subrequest无法传递POST请求方法的原因与修复方案
- 问题原因:njs的
r.subrequest默认使用GET方法发起子请求,且默认不会主动传递原请求的请求方法、请求体、请求头等信息。你注释的代码里只传入了r.variables作为第二个参数,没有指定请求方法和请求体,所以后端收到的都是GET请求,自然报错不支持GET方法。 - 修复方案:
- 首先在nginx.conf的http块或者对应server块添加配置开启请求体读取:
js_request_body on;,否则njs无法获取到POST请求的请求体内容。 - 修改subrequest的调用参数,显式指定请求方法、请求体、请求头,示例代码如下:
r.subrequest('/internalProxyPassToBackend', { method: r.method, body: r.requestBody, headers: r.headersIn }, function(reply) { // 同步后端返回的响应头给客户端 r.headersOut = reply.headersOut; r.return(reply.status, reply.responseBody); }); - 首先在nginx.conf的http块或者对应server块添加配置开启请求体读取:
内容的提问来源于stack exchange,提问作者Pierre
相关产品推荐
相关产品推荐

