配置示例

HTTP 请求

js_import http from http.js;

server {
    listen 8000;

    location / {
        js_content http.hello;
    }
}
function hello(r) {
    r.return(200, "Hello world!\n");
}

export default { hello };

HTTP 请求说明

  • js_import http from http.js:导入 njs 脚本
  • js_content http.hello:使用 njs 脚本处理请求
  • function hello(r):定义一个函数,处理 HTTP 请求
  • r.return(200, "Hello world!\n"):返回响应
  • export default { hello }:导出函数

HTTP 请求原理js_import 指令用于导入 njs 脚本,js_content 指令用于使用 njs 脚本处理请求。hello 函数用于处理 HTTP 请求,r 参数是 HTTP 请求对象,可以使用 r.return() 返回响应。

访问控制

js_import http from http.js;

server {
    listen 8000;

    location / {
        js_content http.access;
    }
}
function access(r) {
    if (r.args.token != 'secret') {
        r.return(401);
    }
}

export default { access };

访问控制说明

  • js_import http from http.js:导入 njs 脚本
  • js_content http.access:使用 njs 脚本处理请求
  • function access(r):定义一个函数,处理 HTTP 请求
  • r.args.token != 'secret':检查请求参数
  • r.return(401):返回 401 响应
  • export default { access }:导出函数

访问控制原理access 函数用于处理 HTTP 请求,r 参数是 HTTP 请求对象,可以使用 r.args.token 访问请求参数。如果请求参数不等于 secret,返回 401 响应。

请求头修改

js_import http from http.js;

server {
    listen 8000;

    location / {
        js_set $res http.headers;
        add_header X-Response $res;
        proxy_pass http://backend;
    }
}
function headers(r) {
    return JSON.stringify(r.headersOut);
}

export default { headers };

请求头修改说明

  • js_set $res http.headers:设置变量
  • add_header X-Response $res:添加响应头
  • function headers(r):定义一个函数,处理 HTTP 请求
  • JSON.stringify(r.headersOut):序列化响应头
  • export default { headers }:导出函数

请求头修改原理js_set 指令用于设置变量,headers 函数用于处理 HTTP 请求,r 参数是 HTTP 请求对象,可以使用 r.headersOut 访问响应头。

响应体修改

js_import http from http.js;

server {
    listen 8000;

    location / {
        js_body_filter http.lower;
        proxy_pass http://backend;
    }
}
function lower(s, chunk) {
    return chunk.toLowerCase();
}

export default { lower };

响应体修改说明

  • js_body_filter http.lower:使用 njs 脚本过滤响应体
  • function lower(s, chunk):定义一个函数,过滤响应体
  • chunk.toLowerCase():将响应体转换为小写
  • export default { lower }:导出函数

响应体修改原理js_body_filter 指令用于使用 njs 脚本过滤响应体,lower 函数用于过滤响应体,s 参数是流对象,chunk 参数是响应体块。

性能优化

  • 避免在脚本中使用循环:避免在脚本中使用循环,因为循环会影响性能
  • 缓存计算结果:缓存计算结果,避免重复计算
  • 使用同步 API:使用同步 API,避免异步 API

性能优化原理: njs 脚本在 Nginx 中执行,会影响 Nginx 的性能。避免在脚本中使用循环,因为循环会影响性能。缓存计算结果,避免重复计算,可以提高性能。使用同步 API,避免异步 API,因为异步 API 会影响性能。

错误处理

function foo(r) {
    try {
        var result = r.subrequest('/auth');
        var response = JSON.parse(result.responseText);
        r.return(200, response);
    } catch (e) {
        r.return(500, "internal error");
    }
}

错误处理说明

  • try { ... } catch (e) { ... }:捕获异常
  • r.subrequest('/auth'):发送子请求
  • JSON.parse(result.responseText):解析响应体
  • r.return(200, response):返回响应
  • r.return(500, "internal error"):返回错误响应

错误处理原理: 使用 try { ... } catch (e) { ... } 捕获异常,避免脚本错误。使用 r.subrequest() 发送子请求,使用 JSON.parse() 解析响应体。如果发生异常,返回错误响应。

日志记录

function foo(r) {
    r.log("foo");
    r.return(200, "OK");
}

日志记录说明

  • r.log("foo"):记录日志
  • r.return(200, "OK"):返回响应

日志记录原理: 使用 r.log() 记录日志,便于故障排查。

注意事项

  • 脚本文件路径正确:确保脚本文件路径正确,避免脚本加载失败
  • 函数导出正确:确保函数导出正确,避免脚本执行失败
  • 避免使用全局变量:避免使用全局变量,因为全局变量会影响脚本的执行
  • 定期更新 njs 版本:定期更新 njs 版本,获取最新的功能和修复

最佳实践

  1. 避免在脚本中使用循环:避免在脚本中使用循环,因为循环会影响性能
  2. 缓存计算结果:缓存计算结果,避免重复计算
  3. 使用同步 API:使用同步 API,避免异步 API
  4. 使用错误处理:使用错误处理,避免脚本错误
  5. 使用日志记录:使用日志记录,便于故障排查
  6. 确保脚本文件路径正确:确保脚本文件路径正确,避免脚本加载失败
  7. 确保函数导出正确:确保函数导出正确,避免脚本执行失败
  8. 避免使用全局变量:避免使用全局变量,因为全局变量会影响脚本的执行
  9. 定期更新 njs 版本:定期更新 njs 版本,获取最新的功能和修复
  10. 监控脚本性能:监控脚本性能,及时发现异常