使用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が入っていて驚いた。ちょっと色付けがヘンなところがあるが…
广告
将在 10 秒后关闭
bannerAds