nginScript是Nginx的JavaScript实现,允许在Nginx配置中使用JavaScript来扩展功能。下面我将通过几个实例来分析nginScript的使用。
nginScript是Nginx的一个模块,它: - 基于ECMAScript 5.1 (ES5)标准 - 专为Nginx配置和请求处理设计 - 在Nginx的不同处理阶段执行
js_include /etc/nginx/conf.d/rewrite.js;
server {
listen 80;
server_name example.com;
location / {
js_content rewriteExample;
}
}
rewrite.js
文件内容:
function rewriteExample(r) {
r.log("Request URI: " + r.uri);
if (r.uri === '/old-path') {
r.uri = '/new-path';
r.internalRedirect('/new-path');
} else {
r.return(200, "Hello from nginScript!");
}
}
分析:
- js_include
指令加载JavaScript文件
- js_content
指定处理请求的JavaScript函数
- r
对象代表请求对象,提供了多种方法
- 可以根据URI进行重定向或返回自定义响应
js_include /etc/nginx/conf.d/auth.js;
server {
listen 80;
server_name api.example.com;
location /secure {
js_content validateRequest;
}
}
auth.js
文件内容:
function validateRequest(r) {
var authHeader = r.headersIn['Authorization'];
if (!authHeader || authHeader !== 'Bearer valid-token') {
r.return(401, "Unauthorized");
return;
}
r.return(200, "Access granted");
}
分析: - 检查请求头中的Authorization字段 - 验证不通过返回401状态码 - 验证通过返回200状态码 - 适用于简单的API认证场景
js_include /etc/nginx/conf.d/proxy.js;
upstream backend {
server backend1.example.com;
server backend2.example.com;
}
server {
listen 80;
server_name dynamic.example.com;
location / {
js_content dynamicProxy;
}
}
proxy.js
文件内容:
function dynamicProxy(r) {
var userAgent = r.headersIn['User-Agent'];
var backend;
if (userAgent.includes('Mobile')) {
backend = 'http://mobile-backend.example.com';
} else {
backend = 'http://desktop-backend.example.com';
}
r.internalRedirect('@proxy_to_' + backend);
}
分析:
- 根据User-Agent动态选择后端服务
- 使用internalRedirect
进行内部重定向
- 可以实现基于设备类型的路由
js_include /etc/nginx/conf.d/response.js;
server {
listen 80;
server_name transform.example.com;
location / {
proxy_pass http://backend;
js_body_filter modifyResponse;
}
}
response.js
文件内容:
function modifyResponse(data, flags) {
if (!flags.last) {
return;
}
var newData = data.replace(/foo/g, 'bar');
ngx.sendBuffer(newData);
}
分析:
- js_body_filter
用于修改响应体
- 可以替换、添加或删除响应内容
- 适用于内容转换或响应修改场景
js_include /etc/nginx/conf.d/router.js;
server {
listen 80;
server_name router.example.com;
location / {
js_content routeRequest;
}
}
router.js
文件内容:
function routeRequest(r) {
var uri = r.uri;
var args = r.args;
var cookies = r.headersIn['Cookie'];
// 基于路径的路由
if (uri.startsWith('/api/v1')) {
r.internalRedirect('@api_v1');
return;
}
// 基于查询参数的路由
if (args['version'] === '2') {
r.internalRedirect('@api_v2');
return;
}
// 基于cookie的路由
if (cookies && cookies.includes('preferred_lang=en')) {
r.internalRedirect('@english_content');
return;
}
// 默认路由
r.internalRedirect('@default_backend');
}
分析: - 实现复杂的路由逻辑 - 可以基于URI、查询参数、cookie等多种条件路由 - 比纯Nginx配置更灵活
执行阶段:nginScript可以在不同阶段执行,选择合适阶段很重要
js_content
:内容生成阶段js_body_filter
:响应体过滤阶段js_header_filter
:响应头过滤阶段避免阻塞操作:nginScript是同步执行的,长时间操作会影响性能
内存使用:复杂的JavaScript逻辑可能增加内存消耗
r.log()
记录调试信息到Nginx错误日志js_var
在Nginx配置和JavaScript之间传递变量try-catch
捕获和处理异常nginScript为Nginx提供了强大的脚本能力,特别适合需要复杂逻辑但又不想开发完整Nginx模块的场景。