老夫万万没想到,几年前无意间学了 NJS ,最近竟然用上了。

是的你没看错,如果你会写javascript,你甚至已经是一名Nginx配置管理员。

今天我们就通过一个例子,带大家初步浅入门 NJS

什么是 NJS

前置知识:

  1. 一点点 nginx.conf 的认识
  2. javascript基本语法
  3. 其他作为程序员的基本素质

0x00 场景介绍(纯杜撰)

案件的经过是这样的,最近有一个新的后端项目,希望接入到我们已有的微服务集群里。

然后我好像明白了一些事情:

Python 开发效率第一条:不做复杂的事情。

不过既然阿刚硬刚,恰好我有解决的方案,就不妨接受挑战吧。

首先梳理一下原始需求:

  1. 真实的业务接口部署在我们的集群里
  2. 真实的业务接口需要做用户鉴权,如:判断用户是否登录
  3. 真实的业务接口不希望请求外部接口,希望网关放进来的都是已经登录的

如果做到了以上三点,他们确实可以很轻松,这理由很“充分”。

所以我指定了这个方案:

好了交代完背景我们进入很干的正题

NJS 真是一个好东西,我们平时看到的 Nginx.conf,最多就做做反向代理、负载均衡。

现在告诉你,通过 javascript 还能给Nginx赋能一些逻辑,一众 JSer自然是很兴奋。

🤡 Nginx 高手竟在我身边。

那么我们看看怎么做:

// auth.js
function auth(r) {
	r.subrequest('/auth') // 假设我们原本需要调用这个接口来检查登录
	  .then((reply) => {
	      if (reply.status !== 200) {
	        throw '未登录';
	      }
	  }).then(() => {
	    	r.subrequest(r.uri, {})
	    	// 隐去了一些不必要的细节
	  }).catch(e => {
	  	r.return(401, e);
	  });
}

export default { auth };

直接贴代码,我觉得我也很刚。

上面这段简单的 JS 代码,相信大家也能看明白的大概。

意思就是,当请求进来时,首先去内部请求一下 /auth 接口;

如果返回的不是200,就告诉前端 401 未登录

否则,再发起内部请求到真实业务接口 r.uri,得到真正的业务接口返回数据。

编写完JS逻辑,这事还没完,需要在 Nginx.conf 里增加点东西

// nginx.conf (只贴关键内容)
# 配置文件开头:载入 NJS 模块
load_module modules/ngx_http_js_module.so;  
...
...
http {
  # 通过 js_import 引入上面的JS代码
  js_import main from auth.js;
  ...
  ...
  server {
    ...
    ...
  location ~ ^/ {
    # 所有请求都通过上面的JS代码来处理了
    js_content main.auth; 
  }

🔥🔥🔥因为上面的分解动作,都是在 Nginx 内部转发完成的,所以在前端的感受上就只是发生了一次简单的请求。

而对于躲在背后的业务接口来说,

开发接口的时候不需要关心用户鉴权,直接裸奔上阵。

🤡当然是皆大欢喜的事情,很简单是不是?