使用JavaScript在NGINX中动态配置nginx – njs – NGINX JavaScript
本文参与了「NGINX Advent Calendar 2018」活动。
太长不看
-
- njsとはNGINXの内部で使用可能な、JavaScriptのサブセット
-
- NGINX自体の動的な設定や拡張に利用可能なもので、Node.jsなどに置き換わるWebアプリ用ではない
- 動的なURLの書き換えやヘッダー・レスポンスの生成が可能。nginx.confの静的な設定以上のことをしたいがWebアプリを作るほどではない場合に有用
安装
如果是NGINX(开源软件),那么
如果您使用nginx.org存储库中提供的软件包安装了nginx本体,那么您需要额外安装动态模块的软件包。
您可以从nginx.org存储库中获取有关如何安装nginx本体的方法。
$ sudo yum (apt) install nginx-module-njs
如果您正在使用Linux发行版中分发的nginx,可以按以下步骤从源代码进行构建。
# njsライブラリ
cd ~/src # 任意の作業ディレクトリ
hg clone http://hg.nginx.org/njs
cd njs
./configure
make
# njsコマンド
# readline エラーが出る場合は libedit-dev パッケージを追加してみる (Ubuntu)
make njs
sudo cp build/njs /usr/local/bin
# nginx モジュール
# すでに nginx-1.15.6 パッケージがインストールされている状態で、
# ダイナミックモジュールを生成する例
cd ~/src
curl http://nginx.org/download/nginx-1.15.6.tar.gz | tar xfoz -
cd nginx-1.15.6
# ./configure --add-dynamic-module=<njsディレクトリ>/nginx \
# <nginx -V の configure オプションを全てコピー&ペースト>
# libssl-dev など、必要パッケージを適宜追加インストールしながら configure コマンドを完了させる
./configure --add-dynamic-module=../njs/nginx --prefix=/etc/nginx
--sbin-path=/usr/sbin/nginx --modules-path=/usr/lib/nginx/modules
--conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log
--http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid
--lock-path=/var/run/nginx.lock ...
make modules
sudo cp objs/ngx_*_js_module.so /usr/lib/nginx/modules
如果是NGINX Plus的情况
$ sudo yum (apt) install nginx-plus-module-njs
文档化
-
- 総合: https://nginx.org/en/docs/njs/
リファレンス: https://nginx.org/en/docs/njs/reference.html
ngx_http_js_module: https://nginx.org/en/docs/http/ngx_http_js_module.html
ngx_stream_js_module: https://nginx.org/en/docs/stream/ngx_stream_js_module.html
基础用法
-
- スクリプトはnginx.conf等の設定とは別のファイルに記述
-
- confファイルから呼び出す
- パスは /etc/nginx 相対
# mainコンテキスト
load_module modules/ngx_http_js_module.so;
http {
js_include js/hello_world.js;
server {
location /njs {
js_content hello;
}
}
}
function hello(r) {
r.headersOut['Content-Type'] = "text/plain";
r.return(200, "Hello world!\n");
}
$ curl localhost/njs
Hello world!
根据时刻改变回应的例子
function hours(r) {
var h = new Date().getHours();
r.headersOut['Content-Type'] = "text/plain";
if (h >= 9 && h <= 17) {
r.return(200, "Business hours\n");
} else {
r.return(200, "Outside hours\n");
}
}
http {
js_include js/hours.js;
server {
location /hours {
js_content hours;
}
}
}
$ curl localhost/hours
Business hours
(9-17時の場合)
一个示例是子请求。
当有一个URL请求时,会在后台作为一个子请求访问天气信息API,并返回其结果的示例。这里使用了OpenWeatherMap的Weather API作为API。
天气API:https://openweathermap.org/api
在中文中,可以这样表达: 使用”r.subquest()”方法调用子请求,并在第三个参数中注册回调函数,在回调函数中操作返回值。
function weather(r) {
r.subrequest('/weather-api',
{ method: 'GET', args: 'q=Tokyo&APPID=xxxxxxxxxxxx' },
function(res) {
if (res.status != 200) {
r.return(res.status);
return;
}
var json = JSON.parse(res.responseBody);
r.headersOut['Content-Type'] = "text/plain";
r.return(200, JSON.stringify(json, undefined, 1));
}
);
}
这些子请求似乎只能访问本地主机。我们设置了外部API作为上游,并配置了反向代理。只允许内部请求。
http {
js_include js/hours.js;
server{
location /weather {
js_content weather;
}
location /weather-api {
internal;
proxy_pass http://api.openweathermap.org/data/2.5/weather;
}
}
}
$ curl localhost/weather
{
"coord": {
"lon": 139.76,
"lat": 35.68
},
"base": "stations",
"wind": {
"speed": 6.2,
"deg": 330,
"gust": 12.9
},
"name": "Tokyo",
"visibility": 10000,
"dt": 1544749200,
"clouds": {
"all": 20
},
"id": 1850147,
"sys": {
"type": 1,
"id": 8077,
"message": 0.0051,
"country": "JP",
"sunrise": 1544737340,
"sunset": 1544772509
},
"weather": [
{
"id": 801,
"main": "Clouds",
"description": "few clouds",
"icon": "02d"
}
],
"cod": 200,
"main": {
"temp": 281.84,
"pressure": 1020,
"humidity": 36,
"temp_min": 281.15,
"temp_max": 282.15
}
}
命令行工具
有一个名为njs的命令行工具,非常方便进行调试和验证操作。
$ njs
interactive njs 0.2.6
v.<Tab> -> the properties and prototype methods of v.
type console.help() for more information
>> var d=new Date().getHours()
undefined
>> d
10
我喜欢的方面
-
- nginxの設定を動的に変えられる
-
- JavaScriptなので取っ付きやすい
- 今の所仕様が小さいので覚えられる
请注意
-
- jsファイルの変更は、nginx -s reload しないと反映されない
-
- js_include は1行しか書けない
-
- r.subrequest() は localhost しかアクセスできない
- require() で外部ファイルを読み込めない
附带一提
- シンタックスハイライト可能な言語にnginxが入っていて驚いた。ちょっと色付けがヘンなところがあるが…