# HG changeset patch # User Yaroslav Zhuravlev # Date 1529412222 -10800 # Node ID 7865ca0da0ab6c21ef0465bbf88089efab04cca3 # Parent b73ccabb852be8079fde8d99257932990d2f8220 Merged HTTP request,response, and reply in njs. diff --git a/xml/en/docs/njs/njs_api.xml b/xml/en/docs/njs/njs_api.xml --- a/xml/en/docs/njs/njs_api.xml +++ b/xml/en/docs/njs/njs_api.xml @@ -211,40 +211,46 @@ Oglm93xn23_MkiaEq_e9u8zk374
+ +
+ -The HTTP objects are available only in the +The HTTP object is available only in the ngx_http_js_module module. - -
- -req.uri +r.args{} -current URI in a request, read-only +request arguments object, read-only -req.method +r.error(string) -request method, read-only +writes a string to the error log +on the error level of logging -req.httpVersion +r.finish() -HTTP version, read-only +finishes sending a response to the client -req.remoteAddress +r.headersIn{} -client address, read-only +incoming headers object, read-only. + +For example, the Header-Name header +can be accessed with the syntax headers['Header-Name'] +or headers.Header_name + -req.headers{} +r.headersOut{} -request headers object, read-only. +outgoing headers object, writable. For example, the Header-Name header can be accessed with the syntax headers['Header-Name'] @@ -252,45 +258,90 @@ or headers.Header_name -req.args{} +r.httpVersion -request arguments object, read-only +HTTP version, read-only -request.variables{} - -nginx variables object, read-only - - -req.response - -the response object (0.2.0), read-only - - -req.log(string) +r.log(string) writes a string to the error log on the info level of logging -req.warn(string) +r.method + +HTTP method, read-only + + +r.parent + +references the parent request object + + +r.remoteAddress -writes a string to the error log -on the warning level of logging (0.2.0) +client address, read-only + + +r.requestBody + +holds the request body, read-only + + +r.responseBody + +holds the subrequest response body, read-only -req.error(string) +r.return(status[, string]) + +sends the entire response +with the specified status to the client + +It is possible to specify either a redirect URL +(for codes 301, 302, 303, 307, and 308) +or the response body text (for other codes) as the second argument + + + +r.send(string) + +sends a part of the response body to the client + + +r.sendHeader() + +sends the HTTP headers to the client + + +r.status + +status, writable + + +r.variables{} + +nginx variables object, read-only + + +r.warn(string) writes a string to the error log -on the error level of logging (0.2.0) +on the warning level of logging -req.subrequest(uri[, +r.uri + +current URI, read-only + + +r.subrequest(uri[, options[, callback]]) creates a subrequest with the given uri and options, and installs -an optional completion callback (0.2.0). +an optional completion callback. If options is a string, then it @@ -313,131 +364,15 @@ request body HTTP method - - - - -The completion callback -receives a reply object. - - - - - - -
- - -
- - - - -res.status - -response status, writable - - -res.headers{} - -response headers object - - -res.contentType - -the response
Content-Type
header field value, writable -
- -res.contentLength - -the response
Content-Length
header field value, writable -
- -res.sendHeader() - -sends the HTTP header to the client - - -res.send(string) - -sends a part of the response body to the client - - -res.finish() - -finishes sending a response to the client - - -res.return(status[, string]) - -sends -the entire response with the specified status to the client -(0.2.0) - -It is possible to specify either a redirect URL -(for codes 301, 302, 303, 307, and 308) -or the response body text (for other codes) as the second argument - - - -
-
- -
- - -
- - - - -reply.uri - -current URI in a reply, read-only - - -reply.method - -reply method, read-only - - -reply.status - -reply status, writable - - -reply.contentType - -the response
Content-Type
header field value, writable -
- -reply.contentLength - -the response
Content-Length
header field value, writable -
- -reply.headers{} - -reply headers object, read-only -
-Additionally, the reply object has -the following properties: - - - -reply.body - -holds the subrequest response body - - -reply.parent - -references the parent request object +The completion callback receives +a subrequest response object with methods and properties +identical to the parent request object. + @@ -451,7 +386,7 @@ references the parent request object
-The stream objects are available only in the +The stream object is available only in the ngx_stream_js_module module. @@ -522,13 +457,13 @@ on the info level of s.warn(string) writes a sent string to the error log -on the warning level of logging (0.2.0) +on the warning level of logging s.error(string) writes a sent string to the error log -on the error level of logging (0.2.0) +on the error level of logging @@ -555,8 +490,8 @@ js_set $decoded_foo decoded_foo; The urldecode.js file: -function decoded_foo(req, res) { - return decodeURIComponent(req.args.foo); +function decoded_foo(r) { + return decodeURIComponent(r.args.foo); } @@ -582,7 +517,7 @@ location / { The urlencode.js file: -function encoded_foo(req, res) { +function encoded_foo(r) { return encodeURIComponent('foo & bar?'); } @@ -614,17 +549,17 @@ location /bar { The fastresponse.js file: -function content(req, res) { +function content(r) { var n = 0; - function done(reply) { + function done(res) { if (n++ == 0) { - res.return(reply.status, reply.body); + r.return(res.status, res.responseBody); } } - req.subrequest('/foo', req.variables.args, done); - req.subrequest('/bar', req.variables.args, done); + r.subrequest('/foo', r.variables.args, done); + r.subrequest('/bar', r.variables.args, done); } @@ -656,7 +591,7 @@ function create_hs256_jwt(claims, key, v return s + '.' + h.update(s).digest().toString('base64url'); } -function jwt(req, res) { +function jwt(r) { var claims = { "iss" : "nginx", "sub" : "alice", @@ -699,28 +634,28 @@ location /api { The subrequest.js file: -function set_keyval(req, res) { - req.subrequest('/api/3/http/keyvals/foo', +function set_keyval(r) { + r.subrequest('/api/3/http/keyvals/foo', { method: 'POST', body: JSON.stringify({ foo: 789, bar: "ss dd 00" })}, - function(reply) { - if (reply.status >= 300) { - res.return(reply.status, reply.body); + function(res) { + if (res.status >= 300) { + r.return(res.status, res.responseBody); return; } - res.return(500); + r.return(500); }); } -function version(req, res) { - req.subrequest('/api/3/nginx', { method: 'GET' }, function(reply) { - if (reply.status != 200) { - res.return(reply.status); +function version(r) { + r.subrequest('/api/3/nginx', { method: 'GET' }, function(res) { + if (res.status != 200) { + r.return(res.status); return; } - var json = JSON.parse(reply.body); - res.return(200, json.version); + var json = JSON.parse(res.responseBody); + r.return(200, json.version); }); } @@ -754,9 +689,9 @@ location @login { The hash.js file: -function create_secure_link(req, res) { +function create_secure_link(r) { return require('crypto').createHash('md5') - .update(req.uri).update(" mykey") + .update(r.uri).update(" mykey") .digest('base64url'); } diff --git a/xml/ru/docs/njs/njs_api.xml b/xml/ru/docs/njs/njs_api.xml --- a/xml/ru/docs/njs/njs_api.xml +++ b/xml/ru/docs/njs/njs_api.xml @@ -23,40 +23,46 @@
+ +
+ Объекты HTTP доступны только в модуле ngx_http_js_module. - -
- -req.uri +r.args{} -текущий URI запроса, только чтение +объект аргументов запроса, только чтение -req.method +r.error(строка) -метод запроса, только чтение +записывает строку в лог-файл ошибок +на уровне лога error -req.httpVersion +r.finish() -версия HTTP, только чтение +завершает отправку ответа клиенту -req.remoteAddress +r.headersIn{} -адрес клиента, только чтение +объект исходящих заголовков, только чтение. + +Например, доступ к заголовку Header-Name +можно получить при помощи синтаксиса headers['Header-Name'] +или headers.Header_name + -req.headers{} +r.headersOut{} -объект заголовков запроса, только чтение. +объект исходящих заголовков, доступно для записи. Например, доступ к заголовку Header-Name можно получить при помощи синтаксиса headers['Header-Name'] @@ -64,9 +70,66 @@ -req.args{} +r.httpVersion + +версия HTTP, только чтение + + +r.log(строка) + +записывает строку в лог-файл ошибок +на уровне лога info + + +r.method + +HTTP метод, только чтение + + +r.parent + +ссылается на родительский объект запроса + + +r.remoteAddress + +адрес клиента, только чтение + + +r.requestBody -объект аргументов запроса, только чтение +хранит тело запроса, только чтение + + +r.responseBody + +хранит тело ответа подзапроса, только чтение + + +r.return(код[, строка]) + +отправляет +клиенту полный ответ с указанным кодом + +Можно задать или URL перенаправления +(для кодов 301, 302, 303, 307 и 308), +или текст тела ответа (для остальных кодов) в качестве второго аргумента + + + +r.send(строка) + +отправляет часть тела ответа клиенту + + +r.sendHeader() + +отправляет заголовок HTTP клиенту + + +r.status + +статус, доступно для записи req.variables{} @@ -74,41 +137,30 @@ объект переменных nginx, только чтение -req.response - -объект ответа (0.2.0), только чтение - - -req.log(строка) +r.warn(строка) записывает строку в лог-файл ошибок -на уровне лога info +на уровне лога warning -req.warn(строка) +r.uri -записывает строку в лог-файл ошибок -на уровне лога warning (0.2.0) +текущий URI, только чтение -req.error(строка) - -записывает строку в лог-файл ошибок -на уровне лога error (0.2.0) - - -req.subrequest(uri[, +r.subrequest(uri[, options[, callback]]) создаёт подзапрос с заданными uri и options и -устанавливает необязательный callback завершения (0.2.0). +устанавливает необязательный callback завершения. Если options является строкой, то в ней содержится срока аргументов подзапроса. В противном случае ожидается, что options является объектом со следующими ключами: + args @@ -129,67 +181,9 @@ -callback -получает объект reply. - - - - - - -
- - -
- - - - -res.status - -статус ответа, доступно для записи - - -res.headers{} - -объект заголовков ответа - - -res.contentType - -значение поля
Content-Type
заголовка ответа, -доступно для записи -
- -res.contentLength - -значение поля
Content-Length
заголовка ответа, -доступно для записи -
- -res.sendHeader() - -отправляет заголовок HTTP клиенту - - -res.send(строка) - -отправляет часть тела ответа клиенту - - -res.finish() - -завершает отправку ответа клиенту - - -res.return(код[, строка]) - -отправляет -клиенту полный ответ с указанным кодом (0.2.0) - -Можно задать или URL перенаправления -(для кодов 301, 302, 303, 307 и 308), -или текст тела ответа (для остальных кодов) в качестве второго аргумента +callback получает +объект ответа подзапроса с методами и свойствами, +идентичными родительскому объекту запроса. @@ -198,68 +192,6 @@
- -
- - - - -reply.uri - -текущий URI, только чтение - - -reply.method - -метод, только чтение - - -reply.status - -статус, доступно для записи - - -reply.contentType - -значение поля
Content-Type
заголовка, -доступно для записи -
- -reply.contentLength - -значение поля
Content-Length
заголовка, -доступно для записи -
- -reply.headers{} - -объект заголовков ответа, только чтение - - -
-
- - -Кроме того, у объект reply имеет -следующие свойства: - - - -reply.body - -хранит тело ответа подзапроса - - -reply.parent - -ссылается на родительский объект запроса - - - - - -
-
@@ -340,13 +272,13 @@ true, если текущий буфер является буфером от проксируемого сервера к клиенту, s.warn(строка) записывает отправленную строку в лог-файл ошибок -на уровне лога warning (0.2.0) +на уровне лога warning s.error(строка) записывает отправленную строку в лог-файл ошибок -на уровне лога error (0.2.0) +на уровне лога error @@ -357,5 +289,232 @@ true, если текущий буфер является буфером от проксируемого сервера к клиенту,
+
+ + +
+ + + +js_include urldecode.js; + +js_set $decoded_foo decoded_foo; + + + + +Файл urldecode.js: + +function decoded_foo(r) { + return decodeURIComponent(r.args.foo); +} + + + +
+ + +
+ + + +js_include urlencode.js; + +js_set $encoded_foo encoded_foo; +... + +location / { + proxy_pass http://example.com?foo=$encoded_foo; +} + + + + +Файл urlencode.js: + +function encoded_foo(r) { + return encodeURIComponent('foo & bar?'); +} + + + +
+ + +
+ + + +js_include fastresponse.js; + +location /start { + js_content content; +} + +location /foo { + proxy_pass http://backend1; +} + +location /bar { + proxy_pass http://backend2; +} + + + + +Файл fastresponse.js: + +function content(r) { + var n = 0; + + function done(res) { + if (n++ == 0) { + r.return(res.status, res.responseBody); + } + } + + r.subrequest('/foo', r.variables.args, done); + r.subrequest('/bar', r.variables.args, done);TBD +} + + + +
+ + +
+ + + +js_include hs_jwt.js; + +js_set $jwt jwt; + + + + +Файл hs_jwt.js: + +function create_hs256_jwt(claims, key, valid) { + var header = { "typ" : "JWT", "alg" : "HS256", "exp" : Date.now() + valid }; + + var s = JSON.stringify(header).toBytes().toString('base64url') + '.' + + JSON.stringify(claims).toBytes().toString('base64url'); + + var h = require('crypto').createHmac('sha256', key); + + return s + '.' + h.update(s).digest().toString('base64url'); +} + +function jwt(r) { + var claims = { + "iss" : "nginx", + "sub" : "alice", + "foo" : 123, + "bar" : "qq", + "zyx" : false + }; + + return create_hs256_jwt(claims, 'foo', 600); +} + + + +
+ + +
+ + + +js_include subrequest.js; + +keyval_zone zone=foo:10m; +... + +location /keyval { + js_content set_keyval; +} + +location /version { + js_content version; +} + +location /api { + api write=on; +} + + + + +Файл subrequest.js: + +function set_keyval(r) { + r.subrequest('/api/3/http/keyvals/foo', + { method: 'POST', + body: JSON.stringify({ foo: 789, bar: "ss dd 00" })}, + + function(res) { + if (res.status >= 300) { + r.return(res.status, res.responseBody); + return; + } + r.return(500); + }); +} +function version(r) { + r.subrequest('/api/3/nginx', { method: 'GET' }, function(res) { + if (res.status != 200) { + r.return(res.status); + return; + } + + var json = JSON.parse(res.responseBody); + r.return(200, json.version); + }); +} + + + +
+ + + + +
+