Nginx njs scripting, API服务的简单实现

njs scripting 是什么?

njs是JavaScript语言的子集,它允许扩展nginx功能。njs的创建符合 ECMAScript 5.1 (严格模式)以及某些 ECMAScript 6 和更高版本的扩展。合规性还在不断发展。 简单说就是在nginx内使用JavaScript编写简单的服务端程序。

为什么要选择使用njs scripting

  • njs scripting的优点
  1. 使用js开发,开发简单。便于快速开发
  2. 部署容易,有个nginx就可以,不需要部署其他东西,对server的性能要求很低, 也容易和其他服务共存。
  3. 在API层面可以保持稳定,以后转成其他实现,也不会影响前端。

njs scripting适用于在项目初期需要一些服务端的功能,但是只希望有一个简单实现,能快速开发部署,对其他发面没什么要求。但是希望API保持稳定,不希望以后升级服务端的时候前端也要跟着改。

njs scripting 实例

通过一个简单实例来体验njs scripting。这个实例的api如下: http://xxx.xxx.xxx/fetch_data?offset=?&limit=? 从服务器获取数据,offset是开始的位置,limit是一次获取的数量, 在列表页面或者瀑布流页面常常需要类似的api进行展示。一般的实现是数据放在数据库中,通过SQL获取数据,然后发送给前端进行展示。一般需要一个应用服务器还有数据库来做,这在有些项目中是没必要的,开发部署都显得过于复杂。

环境安装配置

我是在ubuntu下安装的, 直接用apt-get安装

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
Add the following line to /etc/apt/sources.list:
deb https://nginx.org/packages/ubuntu/ focal nginx
Install GPG key of the repository:

# wget https://nginx.org/keys/nginx_signing.key
# sudo apt-key add nginx_signing.key
Update the package index:
# sudo apt-get update
Install nginx-module-njs deb package:
# sudo apt-get install nginx-module-njs

nginx的配置文件如下

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
js_import /path/to/jsfile.js;   //你的JS文件的路径
server {
    server_name xxxx.com;
    access_log /var/log/nginx/xxxx.com.access.log;
    error_log /var/log/nginx/xxxx.com.error.log info; //使用 info 级别 可以打出log,便于开发中的调试
    root /path/to/your/html;

    location /xxxxx {
        add_header  Content-Type 'application/json';
        js_content jsfile.your_func_name;
    }
}

JS文件

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
function your_func_name(r) {
  var offset = 0; //default offset
  var limit = 20; //default limit

  // r.log('r.args.offset=' + r.args.offset);
  if(Number.isInteger(+r.args.offset)) {
    offset = parseInt(r.args.offset);
  }
  r.log('offset=' + offset);

  // r.log('r.args.limit=' + r.args.limit);
  if(Number.isInteger(+r.args.limit)) {
    limit = parseInt(r.args.limit);
  }
  r.log('limit=' + limit);

  var fs = require('fs').promises;
  fs.readFile("/path/data.json").
    then((data) => {
      var json = JSON.parse(data.toString());
      var output = [];
      for (var i = offset; (i < json.length) && (i < offset + limit); i++) {
        r.log('i=' + i);
        output.push(json[i]);
      }
      r.return(200, JSON.stringify(output));
    }).catch((error) => r.return(400, error));
}

export default { your_func_name };
  1. r.args中可以获取request中的参数,比如r.args.offset可以获取 request (http://xxx.com/api_name?offset=1) 中 offset参数的值
  2. r.log可以输出log,log会输出到 nginx中设置的文件中, 注意log级别. error_log /var/log/nginx/xxxx.com.error.log info; //使用 info 级别 可以打出log,便于开发中的调试
  3. r.return可以返回结果
  4. 实例中的数据保存在一个json文件中,api通过offset,limit输出其中的一部分。
  5. 修改JS文件后,需要重启nginx才会生效。

data.json

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
    [
        {
            "a": "v1",
            "b": "v2",
            "c": "v3"
        },
        {
            "a": "v1",
            "b": "v2",
            "c": "v3"
        },
        {
            "a": "v1",
            "b": "v2",
            "c": "v3"
        }
    ]
记录并分享
Built with Hugo
主题 StackJimmy 设计