Help us understand the problem. What is going on with this article?

nginScriptで遊んでみた

More than 3 years have passed since last update.

nginxをJavaScriptで拡張できるnginScriptがローンチされたので軽く触ってみた。

https://www.nginx.com/blog/launching-nginscript-and-looking-ahead/

nginScriptをビルド

nginScriptは今のところnginx本家のMercurialリポジトリからcloneすることができる。また、nginxモジュールの実装とnginScriptの実装が一緒に含まれているため、まずはnginScriptをビルドする。

hg clone http://hg.nginx.org/njs/
cd njs
./configure
make

nginxにnginScriptを組み込んでビルド

nginScriptのビルドが完了したら今度はnginx本体のビルドを行う。configure実行時に--add-moduleでさきほどビルドしたnginScript(njs)のパスを指定してビルドする。

wget http://nginx.org/download/nginx-1.9.5.tar.gz
tar zxvf nginx-1.9.5.tar.gz
cd nginx-1.9.5
./configure --add-module=<path-to-njs>/nginx
make
sudo make install

js_setでJavaScriptの実行結果をnginxの変数に代入

js_setはJavaScriptの実行結果をnginxの内部変数に代入する。set_by_luamruby_setと違ってhttpコンテキストでしか使えないので注意。(serverlocationコンテキストでは利用不可)

http {
    js_set $var "                                                                                                                                             
        var result = 'Hello, World\n';                                                                                                                
        result                                                                                                                                                
    ";

    server {
        listen 8080;
        location /js-var {
            return 200 $var;
        }
    }
    ...

curlで叩く。

$ curl -s http://127.0.0.1:8080/js-var
Hello, World
$

js_runでJavaScriptの実行する

js_runは特定のlocationに対してJavaScriptを実行するためのフックをかけることができる。$rに内部データを突っ込んでるのがとてもPerlっぽい。

server {
    listen 8080;
    location /js-run {
        js_run "
            var res;
            res = $r.response;
            res.status = 200;
            res.sendHeader();
            res.send('Hello, World\n');
            res.finish();
        ";
    }
}

curlで叩く。

$ curl -s http://127.0.0.1:8080/js-var
Hello, World
$

nginxにはrewriteaccesscontentlogなどなどたくさんの実行フェーズがあってngx_luangx_mrubyだとそれぞれのフェーズにフックをかけてもっといろんなことができる(e.g. アップストリームにプロキシする直前にスクリプト実行してアクセス制御とか)のだが、nginScriptでは今のところフックをかけれるのはcontentフェーズのみだ。

$rからnginxの内部にアクセス

$rはJavaScriptでnginxの内部構造にアクセスするためのエンドポイントだ。今のところアクセスできるものは少ない。詳細はREADMEを見て欲しい。

server {
    listen 8080;
    location /js-r {
        js_run "
            var res;
            res = $r.response;
            res.status = 200;
            res.sendHeader();
            res.send($r.uri);
            res.send('\n');
            res.send($r.method);
            res.send('\n');
            res.send($r.remoteAddress);
            res.send('\n');
            res.finish();
        ";
    }
}

curlで叩く。

$ curl -s http://127.0.0.1:8080/js-r
/js-r
GET
127.0.0.1
$

レスポンスヘッダを操作

$r.response.headersを利用するとレスポンスヘッダを操作することができる。

$r.response.headers.Bokko = 'cubicdaiya';

なお、HTTPのヘッダは-で区切ることがよくあるが、以下のような書き方はSyntaxErrorになる。

$r.response.headers.X-Bokko = 'cubicdaiya';

ヘッダ名に-を含めたい場合は以下のように書く。

$r.response.headers['X-Bokko'] = 'cubicdaiya';

ところでngx_luaだと内部的に_-に変換してくれてとてもかしこい。

-- ngx_lua
-- 内部的に「X-Bokko: cubicdaiya」に変換される
ngx.header.X_Bokko = 'cubicdaiya';

あと、nginxのレスポンスヘッダは連結リストで表現されているので操作にかかるコストはO(n)である。
また、Content-TypeContent-Lengthは専用のアクセサが用意されている。

$r.response.headers.contentType = 'text/plain';
$r.response.headers.contentLength = 15;

まとめ

今のところnginScriptでできるのは、

  • js_setでJavaScriptの実行結果をnginxの変数に代入できる
  • js_runで特定のlocation内でJavaScriptを実行できる
  • $rからnginxの内部構造にちょっとだけアクセスできる
  • レスポンスヘッダの操作ができる

といった感じです。まだ機能少なめでearly development phaseという感じですが、リリースされたばかりですし、今後に期待ですね。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした