Skip to content

Commit 1a5f5f4

Browse files
committed
[add] http/async_var/auth_request example
1 parent 07db6a2 commit 1a5f5f4

File tree

3 files changed

+176
-0
lines changed

3 files changed

+176
-0
lines changed

‎README.rst

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,113 @@ Checking:
9898
curl http://localhost/version
9999
0.4.1
100100
101+
Setting nginx var as a result of async operation
102+
------------------------------------------------
103+
`js_set <https://nginx.org/en/docs/http/ngx_http_js_module.html#js_set>`_ handler
104+
does not support asynchronous operation (r.subrequest(), ngx.fetch()) because it is
105+
invoked in a synchronous context by nginx and is expected to return its result
106+
right away. Fortunately there are ways to overcome this limitation using other
107+
nginx modules.
108+
109+
Using auth_request [http/async_var/auth_request]
110+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
111+
112+
In simple cases `auth_request <http://nginx.org/en/docs/http/ngx_http_auth_request_module.html>`_
113+
is enough and njs is not required.
114+
115+
Simple case criteria:
116+
- request body is not needed to be forwarded
117+
- external service returns the desired value extractable as an nginx variable (for example as a response header)
118+
119+
The following example illustrates this use case using njs ONLY as a fake service.
120+
$backend variable is populated by auth_request module from a response header of a subrequest.
121+
122+
nginx.conf:
123+
124+
.. code-block:: nginx
125+
126+
...
127+
128+
http {
129+
js_path "/etc/nginx/njs/";
130+
131+
js_import main from http/async_var/auth_request.js;
132+
133+
server {
134+
listen 80;
135+
136+
location /secure/ {
137+
auth_request /fetch_upstream;
138+
auth_request_set $backend $upstream_http_x_backend;
139+
140+
proxy_pass http://$backend;
141+
}
142+
143+
location /fetch_upstream {
144+
internal;
145+
146+
proxy_pass http://127.0.0.1:8079;
147+
proxy_pass_request_body off;
148+
proxy_set_header Content-Length "";
149+
proxy_set_header X-Original-URI $request_uri;
150+
}
151+
}
152+
153+
server {
154+
listen 127.0.0.1:8079;
155+
156+
location / {
157+
js_content main.choose_upstream;
158+
}
159+
}
160+
161+
server {
162+
listen 127.0.0.1:8081;
163+
return 200 "BACKEND A:$uri\n";
164+
}
165+
166+
server {
167+
listen 127.0.0.1:8082;
168+
return 200 "BACKEND B:$uri\n";
169+
}
170+
}
171+
172+
example.js:
173+
174+
.. code-block:: js
175+
import qs from "querystring";
176+
177+
function choose_upstream(r) {
178+
let backend;
179+
let args = qs.parse(r.headersIn['X-Original-URI'].split('?')[1]);
180+
181+
switch (args.token) {
182+
case 'A':
183+
backend = '127.0.0.1:8081';
184+
break;
185+
case 'B':
186+
backend = '127.0.0.1:8082';
187+
break;
188+
default:
189+
r.return(404);
190+
}
191+
192+
r.headersOut['X-backend'] = backend;
193+
r.return(200);
194+
}
195+
196+
export default {choose_upstream}
197+
198+
Checking:
199+
200+
.. code-block:: shell
201+
202+
curl http://localhost/secure/abc?token=A
203+
BACKEND A:/secure/abc
204+
205+
curl http://localhost/secure/abcde?token=B
206+
BACKEND B:/secure/abcde
207+
101208
Authorization
102209
-------------
103210

‎conf/http/async_var/auth_request.conf

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
load_module modules/ngx_http_js_module.so;
2+
3+
events { }
4+
5+
http {
6+
js_path "/etc/nginx/njs/";
7+
8+
js_import main from http/async_var/auth_request.js;
9+
10+
server {
11+
listen 80;
12+
13+
location /secure/ {
14+
auth_request /fetch_upstream;
15+
auth_request_set $backend $upstream_http_x_backend;
16+
17+
proxy_pass http://$backend;
18+
}
19+
20+
location /fetch_upstream {
21+
internal;
22+
23+
proxy_pass http://127.0.0.1:8079;
24+
proxy_pass_request_body off;
25+
proxy_set_header Content-Length "";
26+
proxy_set_header X-Original-URI $request_uri;
27+
}
28+
}
29+
30+
server {
31+
listen 127.0.0.1:8079;
32+
33+
location / {
34+
js_content main.choose_upstream;
35+
}
36+
}
37+
38+
server {
39+
listen 127.0.0.1:8081;
40+
return 200 "BACKEND A:$uri\n";
41+
}
42+
43+
server {
44+
listen 127.0.0.1:8082;
45+
return 200 "BACKEND B:$uri\n";
46+
}
47+
}

‎njs/http/async_var/auth_request.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import qs from "querystring";
2+
3+
function choose_upstream(r) {
4+
let backend;
5+
let args = qs.parse(r.headersIn['X-Original-URI'].split('?')[1]);
6+
7+
switch (args.token) {
8+
case 'A':
9+
backend = '127.0.0.1:8081';
10+
break;
11+
case 'B':
12+
backend = '127.0.0.1:8082';
13+
break;
14+
default:
15+
r.return(404);
16+
}
17+
18+
r.headersOut['X-backend'] = backend;
19+
r.return(200);
20+
}
21+
22+
export default {choose_upstream}

0 commit comments

Comments
 (0)