# HG changeset patch # User Sergey Kandaurov # Date 1685969978 -14400 # Node ID 4b41550ebdb3d332d266ad4f064513c1db91a56a # Parent c560f5da581e7cd71f24c0ea4eca9f21a149e9cb Tests: removed njs tests. The tests are now hosted in the njs repository. diff --git a/h2_request_body_js.t b/h2_request_body_js.t deleted file mode 100644 --- a/h2_request_body_js.t +++ /dev/null @@ -1,87 +0,0 @@ -#!/usr/bin/perl - -# (C) Sergey Kandaurov -# (C) Nginx, Inc. - -# Tests for HTTP/2 request body with njs subrequest in the body handler. - -############################################################################### - -use warnings; -use strict; - -use Test::More; - -BEGIN { use FindBin; chdir($FindBin::Bin); } - -use lib 'lib'; -use Test::Nginx; -use Test::Nginx::HTTP2; - -############################################################################### - -select STDERR; $| = 1; -select STDOUT; $| = 1; - -my $t = Test::Nginx->new()->has(qw/http http_v2/) - ->write_file_expand('nginx.conf', <<'EOF'); - -%%TEST_GLOBALS%% - -daemon off; - -events { -} - -http { - %%TEST_GLOBALS_HTTP%% - - js_import test.js; - - server { - listen 127.0.0.1:8080 http2; - server_name localhost; - - lingering_close off; - - location / { - js_content test.sr_body; - add_header X-Body $request_body; - } - - location /sr { } - } -} - -EOF - -$t->write_file('test.js', <write_file('sr', 'SEE-THIS'); -$t->try_run('no njs available')->plan(3); - -############################################################################### - -my $s = Test::Nginx::HTTP2->new(); -my $sid = $s->new_stream({ body => 'TEST' }); -my $frames = $s->read(all => [{ sid => $sid, fin => 1 }]); - -my ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; -is($frame->{headers}->{':status'}, 200, 'status'); -is($frame->{headers}->{'x-body'}, 'TEST', 'request body'); - -($frame) = grep { $_->{type} eq "DATA" } @$frames; -is($frame->{data}, 'SEE-THIS', 'response body'); - -############################################################################### diff --git a/js.t b/js.t deleted file mode 100644 --- a/js.t +++ /dev/null @@ -1,391 +0,0 @@ -#!/usr/bin/perl - -# (C) Roman Arutyunyan -# (C) Dmitry Volyntsev -# (C) Nginx, Inc. - -# Tests for http njs module. - -############################################################################### - -use warnings; -use strict; - -use Test::More; -use Socket qw/ CRLF /; - -BEGIN { use FindBin; chdir($FindBin::Bin); } - -use lib 'lib'; -use Test::Nginx; - -############################################################################### - -select STDERR; $| = 1; -select STDOUT; $| = 1; - -my $t = Test::Nginx->new()->has(qw/http rewrite/) - ->write_file_expand('nginx.conf', <<'EOF'); - -%%TEST_GLOBALS%% - -daemon off; - -events { -} - -http { - %%TEST_GLOBALS_HTTP%% - - js_set $test_method test.method; - js_set $test_version test.version; - js_set $test_addr test.addr; - js_set $test_uri test.uri; - js_set $test_var test.variable; - js_set $test_type test.type; - js_set $test_global test.global_obj; - js_set $test_log test.log; - js_set $test_internal test.sub_internal; - js_set $test_except test.except; - - js_import test.js; - - server { - listen 127.0.0.1:8080; - server_name localhost; - - location /njs { - js_content test.njs; - } - - location /method { - return 200 $test_method; - } - - location /version { - return 200 $test_version; - } - - location /addr { - return 200 $test_addr; - } - - location /uri { - return 200 $test_uri; - } - - location /var { - return 200 $test_var; - } - - location /global { - return 200 $test_global; - } - - location /body { - js_content test.request_body; - } - - location /in_file { - client_body_in_file_only on; - js_content test.request_body; - } - - location /status { - js_content test.status; - } - - location /request_body { - js_content test.request_body; - } - - location /request_body_cache { - js_content test.request_body_cache; - } - - location /send { - js_content test.send; - } - - location /return_method { - js_content test.return_method; - } - - location /type { - js_content test.type; - } - - location /log { - return 200 $test_log; - } - - location /internal { - js_content test.internal; - } - - location /sub_internal { - internal; - return 200 $test_internal; - } - - location /except { - return 200 $test_except; - } - - location /content_except { - js_content test.content_except; - } - - location /content_empty { - js_content test.content_empty; - } - } -} - -EOF - -$t->write_file('test.js', < a[v], r); - - var typ = Buffer.isBuffer(p) ? 'buffer' : (typeof p); - r.return(200, `type: \${typ}`); - } - - function log(r) { - r.log('SEE-LOG'); - } - - async function internal(r) { - let reply = await r.subrequest('/sub_internal'); - - r.return(200, `parent: \${r.internal} sub: \${reply.responseText}`); - } - - function sub_internal(r) { - return r.internal; - } - - function except(r) { - var fs = require('fs'); - fs.readFileSync(); - } - - - function content_except(r) { - JSON.parse({}.a.a); - } - - function content_empty(r) { - } - - export default {njs:test_njs, method, version, addr, uri, - variable, global_obj, status, request_body, internal, - request_body_cache, send, return_method, sub_internal, - type, log, except, content_except, content_empty}; - -EOF - -$t->try_run('no njs available')->plan(27); - -############################################################################### - -like(http_get('/method'), qr/method=GET/, 'r.method'); -like(http_get('/version'), qr/version=1.0/, 'r.httpVersion'); -like(http_get('/addr'), qr/addr=127.0.0.1/, 'r.remoteAddress'); -like(http_get('/uri'), qr/uri=\/uri/, 'r.uri'); - -like(http_get('/status'), qr/204 No Content/, 'r.status'); - -like(http_post('/body'), qr/REQ-BODY/, 'request body'); -like(http_post('/in_file'), qr/request body is in a file/, - 'request body in file'); -like(http_post_big('/body'), qr/200.*^(1234567890){1024}$/ms, - 'request body big'); - -like(http_get('/send?foo=12345&n=11&foo-2=bar&ndd=&foo-3=z'), - qr/n=foo, v=12 n=foo-2, v=ba n=foo-3, v=z/, 'r.send'); - -like(http_get('/return_method?c=200'), qr/200 OK.*\x0d\x0a?\x0d\x0a?$/s, - 'return code'); -like(http_get('/return_method?c=200&t=SEE-THIS'), qr/200 OK.*^SEE-THIS$/ms, - 'return text'); -like(http_get('/return_method?c=301&t=path'), qr/ 301 .*Location: path/s, - 'return redirect'); -like(http_get('/return_method?c=404'), qr/404 Not.*html/s, 'return error page'); -like(http_get('/return_method?c=inv'), qr/ 500 /, 'return invalid'); - -like(http_get('/type?path=variables.host'), qr/200 OK.*type: string$/s, - 'variables type'); -like(http_get('/type?path=rawVariables.host'), qr/200 OK.*type: buffer$/s, - 'rawVariables type'); - -like(http_post('/type?path=requestText'), qr/200 OK.*type: string$/s, - 'requestText type'); -like(http_post('/type?path=requestBuffer'), qr/200 OK.*type: buffer$/s, - 'requestBuffer type'); -like(http_post('/request_body_cache'), - qr/requestText:string requestBuffer:buffer$/s, 'request body cache'); - -like(http_get('/var'), qr/variable=127.0.0.1/, 'r.variables'); -like(http_get('/global'), qr/global=njs/, 'global code'); -like(http_get('/log'), qr/200 OK/, 'r.log'); - -TODO: { -local $TODO = 'not yet' unless has_version('0.7.7'); - -like(http_get('/internal'), qr/parent: false sub: true/, 'r.internal'); - -} - -http_get('/except'); -http_get('/content_except'); - -like(http_get('/content_empty'), qr/500 Internal Server Error/, - 'empty handler'); - -$t->stop(); - -ok(index($t->read_file('error.log'), 'SEE-LOG') > 0, 'log js'); -ok(index($t->read_file('error.log'), 'at fs.readFileSync') > 0, - 'js_set backtrace'); -ok(index($t->read_file('error.log'), 'at JSON.parse') > 0, - 'js_content backtrace'); - -############################################################################### - -sub has_version { - my $need = shift; - - http_get('/njs') =~ /^([.0-9]+)$/m; - - my @v = split(/\./, $1); - my ($n, $v); - - for $n (split(/\./, $need)) { - $v = shift @v || 0; - return 0 if $n > $v; - return 1 if $v > $n; - } - - return 1; -} - -############################################################################### - -sub http_get_hdr { - my ($url, %extra) = @_; - return http(< "JSON::PP not installed") if $@; - -my $t = Test::Nginx->new()->has(qw/http/) - ->write_file_expand('nginx.conf', <<'EOF'); - -%%TEST_GLOBALS%% - -daemon off; - -events { -} - -http { - %%TEST_GLOBALS_HTTP%% - - js_import test.js; - - js_set $test_iter test.iter; - - server { - listen 127.0.0.1:8080; - server_name localhost; - - location /njs { - js_content test.njs; - } - - location /iter { - return 200 $test_iter; - } - - location /keys { - js_content test.keys; - } - - location /object { - js_content test.object; - } - } -} - -EOF - -$t->write_file('test.js', <try_run('no njs')->plan(15); - -############################################################################### - -sub recode { - my $json; - eval { $json = JSON::PP::decode_json(shift) }; - - if ($@) { - return ""; - } - - JSON::PP->new()->canonical()->encode($json); -} - -sub get_json { - http_get(shift) =~ /\x0d\x0a?\x0d\x0a?(.*)/ms; - recode($1); -} - -############################################################################### - -local $TODO = 'not yet' unless has_version('0.7.6'); - -like(http_get('/iter?foo=12345&foo2=bar&nn=22&foo-3=z'), qr/12345barz/, - 'r.args iteration'); -like(http_get('/iter?foo=123&foo2=&foo3&foo4=456'), qr/123456/, - 'r.args iteration 2'); -like(http_get('/iter?foo=123&foo2=&foo3'), qr/123/, 'r.args iteration 3'); -like(http_get('/iter?foo=123&foo2='), qr/123/, 'r.args iteration 4'); -like(http_get('/iter?foo=1&foo=2'), qr/1,2/m, 'r.args iteration 5'); - -like(http_get('/keys?b=1&c=2&a=5'), qr/a,b,c/m, 'r.args sorted keys'); -like(http_get('/keys?b=1&b=2'), qr/b/m, 'r.args duplicate keys'); -like(http_get('/keys?b=1&a&c='), qr/a,b,c/m, 'r.args empty value'); - -is(get_json('/object'), '{}', 'empty object'); -is(get_json('/object?a=1&b=2&c=3'), '{"a":"1","b":"2","c":"3"}', - 'ordinary object'); -is(get_json('/object?a=1&A=2'), '{"A":"2","a":"1"}', - 'case sensitive object'); -is(get_json('/object?a=1&A=2&a=3'), '{"A":"2","a":["1","3"]}', - 'duplicate keys object'); -is(get_json('/object?%61=1&a=2'), '{"a":["1","2"]}', - 'keys percent-encoded object'); -is(get_json('/object?a=%62%63&b=%63%64'), '{"a":"bc","b":"cd"}', - 'values percent-encoded object'); -is(get_json('/object?a=%6&b=%&c=%%&d=%zz'), - '{"a":"%6","b":"%","c":"%%","d":"%zz"}', - 'values percent-encoded broken object'); - -############################################################################### - -sub has_version { - my $need = shift; - - http_get('/njs') =~ /^([.0-9]+)$/m; - - my @v = split(/\./, $1); - my ($n, $v); - - for $n (split(/\./, $need)) { - $v = shift @v || 0; - return 0 if $n > $v; - return 1 if $v > $n; - } - - return 1; -} - -############################################################################### diff --git a/js_async.t b/js_async.t deleted file mode 100644 --- a/js_async.t +++ /dev/null @@ -1,249 +0,0 @@ -#!/usr/bin/perl - -# (C) Dmitry Volyntsev -# (C) Nginx, Inc. - -# Async tests for http njs module. - -############################################################################### - -use warnings; -use strict; - -use Test::More; - -BEGIN { use FindBin; chdir($FindBin::Bin); } - -use lib 'lib'; -use Test::Nginx; - -############################################################################### - -select STDERR; $| = 1; -select STDOUT; $| = 1; - -my $t = Test::Nginx->new()->has(qw/http rewrite/) - ->write_file_expand('nginx.conf', <<'EOF'); - -%%TEST_GLOBALS%% - -daemon off; - -events { -} - -http { - %%TEST_GLOBALS_HTTP%% - - js_set $test_async test.set_timeout; - js_set $context_var test.context_var; - js_set $test_set_rv_var test.set_rv_var; - - js_import test.js; - - server { - listen 127.0.0.1:8080; - server_name localhost; - - location /njs { - js_content test.njs; - } - - location /async_var { - return 200 $test_async; - } - - location /shared_ctx { - add_header H $context_var; - js_content test.shared_ctx; - } - - location /set_timeout { - js_content test.set_timeout; - } - - location /set_timeout_many { - js_content test.set_timeout_many; - } - - location /set_timeout_data { - postpone_output 0; - js_content test.set_timeout_data; - } - - location /limit_rate { - postpone_output 0; - sendfile_max_chunk 5; - js_content test.limit_rate; - } - - location /async_content { - js_content test.async_content; - } - - location /set_rv_var { - return 200 $test_set_rv_var; - } - } -} - -EOF - -$t->write_file('test.js', < {resolve(x)}).then(v => v).then(v => v); - } - - async function async_content(r) { - const a1 = await pr('A'); - const a2 = await pr('B'); - - r.return(200, `retval: \${a1 + a2}`); - } - - async function set_rv_var(r) { - const a1 = await pr(10); - const a2 = await pr(20); - - r.setReturnValue(`retval: \${a1 + a2}`); - } - - export default {njs:test_njs, set_timeout, set_timeout_data, - set_timeout_many, context_var, shared_ctx, limit_rate, - async_content, set_rv_var}; - -EOF - -$t->try_run('no njs available')->plan(9); - -############################################################################### - -like(http_get('/set_timeout'), qr/Content-Type: foo/, 'setTimeout'); -like(http_get('/set_timeout_many'), qr/Content-Type: reply/, 'setTimeout many'); -like(http_get('/set_timeout_data'), qr/123456789/, 'setTimeout data'); -like(http_get('/shared_ctx?a=xxx'), qr/H: xxx/, 'shared context'); -like(http_get('/limit_rate'), qr/A{50}/, 'limit_rate'); - -TODO: { -local $TODO = 'not yet' unless has_version('0.7.0'); - -like(http_get('/async_content'), qr/retval: AB/, 'async content'); -like(http_get('/set_rv_var'), qr/retval: 30/, 'set return value variable'); - -} - -http_get('/async_var'); - -$t->stop(); - -ok(index($t->read_file('error.log'), 'pending events') > 0, - 'pending js events'); -ok(index($t->read_file('error.log'), 'async operation inside') > 0, - 'async op in var handler'); - -############################################################################### - -sub has_version { - my $need = shift; - - http_get('/njs') =~ /^([.0-9]+)$/m; - - my @v = split(/\./, $1); - my ($n, $v); - - for $n (split(/\./, $need)) { - $v = shift @v || 0; - return 0 if $n > $v; - return 1 if $v > $n; - } - - return 1; -} - -############################################################################### diff --git a/js_body_filter.t b/js_body_filter.t deleted file mode 100644 --- a/js_body_filter.t +++ /dev/null @@ -1,168 +0,0 @@ -#!/usr/bin/perl - -# (C) Dmitry Volyntsev -# (C) Nginx, Inc. - -# Tests for http njs module, body filter. - -############################################################################### - -use warnings; -use strict; - -use Test::More; - -BEGIN { use FindBin; chdir($FindBin::Bin); } - -use lib 'lib'; -use Test::Nginx; - -############################################################################### - -select STDERR; $| = 1; -select STDOUT; $| = 1; - -my $t = Test::Nginx->new()->has(qw/http proxy/) - ->write_file_expand('nginx.conf', <<'EOF'); - -%%TEST_GLOBALS%% - -daemon off; - -events { -} - -http { - %%TEST_GLOBALS_HTTP%% - - js_import test.js; - - server { - listen 127.0.0.1:8080; - server_name localhost; - - location /njs { - js_content test.njs; - } - - location /append { - js_body_filter test.append; - proxy_pass http://127.0.0.1:8081/source; - } - - location /buffer_type { - js_body_filter test.buffer_type buffer_type=buffer; - proxy_pass http://127.0.0.1:8081/source; - } - - location /forward { - js_body_filter test.forward buffer_type=string; - proxy_pass http://127.0.0.1:8081/source; - } - - location /filter { - proxy_buffering off; - js_body_filter test.filter; - proxy_pass http://127.0.0.1:8081/source; - } - - location /prepend { - js_body_filter test.prepend; - proxy_pass http://127.0.0.1:8081/source; - } - } - - server { - listen 127.0.0.1:8081; - server_name localhost; - - location /source { - postpone_output 1; - js_content test.source; - } - } -} - -EOF - -$t->write_file('test.js', <= Number(r.args.len)) { - r.sendBuffer(`\${data}|`, flags); - - if (r.args.dup && !flags.last) { - r.sendBuffer(data, flags); - } - } - } - - function forward(r, data, flags) { - r.sendBuffer(data, flags); - } - - function prepend(r, data, flags) { - r.sendBuffer("XXX"); - r.sendBuffer(data, flags); - r.done(); - } - - export default {njs: test_njs, append, buffer_type, filter, forward, - prepend, source}; - -EOF - -$t->try_run('no njs body filter')->plan(6); - -############################################################################### - -like(http_get('/append'), qr/AAABBCDDDDXXX/, 'append'); -like(http_get('/buffer_type'), qr/AAABBCDDDD/, 'buffer type'); -like(http_get('/forward'), qr/AAABBCDDDD/, 'forward'); -like(http_get('/filter?len=3'), qr/AAA|DDDD|/, 'filter 3'); -like(http_get('/filter?len=2&dup=1'), qr/AAA|AAABB|BBDDDD|DDDD/, - 'filter 2 dup'); -like(http_get('/prepend'), qr/XXXAAABBCDDDD/, 'prepend'); - -############################################################################### diff --git a/js_body_filter_if.t b/js_body_filter_if.t deleted file mode 100644 --- a/js_body_filter_if.t +++ /dev/null @@ -1,127 +0,0 @@ -#!/usr/bin/perl - -# (C) Dmitry Volyntsev -# (C) Nginx, Inc. - -# Tests for http njs module, body filter, if context. - -############################################################################### - -use warnings; -use strict; - -use Test::More; - -BEGIN { use FindBin; chdir($FindBin::Bin); } - -use lib 'lib'; -use Test::Nginx; - -############################################################################### - -select STDERR; $| = 1; -select STDOUT; $| = 1; - -my $t = Test::Nginx->new()->has(qw/http proxy rewrite/) - ->write_file_expand('nginx.conf', <<'EOF'); - -%%TEST_GLOBALS%% - -daemon off; - -events { -} - -http { - %%TEST_GLOBALS_HTTP%% - - js_import test.js; - - server { - listen 127.0.0.1:8080; - server_name localhost; - - location /njs { - js_content test.njs; - } - - location /filter { - if ($arg_name ~ "prepend") { - js_body_filter test.prepend; - } - - if ($arg_name ~ "append") { - js_body_filter test.append; - } - - js_body_filter test.should_not_be_called; - - proxy_pass http://127.0.0.1:8081/source; - } - } - - server { - listen 127.0.0.1:8081; - server_name localhost; - - location /source { - postpone_output 1; - js_content test.source; - } - } -} - -EOF - -$t->write_file('test.js', <try_run('no njs body filter')->plan(2); - -############################################################################### - -like(http_get('/filter?name=append'), qr/AAABBCDDDDXXX/, 'append'); -like(http_get('/filter?name=prepend'), qr/XXXAAABBCDDDD/, 'prepend'); - -############################################################################### diff --git a/js_buffer.t b/js_buffer.t deleted file mode 100644 --- a/js_buffer.t +++ /dev/null @@ -1,184 +0,0 @@ -#!/usr/bin/perl - -# (C) Dmitry Volyntsev -# (C) Nginx, Inc. - -# Tests for http njs module, buffer properties. - -############################################################################### - -use warnings; -use strict; - -use Test::More; - -use Socket qw/ CRLF /; - -BEGIN { use FindBin; chdir($FindBin::Bin); } - -use lib 'lib'; -use Test::Nginx; - -############################################################################### - -select STDERR; $| = 1; -select STDOUT; $| = 1; - -eval { require JSON::PP; }; -plan(skip_all => "JSON::PP not installed") if $@; - -my $t = Test::Nginx->new()->has(qw/http rewrite proxy/) - ->write_file_expand('nginx.conf', <<'EOF'); - -%%TEST_GLOBALS%% - -daemon off; - -events { -} - -http { - %%TEST_GLOBALS_HTTP%% - - js_import test.js; - - server { - listen 127.0.0.1:8080; - server_name localhost; - - location /njs { - js_content test.njs; - } - - location /return { - js_content test.return; - } - - location /req_body { - js_content test.req_body; - } - - location /res_body { - js_content test.res_body; - } - - location /res_text { - js_content test.res_text; - } - - location /binary_var { - js_content test.binary_var; - } - - location /p/ { - proxy_pass http://127.0.0.1:8081/; - } - } - - server { - listen 127.0.0.1:8081; - server_name localhost; - - location /sub1 { - return 200 '{"a": {"b": 1}}'; - } - } -} - -EOF - -$t->write_file('test.js', < { - var body = reply.responseBuffer; - var view = new DataView(body.buffer); - view.setInt8(2, 'c'.charCodeAt(0)); - body = JSON.parse(body); - body.type = type(reply.responseBuffer); - r.return(200, JSON.stringify(body)); - }) - } - - function res_text(r) { - r.subrequest('/p/sub1') - .then(reply => { - var body = JSON.parse(reply.responseText); - body.type = type(reply.responseText); - r.return(200, JSON.stringify(body)); - }) - } - - function binary_var(r) { - var test = r.rawVariables.binary_remote_addr - .equals(Buffer.from([127,0,0,1])); - r.return(200, test); - } - - export default {njs: test_njs, return: test_return, req_body, res_body, - res_text, binary_var}; - -EOF - -$t->try_run('no njs buffer')->plan(5); - -############################################################################### - -like(http_get('/return?text=FOO'), qr/200 OK.*body: FOO$/s, - 'return buffer'); -like(http_post('/req_body'), qr/200 OK.*BAR$/s, 'request buffer'); -is(get_json('/res_body'), '{"c":{"b":1},"type":"buffer"}', 'response buffer'); -is(get_json('/res_text'), '{"a":{"b":1},"type":"string"}', 'response text'); -like(http_get('/binary_var'), qr/200 OK.*true$/s, - 'binary var'); - -############################################################################### - -sub recode { - my $json; - eval { $json = JSON::PP::decode_json(shift) }; - - if ($@) { - return ""; - } - - JSON::PP->new()->canonical()->encode($json); -} - -sub get_json { - http_get(shift) =~ /\x0d\x0a?\x0d\x0a?(.*)/ms; - recode($1); -} - -sub http_post { - my ($url, %extra) = @_; - - my $p = "POST $url HTTP/1.0" . CRLF . - "Host: localhost" . CRLF . - "Content-Length: 17" . CRLF . - CRLF . - "{\"a\":{\"b\":\"BAR\"}}"; - - return http($p, %extra); -} - -############################################################################### diff --git a/js_dump.t b/js_dump.t deleted file mode 100644 --- a/js_dump.t +++ /dev/null @@ -1,110 +0,0 @@ -#!/usr/bin/perl - -# (C) Dmitry Volyntsev -# (C) Nginx, Inc. - -# Tests for http njs module, request object dump. - -############################################################################### - -use warnings; -use strict; - -use Test::More; -use Socket qw/ CRLF /; - -BEGIN { use FindBin; chdir($FindBin::Bin); } - -use lib 'lib'; -use Test::Nginx; - -############################################################################### - -select STDERR; $| = 1; -select STDOUT; $| = 1; - -my $t = Test::Nginx->new()->has(qw/http rewrite/) - ->write_file_expand('nginx.conf', <<'EOF'); - -%%TEST_GLOBALS%% - -daemon off; - -events { -} - -http { - %%TEST_GLOBALS_HTTP%% - - js_import test.js; - - server { - listen 127.0.0.1:8080; - server_name localhost; - - location /dump { - js_content test.dump; - } - - location /stringify { - js_content test.stringify; - } - - location /stringify_subrequest { - js_content test.stringify_subrequest; - } - - location /js_sub { - return 201 '{$request_method}'; - } - } -} - -EOF - -$t->write_file('test.js', < { - r.return(200, JSON.stringify(reply)) - }); - } - - export default {dump, stringify, stringify_subrequest}; - -EOF - -$t->try_run('no njs dump')->plan(3); - -############################################################################### - -like(http( - 'GET /dump?v=1&t=x HTTP/1.0' . CRLF - . 'Foo: bar' . CRLF - . 'Foo2: bar2' . CRLF - . 'Host: localhost' . CRLF . CRLF -), qr/method:'GET'/, 'njs.dump(r)'); - -like(http( - 'GET /stringify?v=1&t=x HTTP/1.0' . CRLF - . 'Foo: bar' . CRLF - . 'Foo2: bar2' . CRLF - . 'Host: localhost' . CRLF . CRLF -), qr/headersOut":\{"baz":"bar"}/, 'JSON.stringify(r)'); - -like(http( - 'GET /stringify_subrequest HTTP/1.0' . CRLF - . 'Host: localhost' . CRLF . CRLF -), qr/"status":201/, 'JSON.stringify(reply)'); - -############################################################################### diff --git a/js_fetch.t b/js_fetch.t deleted file mode 100644 --- a/js_fetch.t +++ /dev/null @@ -1,694 +0,0 @@ -#!/usr/bin/perl - -# (C) Dmitry Volyntsev -# (C) Nginx, Inc. - -# Tests for http njs module, fetch method. - -############################################################################### - -use warnings; -use strict; - -use Test::More; - -use Socket qw/ CRLF /; - -BEGIN { use FindBin; chdir($FindBin::Bin); } - -use lib 'lib'; -use Test::Nginx; - -############################################################################### - -select STDERR; $| = 1; -select STDOUT; $| = 1; - -eval { require JSON::PP; }; -plan(skip_all => "JSON::PP not installed") if $@; - -my $t = Test::Nginx->new()->has(qw/http/) - ->write_file_expand('nginx.conf', <<'EOF'); - -%%TEST_GLOBALS%% - -daemon off; - -events { -} - -http { - %%TEST_GLOBALS_HTTP%% - - js_import test.js; - - server { - listen 127.0.0.1:8080; - server_name localhost; - - location /njs { - js_content test.njs; - } - - location /broken { - js_content test.broken; - } - - location /broken_response { - js_content test.broken_response; - } - - location /body { - js_content test.body; - } - - location /body_special { - js_content test.body_special; - } - - location /chain { - js_content test.chain; - } - - location /chunked_ok { - js_content test.chunked_ok; - } - - location /chunked_fail { - js_content test.chunked_fail; - } - - location /header { - js_content test.header; - } - - location /header_iter { - js_content test.header_iter; - } - - location /multi { - js_content test.multi; - } - - location /property { - js_content test.property; - } - - location /loc { - js_content test.loc; - } - - location /json { } - } - - server { - listen 127.0.0.1:8081; - server_name localhost; - - location /loc { - js_content test.loc; - } - } -} - -EOF - -my $p0 = port(8080); -my $p1 = port(8081); -my $p2 = port(8082); - -$t->write_file('json', '{"a":[1,2], "b":{"c":"FIELD"}}'); - -$t->write_file('test.js', < a[v], obj); - } - - return JSON.stringify(retval); - } - - ngx.fetch(`http://127.0.0.1:$p0/\${loc}`) - .then(reply => reply[getter]()) - .then(data => r.return(200, query(data))) - .catch(e => r.return(501, e.message)) - } - - function property(r) { - var opts = {headers:{}}; - - if (r.args.code) { - opts.headers.code = r.args.code; - } - - var p = ngx.fetch('http://127.0.0.1:$p0/loc', opts) - - if (r.args.readBody) { - p = p.then(rep => - rep.text().then(body => {rep.text = body; return rep;})) - } - - p.then(reply => r.return(200, reply[r.args.pr])) - .catch(e => r.return(501, e.message)) - } - - function process_errors(r, tests) { - var results = []; - - tests.forEach(args => { - ngx.fetch.apply(r, args) - .then(reply => { - r.return(400, '["unexpected then"]'); - }) - .catch(e => { - results.push(e.message); - - if (results.length == tests.length) { - results.sort(); - r.return(200, JSON.stringify(results)); - } - }) - }) - } - - function broken(r) { - var tests = [ - ['http://127.0.0.1:1/loc'], - ['http://127.0.0.1:80800/loc'], - [Symbol.toStringTag], - ]; - - return process_errors(r, tests); - } - - function broken_response(r) { - var tests = [ - ['http://127.0.0.1:$p2/status_line'], - ['http://127.0.0.1:$p2/length'], - ['http://127.0.0.1:$p2/header'], - ['http://127.0.0.1:$p2/headers'], - ['http://127.0.0.1:$p2/content_length'], - ]; - - return process_errors(r, tests); - } - - function chain(r) { - var results = []; - var reqs = [ - ['http://127.0.0.1:$p0/loc'], - ['http://127.0.0.1:$p1/loc'], - ]; - - function next(reply) { - if (reqs.length == 0) { - r.return(200, "SUCCESS"); - return; - } - - ngx.fetch.apply(r, reqs.pop()) - .then(next) - .catch(e => r.return(400, e.message)) - } - - next(); - } - - function chunked_ok(r) { - var results = []; - var tests = [ - ['http://127.0.0.1:$p2/big/ok', {max_response_body_size:128000}], - ['http://127.0.0.1:$p2/chunked/ok'], - ['http://127.0.0.1:$p2/chunked/big'], - ]; - - function collect(v) { - results.push(v); - - if (results.length == tests.length) { - r.return(200); - } - } - - tests.forEach(args => { - ngx.fetch.apply(r, args) - .then(reply => reply.text()) - .then(body => collect(body.length)) - }) - } - - function chunked_fail(r) { - var results = []; - var tests = [ - ['http://127.0.0.1:$p2/big', {max_response_body_size:128000}], - ['http://127.0.0.1:$p2/chunked'], - ['http://127.0.0.1:$p2/chunked/big', {max_response_body_size:128}], - ]; - - function collect(v) { - results.push(v); - - if (results.length == tests.length) { - r.return(200); - } - } - - tests.forEach(args => { - ngx.fetch.apply(r, args) - .then(reply => reply.text()) - .catch(e => collect(e.message)) - }) - } - - function header(r) { - var url = `http://127.0.0.1:$p2/\${r.args.loc}`; - var method = r.args.method ? r.args.method : 'get'; - - var p = ngx.fetch(url) - - if (r.args.readBody) { - p = p.then(rep => - rep.text().then(body => {rep.text = body; return rep;})) - } - - p.then(reply => { - var h = reply.headers[method](r.args.h); - r.return(200, njs.dump(h)); - }) - .catch(e => r.return(501, e.message)) - } - - async function body_special(r) { - let opts = {}; - - if (r.args.method) { - opts.method = r.args.method; - } - - let reply = await ngx.fetch(`http://127.0.0.1:$p2/\${r.args.loc}`, - opts); - let body = await reply.text(); - - r.return(200, body != '' ? body : ''); - } - - async function header_iter(r) { - let url = `http://127.0.0.1:$p2/\${r.args.loc}`; - - let response = await ngx.fetch(url); - - let headers = response.headers; - let out = []; - for (let key in response.headers) { - if (key != 'Connection') { - out.push(`\${key}:\${headers.get(key)}`); - } - } - - r.return(200, njs.dump(out)); - } - - function multi(r) { - var results = []; - var tests = [ - [ - 'http://127.0.0.1:$p0/loc', - { headers: {Code: 201}}, - ], - [ - 'http://127.0.0.1:$p0/loc', - { method:'POST', headers: {Code: 401}, body: 'OK'}, - ], - [ - 'http://127.0.0.1:$p1/loc', - { method:'PATCH', - headers: {bar:'xxx'}}, - ], - ]; - - function cmp(a,b) { - if (a.b > b.b) {return 1;} - if (a.b < b.b) {return -1;} - return 0 - } - - tests.forEach(args => { - ngx.fetch.apply(r, args) - .then(rep => - rep.text().then(body => {rep.text = body; return rep;})) - .then(rep => { - results.push({b:rep.text, - c:rep.status, - u:rep.url}); - - if (results.length == tests.length) { - results.sort(cmp); - r.return(200, JSON.stringify(results)); - } - }) - .catch(e => { - r.return(400, `["\${e.message}"]`); - throw e; - }) - }) - - if (r.args.throw) { - throw 'Oops'; - } - } - - function str(v) { return v ? v : ''}; - - function loc(r) { - var v = r.variables; - var body = str(r.requestText); - var bar = str(r.headersIn.bar); - var c = r.headersIn.code ? Number(r.headersIn.code) : 200; - r.return(c, `\${v.request_method}:\${bar}:\${body}`); - } - - export default {njs: test_njs, body, broken, broken_response, body_special, - chain, chunked_ok, chunked_fail, header, header_iter, - multi, loc, property}; -EOF - -$t->try_run('no njs.fetch')->plan(34); - -$t->run_daemon(\&http_daemon, port(8082)); -$t->waitforsocket('127.0.0.1:' . port(8082)); - -############################################################################### - -like(http_get('/body?getter=arrayBuffer&loc=loc'), qr/200 OK.*"GET::"$/s, - 'fetch body arrayBuffer'); -like(http_get('/body?getter=text&loc=loc'), qr/200 OK.*"GET::"$/s, - 'fetch body text'); -like(http_get('/body?getter=json&loc=json&path=b.c'), - qr/200 OK.*"FIELD"$/s, 'fetch body json'); -like(http_get('/body?getter=json&loc=loc'), qr/501/s, - 'fetch body json invalid'); -like(http_get('/body_special?loc=parted'), qr/200 OK.*X{32000}$/s, - 'fetch body parted'); -like(http_get('/property?pr=bodyUsed'), qr/false$/s, - 'fetch bodyUsed false'); -like(http_get('/property?pr=bodyUsed&readBody=1'), qr/true$/s, - 'fetch bodyUsed true'); -like(http_get('/property?pr=ok'), qr/200 OK.*true$/s, - 'fetch ok true'); -like(http_get('/property?pr=ok&code=401'), qr/200 OK.*false$/s, - 'fetch ok false'); -like(http_get('/property?pr=redirected'), qr/200 OK.*false$/s, - 'fetch redirected false'); -like(http_get('/property?pr=statusText'), qr/200 OK.*OK$/s, - 'fetch statusText OK'); -like(http_get('/property?pr=statusText&code=403'), qr/200 OK.*Forbidden$/s, - 'fetch statusText Forbidden'); -like(http_get('/property?pr=type'), qr/200 OK.*basic$/s, - 'fetch type'); -like(http_get('/header?loc=duplicate_header&h=BAR'), qr/200 OK.*c$/s, - 'fetch header'); -like(http_get('/header?loc=duplicate_header&h=BARR'), qr/200 OK.*null$/s, - 'fetch no header'); -like(http_get('/header?loc=duplicate_header&h=foo'), qr/200 OK.*a, ?b$/s, - 'fetch header duplicate'); -like(http_get('/header?loc=duplicate_header&h=BAR&method=getAll'), - qr/200 OK.*\['c']$/s, 'fetch getAll header'); -like(http_get('/header?loc=duplicate_header&h=BARR&method=getAll'), - qr/200 OK.*\[]$/s, 'fetch getAll no header'); -like(http_get('/header?loc=duplicate_header&h=FOO&method=getAll'), - qr/200 OK.*\['a','b']$/s, 'fetch getAll duplicate'); -like(http_get('/header?loc=duplicate_header&h=bar&method=has'), - qr/200 OK.*true$/s, 'fetch header has'); -like(http_get('/header?loc=duplicate_header&h=buz&method=has'), - qr/200 OK.*false$/s, 'fetch header does not have'); -like(http_get('/header?loc=chunked/big&h=BAR&readBody=1'), qr/200 OK.*xxx$/s, - 'fetch chunked header'); -is(get_json('/multi'), - '[{"b":"GET::","c":201,"u":"http://127.0.0.1:'.$p0.'/loc"},' . - '{"b":"PATCH:xxx:","c":200,"u":"http://127.0.0.1:'.$p1.'/loc"},' . - '{"b":"POST::OK","c":401,"u":"http://127.0.0.1:'.$p0.'/loc"}]', - 'fetch multi'); -like(http_get('/multi?throw=1'), qr/500/s, 'fetch destructor'); -like(http_get('/broken'), qr/200/s, 'fetch broken'); -like(http_get('/broken_response'), qr/200/s, 'fetch broken response'); -like(http_get('/chunked_ok'), qr/200/s, 'fetch chunked ok'); -like(http_get('/chunked_fail'), qr/200/s, 'fetch chunked fail'); -like(http_get('/chain'), qr/200 OK.*SUCCESS$/s, 'fetch chain'); - -TODO: { -todo_skip 'leaves coredump', 1 unless $ENV{TEST_NGINX_UNSAFE} - or has_version('0.7.4'); - -like(http_get('/header_iter?loc=duplicate_header_large'), - qr/\['A:a','B:a','C:a','D:a','E:a','F:a','G:a','H:a','Moo:a, ?b']$/s, - 'fetch header duplicate large'); - -} - -TODO: { -local $TODO = 'not yet' unless has_version('0.7.7'); - -like(http_get('/body_special?loc=no_content_length'), - qr/200 OK.*CONTENT-BODY$/s, 'fetch body without content-length'); -like(http_get('/body_special?loc=no_content_length/parted'), - qr/200 OK.*X{32000}$/s, 'fetch body without content-length parted'); - -} - -TODO: { -local $TODO = 'not yet' unless has_version('0.7.8'); - -like(http_get('/body_special?loc=head&method=HEAD'), - qr/200 OK.*$/s, 'fetch head method'); -like(http_get('/body_special?loc=length&method=head'), - qr/200 OK.*$/s, 'fetch head method lower case'); - -} - -############################################################################### - -sub has_version { - my $need = shift; - - http_get('/njs') =~ /^([.0-9]+)$/m; - - my @v = split(/\./, $1); - my ($n, $v); - - for $n (split(/\./, $need)) { - $v = shift @v || 0; - return 0 if $n > $v; - return 1 if $v > $n; - } - - return 1; -} - -############################################################################### - -sub recode { - my $json; - eval { $json = JSON::PP::decode_json(shift) }; - - if ($@) { - return ""; - } - - JSON::PP->new()->canonical()->encode($json); -} - -sub get_json { - http_get(shift) =~ /\x0d\x0a?\x0d\x0a?(.*)/ms; - recode($1); -} - -############################################################################### - -sub http_daemon { - my $port = shift; - - my $server = IO::Socket::INET->new( - Proto => 'tcp', - LocalAddr => '127.0.0.1:' . $port, - Listen => 5, - Reuse => 1 - ) or die "Can't create listening socket: $!\n"; - - local $SIG{PIPE} = 'IGNORE'; - - while (my $client = $server->accept()) { - $client->autoflush(1); - - my $headers = ''; - my $uri = ''; - - while (<$client>) { - $headers .= $_; - last if (/^\x0d?\x0a?$/); - } - - $uri = $1 if $headers =~ /^\S+\s+([^ ]+)\s+HTTP/i; - - if ($uri eq '/status_line') { - print $client - "HTTP/1.1 2A"; - - } elsif ($uri eq '/content_length') { - print $client - "HTTP/1.1 200 OK" . CRLF . - "Content-Length: " . CRLF . - "Connection: close" . CRLF . - CRLF; - - } elsif ($uri eq '/header') { - print $client - "HTTP/1.1 200 OK" . CRLF . - "@#" . CRLF . - "Connection: close" . CRLF . - CRLF; - - } elsif ($uri eq '/duplicate_header') { - print $client - "HTTP/1.1 200 OK" . CRLF . - "Foo: a" . CRLF . - "bar: c" . CRLF . - "Foo: b" . CRLF . - "Connection: close" . CRLF . - CRLF; - - } elsif ($uri eq '/duplicate_header_large') { - print $client - "HTTP/1.1 200 OK" . CRLF . - "A: a" . CRLF . - "B: a" . CRLF . - "C: a" . CRLF . - "D: a" . CRLF . - "E: a" . CRLF . - "F: a" . CRLF . - "G: a" . CRLF . - "H: a" . CRLF . - "Moo: a" . CRLF . - "Moo: b" . CRLF . - "Connection: close" . CRLF . - CRLF; - - } elsif ($uri eq '/headers') { - print $client - "HTTP/1.1 200 OK" . CRLF . - "Connection: close" . CRLF; - - } elsif ($uri eq '/length') { - print $client - "HTTP/1.1 200 OK" . CRLF . - "Content-Length: 100" . CRLF . - "Connection: close" . CRLF . - CRLF . - "unfinished" . CRLF; - - } elsif ($uri eq '/head') { - print $client - "HTTP/1.1 200 OK" . CRLF . - "Content-Length: 100" . CRLF . - "Connection: close" . CRLF . - CRLF; - - } elsif ($uri eq '/parted') { - print $client - "HTTP/1.1 200 OK" . CRLF . - "Content-Length: 32000" . CRLF . - "Connection: close" . CRLF . - CRLF; - - for (1 .. 4) { - select undef, undef, undef, 0.01; - print $client "X" x 8000; - } - - } elsif ($uri eq '/no_content_length') { - print $client - "HTTP/1.1 200 OK" . CRLF . - "Connection: close" . CRLF . - CRLF . - "CONTENT-BODY"; - - } elsif ($uri eq '/no_content_length/parted') { - print $client - "HTTP/1.1 200 OK" . CRLF . - "Connection: close" . CRLF . - CRLF; - - for (1 .. 4) { - select undef, undef, undef, 0.01; - print $client "X" x 8000; - } - - } elsif ($uri eq '/big') { - print $client - "HTTP/1.1 200 OK" . CRLF . - "Content-Length: 100100" . CRLF . - "Connection: close" . CRLF . - CRLF; - for (1 .. 1000) { - print $client ("X" x 98) . CRLF; - } - print $client "unfinished" . CRLF; - - } elsif ($uri eq '/big/ok') { - print $client - "HTTP/1.1 200 OK" . CRLF . - "Content-Length: 100010" . CRLF . - "Connection: close" . CRLF . - CRLF; - for (1 .. 1000) { - print $client ("X" x 98) . CRLF; - } - print $client "finished" . CRLF; - - } elsif ($uri eq '/chunked') { - print $client - "HTTP/1.1 200 OK" . CRLF . - "Transfer-Encoding: chunked" . CRLF . - "Connection: close" . CRLF . - CRLF . - "ff" . CRLF . - "unfinished" . CRLF; - - } elsif ($uri eq '/chunked/ok') { - print $client - "HTTP/1.1 200 OK" . CRLF . - "Transfer-Encoding: chunked" . CRLF . - "Connection: close" . CRLF . - CRLF . - "a" . CRLF . - "finished" . CRLF . - CRLF . "0" . CRLF . CRLF; - } elsif ($uri eq '/chunked/big') { - print $client - "HTTP/1.1 200 OK" . CRLF . - "Transfer-Encoding: chunked" . CRLF . - "Bar: xxx" . CRLF . - "Connection: close" . CRLF . - CRLF; - - for (1 .. 100) { - print $client "ff" . CRLF . ("X" x 255) . CRLF; - } - - print $client "0" . CRLF . CRLF; - } - } -} - -############################################################################### diff --git a/js_fetch_https.t b/js_fetch_https.t deleted file mode 100644 --- a/js_fetch_https.t +++ /dev/null @@ -1,304 +0,0 @@ -#!/usr/bin/perl - -# (C) Antoine Bonavita -# (C) Nginx, Inc. - -# Tests for http njs module, fetch method, https support. - -############################################################################### - -use warnings; -use strict; - -use Test::More; - -BEGIN { use FindBin; chdir($FindBin::Bin); } - -use lib 'lib'; -use Test::Nginx; - -############################################################################### - -select STDERR; $| = 1; -select STDOUT; $| = 1; - -my $t = Test::Nginx->new()->has(qw/http http_ssl rewrite/) - ->write_file_expand('nginx.conf', <<'EOF'); - -%%TEST_GLOBALS%% - -daemon off; - -events { -} - -http { - %%TEST_GLOBALS_HTTP%% - - js_import test.js; - - server { - listen 127.0.0.1:8080; - server_name localhost; - - resolver 127.0.0.1:%%PORT_8981_UDP%%; - resolver_timeout 1s; - - location /njs { - js_content test.njs; - } - - location /https { - js_content test.https; - } - - location /https.myca { - js_content test.https; - - js_fetch_ciphers HIGH:!aNull:!MD5; - js_fetch_protocols TLSv1.1 TLSv1.2; - js_fetch_trusted_certificate myca.crt; - } - - location /https.myca.short { - js_content test.https; - - js_fetch_verify_depth 0; - js_fetch_trusted_certificate myca.crt; - } - } - - server { - listen 127.0.0.1:8081 ssl default; - server_name default.example.com; - - ssl_certificate default.example.com.chained.crt; - ssl_certificate_key default.example.com.key; - - location /loc { - return 200 "You are at default.example.com."; - } - } - - server { - listen 127.0.0.1:8081 ssl; - server_name 1.example.com; - - ssl_certificate 1.example.com.chained.crt; - ssl_certificate_key 1.example.com.key; - - location /loc { - return 200 "You are at 1.example.com."; - } - } -} - -EOF - -my $p1 = port(8081); - -$t->write_file('test.js', < reply.text()) - .then(body => r.return(200, body)) - .catch(e => r.return(501, e.message)) - } - - export default {njs: test_njs, https}; -EOF - -my $d = $t->testdir(); - -$t->write_file('openssl.conf', <write_file('myca.conf', <>$d/openssl.out 2>&1") == 0 - or die "Can't create self-signed certificate for CA: $!\n"; - -foreach my $name ('intermediate', 'default.example.com', '1.example.com') { - system("openssl req -new " - . "-config $d/openssl.conf -subj /CN=$name/ " - . "-out $d/$name.csr -keyout $d/$name.key " - . ">>$d/openssl.out 2>&1") == 0 - or die "Can't create certificate signing req for $name: $!\n"; -} - -$t->write_file('certserial', '1000'); -$t->write_file('certindex', ''); - -system("openssl ca -batch -config $d/myca.conf " - . "-keyfile $d/myca.key -cert $d/myca.crt " - . "-subj /CN=intermediate/ -in $d/intermediate.csr " - . "-out $d/intermediate.crt " - . ">>$d/openssl.out 2>&1") == 0 - or die "Can't sign certificate for intermediate: $!\n"; - -foreach my $name ('default.example.com', '1.example.com') { - system("openssl ca -batch -config $d/myca.conf " - . "-keyfile $d/intermediate.key -cert $d/intermediate.crt " - . "-subj /CN=$name/ -in $d/$name.csr -out $d/$name.crt " - . ">>$d/openssl.out 2>&1") == 0 - or die "Can't sign certificate for $name $!\n"; - $t->write_file("$name.chained.crt", $t->read_file("$name.crt") - . $t->read_file('intermediate.crt')); -} - -$t->try_run('no njs.fetch')->plan(7); - -$t->run_daemon(\&dns_daemon, port(8981), $t); -$t->waitforfile($t->testdir . '/' . port(8981)); - -############################################################################### - -local $TODO = 'not yet' unless has_version('0.7.0'); - -like(http_get('/https?domain=default.example.com&verify=false'), - qr/You are at default.example.com.$/s, 'fetch https'); -like(http_get('/https?domain=127.0.0.1&verify=false'), - qr/You are at default.example.com.$/s, 'fetch https by IP'); -like(http_get('/https?domain=1.example.com&verify=false'), - qr/You are at 1.example.com.$/s, 'fetch tls extension'); -like(http_get('/https.myca?domain=default.example.com'), - qr/You are at default.example.com.$/s, 'fetch https trusted certificate'); -like(http_get('/https.myca?domain=localhost'), - qr/connect failed/s, 'fetch https wrong CN certificate'); -like(http_get('/https?domain=default.example.com'), - qr/connect failed/s, 'fetch https non trusted CA'); -like(http_get('/https.myca.short?domain=default.example.com'), - qr/connect failed/s, 'fetch https CA too far'); - -############################################################################### - -sub has_version { - my $need = shift; - - http_get('/njs') =~ /^([.0-9]+)$/m; - - my @v = split(/\./, $1); - my ($n, $v); - - for $n (split(/\./, $need)) { - $v = shift @v || 0; - return 0 if $n > $v; - return 1 if $v > $n; - } - - return 1; -} - -############################################################################### - -sub reply_handler { - my ($recv_data, $port, %extra) = @_; - - my (@name, @rdata); - - use constant NOERROR => 0; - use constant A => 1; - use constant IN => 1; - - # default values - - my ($hdr, $rcode, $ttl) = (0x8180, NOERROR, 3600); - - # decode name - - my ($len, $offset) = (undef, 12); - while (1) { - $len = unpack("\@$offset C", $recv_data); - last if $len == 0; - $offset++; - push @name, unpack("\@$offset A$len", $recv_data); - $offset += $len; - } - - $offset -= 1; - my ($id, $type, $class) = unpack("n x$offset n2", $recv_data); - - my $name = join('.', @name); - - if ($type == A) { - push @rdata, rd_addr($ttl, '127.0.0.1'); - } - - $len = @name; - pack("n6 (C/a*)$len x n2", $id, $hdr | $rcode, 1, scalar @rdata, - 0, 0, @name, $type, $class) . join('', @rdata); -} - -sub rd_addr { - my ($ttl, $addr) = @_; - - my $code = 'split(/\./, $addr)'; - - return pack 'n3N', 0xc00c, A, IN, $ttl if $addr eq ''; - - pack 'n3N nC4', 0xc00c, A, IN, $ttl, eval "scalar $code", eval($code); -} - -sub dns_daemon { - my ($port, $t) = @_; - - my ($data, $recv_data); - my $socket = IO::Socket::INET->new( - LocalAddr => '127.0.0.1', - LocalPort => $port, - Proto => 'udp', - ) - or die "Can't create listening socket: $!\n"; - - local $SIG{PIPE} = 'IGNORE'; - - # signal we are ready - - open my $fh, '>', $t->testdir() . '/' . $port; - close $fh; - - while (1) { - $socket->recv($recv_data, 65536); - $data = reply_handler($recv_data, $port); - $socket->send($data); - } -} - -############################################################################### diff --git a/js_fetch_objects.t b/js_fetch_objects.t deleted file mode 100644 --- a/js_fetch_objects.t +++ /dev/null @@ -1,520 +0,0 @@ -#!/usr/bin/perl - -# (C) Dmitry Volyntsev -# (C) Nginx, Inc. - -# Tests for http njs module, fetch objects. - -############################################################################### - -use warnings; -use strict; - -use Test::More; - -BEGIN { use FindBin; chdir($FindBin::Bin); } - -use lib 'lib'; -use Test::Nginx; - -############################################################################### - -select STDERR; $| = 1; -select STDOUT; $| = 1; - -my $t = Test::Nginx->new()->has(qw/http rewrite/) - ->write_file_expand('nginx.conf', <<'EOF'); - -%%TEST_GLOBALS%% - -daemon off; - -events { -} - -http { - %%TEST_GLOBALS_HTTP%% - - js_import test.js; - - server { - listen 127.0.0.1:8080; - server_name localhost; - - location /njs { - js_content test.njs; - } - - location /headers { - js_content test.headers; - } - - location /request { - js_content test.request; - } - - location /response { - js_content test.response; - } - - location /fetch { - js_content test.fetch; - } - - location /fetch_multi_header { - js_content test.fetch_multi_header; - } - - location /method { - return 200 $request_method; - } - - location /header { - return 200 $http_a; - } - - location /body { - js_content test.body; - } - } -} - -EOF - -my $p0 = port(8080); - -$t->write_file('test.js', < { - var h = new Headers(); - return h.get('a'); - }, null], - ['normal', () => { - var h = new Headers({a: 'X', b: 'Z'}); - return `\${h.get('a')} \${h.get('B')}`; - }, 'X Z'], - ['trim value', () => { - var h = new Headers({a: ' X '}); - return h.get('a'); - }, 'X'], - ['invalid header name', () => { - const valid = "!#\$\%&'*+-.^_`|~0123456789"; - - for (var i = 0; i < 128; i++) { - var c = String.fromCodePoint(i); - - if (valid.indexOf(c) != -1 || /[a-zA-Z]+/.test(c)) { - continue; - } - - try { - new Headers([[c, 'a']]); - throw new Error( - `header with "\${c}" (\${i}) should throw`); - - } catch (e) { - if (e.message != 'invalid header name') { - throw e; - } - } - } - - return 'OK'; - - }, 'OK'], - ['invalid header value', () => { - var h = new Headers({A: 'aa\x00a'}); - }, 'invalid header value'], - ['combine', () => { - var h = new Headers({a: 'X', A: 'Z'}); - return h.get('a'); - }, 'X, Z'], - ['combine2', () => { - var h = new Headers([['A', 'x'], ['a', 'z']]); - return h.get('a'); - }, 'x, z'], - ['combine3', () => { - var h = new Headers(); - h.append('a', 'A'); - h.append('a', 'B'); - h.append('a', 'C'); - h.append('a', 'D'); - h.append('a', 'E'); - h.append('a', 'F'); - return h.get('a'); - }, 'A, B, C, D, E, F'], - ['getAll', () => { - var h = new Headers({a: 'X', A: 'Z'}); - return njs.dump(h.getAll('a')); - }, "['X','Z']"], - ['inherit', () => { - var h = new Headers({a: 'X', b: 'Y'}); - var h2 = new Headers(h); - h2.append('c', 'Z'); - return h2.has('a') && h2.has('B') && h2.has('c'); - }, true], - ['delete', () => { - var h = new Headers({a: 'X', b: 'Z'}); - h.delete('b'); - return h.get('a') && !h.get('b'); - }, true], - ['forEach', () => { - var r = []; - var h = new Headers({a: '0', b: '1', c: '2'}); - h.delete('b'); - h.append('z', '3'); - h.append('a', '4'); - h.append('q', '5'); - h.forEach((v, k) => { r.push(`\${v}:\${k}`)}) - return r.join('|'); - }, 'a:0, 4|c:2|q:5|z:3'], - ['set', () => { - var h = new Headers([['A', 'x'], ['a', 'y'], ['a', 'z']]); - h.set('a', '#'); - return h.get('a'); - }, '#'], - ]; - - run(r, tests); - } - - async function request(r) { - const tests = [ - ['empty', () => { - try { - new Request(); - throw new Error(`Request() should throw`); - - } catch (e) { - if (e.message != '1st argument is required') { - throw e; - } - } - - return 'OK'; - - }, 'OK'], - ['normal', () => { - var r = new Request("http://nginx.org", - {headers: {a: 'X', b: 'Y'}}); - return `\${r.url}: \${r.method} \${r.headers.a}`; - }, 'http://nginx.org: GET X'], - ['url trim', () => { - var r = new Request("\\x00\\x01\\x02\\x03\\x05\\x06\\x07\\x08" - + "\\x09\\x0a\\x0b\\x0c\\x0d\\x0e\\x0f" - + "\\x10\\x11\\x12\\x13\\x14\\x15\\x16" - + "\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d" - + "\\x1e\\x1f\\x20http://nginx.org\\x00" - + "\\x01\\x02\\x03\\x05\\x06\\x07\\x08" - + "\\x09\\x0a\\x0b\\x0c\\x0d\\x0e\\x0f" - + "\\x10\\x11\\x12\\x13\\x14\\x15\\x16" - + "\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d" - + "\\x1e\\x1f\\x20"); - return r.url; - }, 'http://nginx.org'], - ['read only', () => { - var r = new Request("http://nginx.org"); - - const props = ['bodyUsed', 'cache', 'credentials', 'headers', - 'method', 'mode', 'url']; - try { - props.forEach(prop => { - r[prop] = 1; - throw new Error( - `setting read-only \${prop} should throw`); - }) - - } catch (e) { - if (!e.message.startsWith('Cannot assign to read-only p')) { - throw e; - } - } - - return 'OK'; - - }, 'OK'], - ['cache', () => { - const props = ['default', 'no-cache', 'no-store', 'reload', - 'force-cache', 'only-if-cached', '#']; - try { - props.forEach(cv => { - var r = new Request("http://nginx.org", {cache: cv}); - if (r.cache != cv) { - throw new Error(`r.cache != \${cv}`); - } - }) - - } catch (e) { - if (!e.message.startsWith('unknown cache type: #')) { - throw e; - } - } - - return 'OK'; - - }, 'OK'], - ['credentials', () => { - const props = ['omit', 'include', 'same-origin', '#']; - try { - props.forEach(cr => { - var r = new Request("http://nginx.org", - {credentials: cr}); - if (r.credentials != cr) { - throw new Error(`r.credentials != \${cr}`); - } - }) - - } catch (e) { - if (!e.message.startsWith('unknown credentials type: #')) { - throw e; - } - } - - return 'OK'; - - }, 'OK'], - ['method', () => { - const methods = ['get', 'hEad', 'Post', 'OPTIONS', 'PUT', - 'DELETE', 'CONNECT']; - try { - methods.forEach(m => { - var r = new Request("http://nginx.org", {method: m}); - if (r.method != m.toUpperCase()) { - throw new Error(`r.method != \${m}`); - } - }) - - } catch (e) { - if (!e.message.startsWith('forbidden method: CONNECT')) { - throw e; - } - } - - return 'OK'; - - }, 'OK'], - ['mode', () => { - const props = ['same-origin', 'cors', 'no-cors', 'navigate', - 'websocket', '#']; - try { - props.forEach(m => { - var r = new Request("http://nginx.org", {mode: m}); - if (r.mode != m) { - throw new Error(`r.mode != \${m}`); - } - }) - - } catch (e) { - if (!e.message.startsWith('unknown mode type: #')) { - throw e; - } - } - - return 'OK'; - - }, 'OK'], - ['inherit', () => { - var r = new Request("http://nginx.org", - {headers: {a: 'X', b: 'Y'}}); - var r2 = new Request(r); - r2.headers.append('a', 'Z') - return `\${r2.url}: \${r2.headers.get('a')}`; - }, 'http://nginx.org: X, Z'], - ['inherit2', () => { - var r = new Request("http://nginx.org", - {headers: {a: 'X', b: 'Y'}}); - var r2 = new Request(r); - r2.headers.append('a', 'Z') - return `\${r.url}: \${r.headers.get('a')}`; - }, 'http://nginx.org: X'], - ['inherit3', () => { - var h = new Headers(); - h.append('a', 'X'); - h.append('a', 'Z'); - var r = new Request("http://nginx.org", {headers: h}); - return `\${r.url}: \${r.headers.get('a')}`; - }, 'http://nginx.org: X, Z'], - ['content type', async () => { - var r = new Request("http://nginx.org", - {body: 'ABC', method: 'POST'}); - var body = await r.text(); - return `\${body}: \${r.headers.get('Content-Type')}`; - }, 'ABC: text/plain;charset=UTF-8'], - ['GET body', () => { - try { - var r = new Request("http://nginx.org", {body: 'ABC'}); - - } catch (e) { - if (!e.message.startsWith('Request body incompatible w')) { - throw e; - } - } - - return 'OK'; - - }, 'OK'], - ]; - - run(r, tests); - } - - async function response(r) { - const tests = [ - ['empty', async () => { - var r = new Response(); - var body = await r.text(); - return `\${r.url}: \${r.status} \${body} \${r.headers.get('a')}`; - }, ': 200 null'], - ['normal', async () => { - var r = new Response("ABC", {headers: {a: 'X', b: 'Y'}}); - var body = await r.text(); - return `\${r.url}: \${r.status} \${body} \${r.headers.get('a')}`; - }, ': 200 ABC X'], - ['headers', async () => { - var r = new Response(null, - {headers: new Headers({a: 'X', b: 'Y'})}); - var body = await r.text(); - return `\${r.url}: \${body} \${r.headers.get('b')}`; - }, ': Y'], - ['json', async () => { - var r = new Response('{"a": {"b": 42}}'); - var json = await r.json(); - return json.a.b; - }, 42], - ['statusText', () => { - const statuses = ['status text', 'aa\\u0000a']; - try { - statuses.forEach(s => { - var r = new Response(null, {statusText: s}); - if (r.statusText != s) { - throw new Error(`r.statusText != \${s}`); - } - }) - - } catch (e) { - if (!e.message.startsWith('invalid Response statusText')) { - throw e; - } - } - - return 'OK'; - - }, 'OK'], - ]; - - run(r, tests); - } - - async function fetch(r) { - const tests = [ - ['method', async () => { - var req = new Request("http://127.0.0.1:$p0/method", - {method: 'PUT'}); - var r = await ngx.fetch(req); - var body = await r.text(); - return `\${r.url}: \${r.status} \${body} \${r.headers.get('a')}`; - }, 'http://127.0.0.1:$p0/method: 200 PUT null'], - ['request body', async () => { - var req = new Request("http://127.0.0.1:$p0/body", - {body: 'foo'}); - var r = await ngx.fetch(req); - var body = await r.text(); - return `\${r.url}: \${r.status} \${body}`; - }, 'http://127.0.0.1:$p0/body: 201 foo'], - ]; - - run(r, tests); - } - - async function fetch_multi_header(r) { - const tests = [ - ['request multi header', async () => { - var h = new Headers({a: 'X'}); - h.append('a', 'Z'); - var req = new Request("http://127.0.0.1:$p0/header", - {headers: h}); - var r = await ngx.fetch(req); - var body = await r.text(); - return `\${r.url}: \${r.status} \${body}`; - }, 'http://127.0.0.1:$p0/header: 200 X, Z'], - ]; - - run(r, tests); - } - - export default {njs: test_njs, body, headers, request, response, fetch, - fetch_multi_header}; -EOF - -$t->try_run('no njs')->plan(5); - -############################################################################### - -local $TODO = 'not yet' unless has_version('0.7.10'); - -like(http_get('/headers'), qr/200 OK/s, 'headers tests'); -like(http_get('/request'), qr/200 OK/s, 'request tests'); -like(http_get('/response'), qr/200 OK/s, 'response tests'); -like(http_get('/fetch'), qr/200 OK/s, 'fetch tests'); - -TODO: { -local $TODO = 'not yet' unless $t->has_version('1.23.0'); - -like(http_get('/fetch_multi_header'), qr/200 OK/s, - 'fetch multi header tests'); - -} - -############################################################################### - -sub has_version { - my $need = shift; - - http_get('/njs') =~ /^([.0-9]+)$/m; - - my @v = split(/\./, $1); - my ($n, $v); - - for $n (split(/\./, $need)) { - $v = shift @v || 0; - return 0 if $n > $v; - return 1 if $v > $n; - } - - return 1; -} - -############################################################################### diff --git a/js_fetch_resolver.t b/js_fetch_resolver.t deleted file mode 100644 --- a/js_fetch_resolver.t +++ /dev/null @@ -1,231 +0,0 @@ -#!/usr/bin/perl - -# (C) Dmitry Volyntsev -# (C) Nginx, Inc. - -# Tests for http njs module, fetch method, dns support. - -############################################################################### - -use warnings; -use strict; - -use Test::More; - -use IO::Select; - -BEGIN { use FindBin; chdir($FindBin::Bin); } - -use lib 'lib'; -use Test::Nginx; - -############################################################################### - -select STDERR; $| = 1; -select STDOUT; $| = 1; - -plan(skip_all => '127.0.0.2 local address required') - unless defined IO::Socket::INET->new( LocalAddr => '127.0.0.2' ); - -my $t = Test::Nginx->new()->has(qw/http/) - ->write_file_expand('nginx.conf', <<'EOF'); - -%%TEST_GLOBALS%% - -daemon off; - -events { -} - -http { - %%TEST_GLOBALS_HTTP%% - - js_import test.js; - - server { - listen 127.0.0.1:8080; - server_name localhost; - - location /njs { - js_content test.njs; - } - - location /dns { - js_content test.dns; - - resolver 127.0.0.1:%%PORT_8981_UDP%%; - resolver_timeout 1s; - } - } - - server { - listen 127.0.0.1:8080; - server_name aaa; - - location /loc { - js_content test.loc; - } - } - - server { - listen 127.0.0.1:8080; - server_name many; - - location /loc { - js_content test.loc; - } - } -} - -EOF - -my $p0 = port(8080); - -$t->write_file('test.js', < reply.text()) - .then(body => r.return(200, body)) - .catch(e => r.return(501, e.message)) - } - - function str(v) { return v ? v : ''}; - - function loc(r) { - var v = r.variables; - var body = str(r.requestText); - var foo = str(r.headersIn.foo); - var bar = str(r.headersIn.bar); - var c = r.headersIn.code ? Number(r.headersIn.code) : 200; - r.return(c, `\${v.host}:\${v.request_method}:\${foo}:\${bar}:\${body}`); - } - - export default {njs: test_njs, dns, loc}; -EOF - -$t->try_run('no njs.fetch')->plan(3); - -$t->run_daemon(\&dns_daemon, port(8981), $t); -$t->waitforfile($t->testdir . '/' . port(8981)); - -############################################################################### - -like(http_get('/dns?domain=aaa'), qr/aaa:GET:::$/s, 'fetch dns aaa'); -like(http_get('/dns?domain=many'), qr/many:GET:::$/s, 'fetch dns many'); -like(http_get('/dns?domain=unknown'), qr/"unknown" could not be resolved/s, - 'fetch dns unknown'); - -############################################################################### - -sub reply_handler { - my ($recv_data, $port, %extra) = @_; - - my (@name, @rdata); - - use constant NOERROR => 0; - use constant FORMERR => 1; - use constant SERVFAIL => 2; - use constant NXDOMAIN => 3; - - use constant A => 1; - - use constant IN => 1; - - # default values - - my ($hdr, $rcode, $ttl) = (0x8180, NOERROR, 3600); - - # decode name - - my ($len, $offset) = (undef, 12); - while (1) { - $len = unpack("\@$offset C", $recv_data); - last if $len == 0; - $offset++; - push @name, unpack("\@$offset A$len", $recv_data); - $offset += $len; - } - - $offset -= 1; - my ($id, $type, $class) = unpack("n x$offset n2", $recv_data); - - my $name = join('.', @name); - - if ($name eq 'aaa' && $type == A) { - push @rdata, rd_addr($ttl, '127.0.0.1'); - - } elsif ($name eq 'many' && $type == A) { - push @rdata, rd_addr($ttl, '127.0.0.2'); - push @rdata, rd_addr($ttl, '127.0.0.1'); - } - - $len = @name; - pack("n6 (C/a*)$len x n2", $id, $hdr | $rcode, 1, scalar @rdata, - 0, 0, @name, $type, $class) . join('', @rdata); -} - -sub rd_addr { - my ($ttl, $addr) = @_; - - my $code = 'split(/\./, $addr)'; - - return pack 'n3N', 0xc00c, A, IN, $ttl if $addr eq ''; - - pack 'n3N nC4', 0xc00c, A, IN, $ttl, eval "scalar $code", eval($code); -} - -sub dns_daemon { - my ($port, $t, %extra) = @_; - - my ($data, $recv_data); - my $socket = IO::Socket::INET->new( - LocalAddr => '127.0.0.1', - LocalPort => $port, - Proto => 'udp', - ) - or die "Can't create listening socket: $!\n"; - - my $sel = IO::Select->new($socket); - - local $SIG{PIPE} = 'IGNORE'; - - # signal we are ready - - open my $fh, '>', $t->testdir() . '/' . $port; - close $fh; - - while (my @ready = $sel->can_read) { - foreach my $fh (@ready) { - if ($socket == $fh) { - $fh->recv($recv_data, 65536); - $data = reply_handler($recv_data, $port); - $fh->send($data); - - } else { - $fh->recv($recv_data, 65536); - unless (length $recv_data) { - $sel->remove($fh); - $fh->close; - next; - } - -again: - my $len = unpack("n", $recv_data); - $data = substr $recv_data, 2, $len; - $data = reply_handler($data, $port, tcp => 1); - $data = pack("n", length $data) . $data; - $fh->send($data); - $recv_data = substr $recv_data, 2 + $len; - goto again if length $recv_data; - } - } - } -} - -############################################################################### diff --git a/js_fetch_timeout.t b/js_fetch_timeout.t deleted file mode 100644 --- a/js_fetch_timeout.t +++ /dev/null @@ -1,119 +0,0 @@ -#!/usr/bin/perl - -# (C) Dmitry Volyntsev -# (C) Nginx, Inc. - -# Tests for http njs module, fetch method timeout. - -############################################################################### - -use warnings; -use strict; - -use Test::More; - -use Socket qw/ CRLF /; - -BEGIN { use FindBin; chdir($FindBin::Bin); } - -use lib 'lib'; -use Test::Nginx; - -############################################################################### - -select STDERR; $| = 1; -select STDOUT; $| = 1; - -my $t = Test::Nginx->new()->has(qw/http/) - ->write_file_expand('nginx.conf', <<'EOF'); - -%%TEST_GLOBALS%% - -daemon off; - -events { -} - -http { - %%TEST_GLOBALS_HTTP%% - - js_import test.js; - - server { - listen 127.0.0.1:8080; - server_name localhost; - - location /njs { - js_content test.njs; - } - - location /normal_timeout { - js_content test.timeout_test; - } - - location /short_timeout { - js_fetch_timeout 200ms; - js_content test.timeout_test; - } - } - - server { - listen 127.0.0.1:8081; - server_name localhost; - - location /normal_reply { - js_content test.normal_reply; - } - - location /delayed_reply { - js_content test.delayed_reply; - } - } -} - -EOF - -my $p1 = port(8081); - -$t->write_file('test.js', < ngx.fetch(v))); - - let bs = rs.map(v => ({s: v.status, v: v.value ? v.value.headers.X - : v.reason})); - - r.return(200, njs.dump(bs)); - } - - function normal_reply(r) { - r.headersOut.X = 'N'; - r.return(200); - } - - function delayed_reply(r) { - r.headersOut.X = 'D'; - setTimeout((r) => { r.return(200); }, 250, r, 0); - } - - export default {njs: test_njs, timeout_test, normal_reply, delayed_reply}; -EOF - -$t->try_run('no js_fetch_timeout')->plan(2); - -############################################################################### - -like(http_get('/normal_timeout'), - qr/\[\{s:'fulfilled',v:'N'},\{s:'fulfilled',v:'D'}]$/s, - 'normal timeout'); -like(http_get('/short_timeout'), - qr/\[\{s:'fulfilled',v:'N'},\{s:'rejected',v:Error: read timed out}]$/s, - 'short timeout'); - -############################################################################### diff --git a/js_fetch_verify.t b/js_fetch_verify.t deleted file mode 100644 --- a/js_fetch_verify.t +++ /dev/null @@ -1,192 +0,0 @@ -#!/usr/bin/perl - -# (C) Sergey Kandaurov -# (C) Nginx, Inc. - -# Tests for http njs module, fetch method, backend certificate verification. - -############################################################################### - -use warnings; -use strict; - -use Test::More; - -BEGIN { use FindBin; chdir($FindBin::Bin); } - -use lib 'lib'; -use Test::Nginx; - -############################################################################### - -select STDERR; $| = 1; -select STDOUT; $| = 1; - -my $t = Test::Nginx->new()->has(qw/http http_ssl/) - ->write_file_expand('nginx.conf', <<'EOF'); - -%%TEST_GLOBALS%% - -daemon off; - -events { -} - -http { - %%TEST_GLOBALS_HTTP%% - - js_import test.js; - - server { - listen 127.0.0.1:8080; - server_name localhost; - - resolver 127.0.0.1:%%PORT_8981_UDP%%; - resolver_timeout 1s; - - location /njs { - js_content test.njs; - } - - location /https { - js_content test.https; - } - - location /https.verify_off { - js_content test.https; - js_fetch_verify off; - } - } - - server { - listen 127.0.0.1:8081 ssl; - server_name localhost; - - ssl_certificate localhost.crt; - ssl_certificate_key localhost.key; - } -} - -EOF - -my $p1 = port(8081); - -$t->write_file('test.js', < reply.text()) - .then(body => r.return(200, body)) - .catch(e => r.return(501, e.message)); - } - - export default {njs: test_njs, https}; -EOF - -$t->write_file('openssl.conf', <testdir(); - -foreach my $name ('localhost') { - system('openssl req -x509 -new ' - . "-config $d/openssl.conf -subj /CN=$name/ " - . "-out $d/$name.crt -keyout $d/$name.key " - . ">>$d/openssl.out 2>&1") == 0 - or die "Can't create certificate for $name: $!\n"; -} - -$t->try_run('no js_fetch_verify')->plan(2); - -$t->run_daemon(\&dns_daemon, port(8981), $t); -$t->waitforfile($t->testdir . '/' . port(8981)); - -############################################################################### - -like(http_get('/https'), qr/connect failed/, 'fetch verify error'); -like(http_get('/https.verify_off'), qr/200 OK/, 'fetch verify off'); - -############################################################################### - -sub reply_handler { - my ($recv_data, $port, %extra) = @_; - - my (@name, @rdata); - - use constant NOERROR => 0; - use constant A => 1; - use constant IN => 1; - - # default values - - my ($hdr, $rcode, $ttl) = (0x8180, NOERROR, 3600); - - # decode name - - my ($len, $offset) = (undef, 12); - while (1) { - $len = unpack("\@$offset C", $recv_data); - last if $len == 0; - $offset++; - push @name, unpack("\@$offset A$len", $recv_data); - $offset += $len; - } - - $offset -= 1; - my ($id, $type, $class) = unpack("n x$offset n2", $recv_data); - - my $name = join('.', @name); - - if ($type == A) { - push @rdata, rd_addr($ttl, '127.0.0.1'); - } - - $len = @name; - pack("n6 (C/a*)$len x n2", $id, $hdr | $rcode, 1, scalar @rdata, - 0, 0, @name, $type, $class) . join('', @rdata); -} - -sub rd_addr { - my ($ttl, $addr) = @_; - - my $code = 'split(/\./, $addr)'; - - return pack 'n3N', 0xc00c, A, IN, $ttl if $addr eq ''; - - pack 'n3N nC4', 0xc00c, A, IN, $ttl, eval "scalar $code", eval($code); -} - -sub dns_daemon { - my ($port, $t) = @_; - - my ($data, $recv_data); - my $socket = IO::Socket::INET->new( - LocalAddr => '127.0.0.1', - LocalPort => $port, - Proto => 'udp', - ) - or die "Can't create listening socket: $!\n"; - - local $SIG{PIPE} = 'IGNORE'; - - # signal we are ready - - open my $fh, '>', $t->testdir() . '/' . $port; - close $fh; - - while (1) { - $socket->recv($recv_data, 65536); - $data = reply_handler($recv_data, $port); - $socket->send($data); - } -} - -############################################################################### diff --git a/js_header_filter.t b/js_header_filter.t deleted file mode 100644 --- a/js_header_filter.t +++ /dev/null @@ -1,93 +0,0 @@ -#!/usr/bin/perl - -# (C) Dmitry Volyntsev -# (C) Nginx, Inc. - -# Tests for http njs module, header filter. - -############################################################################### - -use warnings; -use strict; - -use Test::More; - -BEGIN { use FindBin; chdir($FindBin::Bin); } - -use lib 'lib'; -use Test::Nginx; - -############################################################################### - -select STDERR; $| = 1; -select STDOUT; $| = 1; - -my $t = Test::Nginx->new()->has(qw/http proxy rewrite/) - ->write_file_expand('nginx.conf', <<'EOF'); - -%%TEST_GLOBALS%% - -daemon off; - -events { -} - -http { - %%TEST_GLOBALS_HTTP%% - - js_import test.js; - - server { - listen 127.0.0.1:8080; - server_name localhost; - - location /njs { - js_content test.njs; - } - - location /filter/ { - js_header_filter test.filter; - proxy_pass http://127.0.0.1:8081/; - } - } - - server { - listen 127.0.0.1:8081; - server_name localhost; - - location / { - add_header Set-Cookie "BB"; - add_header Set-Cookie "CCCC"; - - return 200; - } - } -} - -EOF - -$t->write_file('test.js', <v.length > len); - } - - export default {njs: test_njs, filter}; - -EOF - -$t->try_run('no njs header filter')->plan(2); - -############################################################################### - -like(http_get('/filter/?len=1'), qr/Set-Cookie: BB.*Set-Cookie: CCCC.*/ms, - 'all');; -unlike(http_get('/filter/?len=3'), qr/Set-Cookie: BB/, - 'filter'); - -############################################################################### diff --git a/js_header_filter_if.t b/js_header_filter_if.t deleted file mode 100644 --- a/js_header_filter_if.t +++ /dev/null @@ -1,95 +0,0 @@ -#!/usr/bin/perl - -# (C) Dmitry Volyntsev -# (C) Nginx, Inc. - -# Tests for http njs module, header filter, if context. - -############################################################################### - -use warnings; -use strict; - -use Test::More; - -BEGIN { use FindBin; chdir($FindBin::Bin); } - -use lib 'lib'; -use Test::Nginx; - -############################################################################### - -select STDERR; $| = 1; -select STDOUT; $| = 1; - -my $t = Test::Nginx->new()->has(qw/http proxy rewrite/) - ->write_file_expand('nginx.conf', <<'EOF'); - -%%TEST_GLOBALS%% - -daemon off; - -events { -} - -http { - %%TEST_GLOBALS_HTTP%% - - js_import test.js; - - server { - listen 127.0.0.1:8080; - server_name localhost; - - location /njs { - js_content test.njs; - } - - location / { - if ($arg_name ~ "add") { - js_header_filter test.add; - } - - js_header_filter test.add2; - - proxy_pass http://127.0.0.1:8081/; - } - } - - server { - listen 127.0.0.1:8081; - server_name localhost; - - location / { - return 200; - } - } -} - -EOF - -$t->write_file('test.js', <try_run('no njs header filter')->plan(2); - -############################################################################### - -like(http_get('/?name=add'), qr/Foo: bar/, 'header filter if'); -like(http_get('/'), qr/Bar: xxx/, 'header filter'); - -############################################################################### diff --git a/js_headers.t b/js_headers.t deleted file mode 100644 --- a/js_headers.t +++ /dev/null @@ -1,568 +0,0 @@ -#!/usr/bin/perl - -# (C) Dmitry Volyntsev -# (C) Nginx, Inc. - -# Tests for http njs module, working with headers. - -############################################################################### - -use warnings; -use strict; - -use Test::More; - -use Socket qw/ CRLF /; - -BEGIN { use FindBin; chdir($FindBin::Bin); } - -use lib 'lib'; -use Test::Nginx; - -############################################################################### - -select STDERR; $| = 1; -select STDOUT; $| = 1; - -my $t = Test::Nginx->new()->has(qw/http charset/) - ->write_file_expand('nginx.conf', <<'EOF'); - -%%TEST_GLOBALS%% - -daemon off; - -events { -} - -http { - %%TEST_GLOBALS_HTTP%% - - js_set $test_foo_in test.foo_in; - js_set $test_ifoo_in test.ifoo_in; - - js_import test.js; - - server { - listen 127.0.0.1:8080; - server_name localhost; - - location /njs { - js_content test.njs; - } - - location /content_length { - js_content test.content_length; - } - - location /content_length_arr { - js_content test.content_length_arr; - } - - location /content_length_keys { - js_content test.content_length_keys; - } - - location /content_type { - charset windows-1251; - - default_type text/plain; - js_content test.content_type; - } - - location /content_type_arr { - charset windows-1251; - - default_type text/plain; - js_content test.content_type_arr; - } - - location /content_encoding { - js_content test.content_encoding; - } - - location /content_encoding_arr { - js_content test.content_encoding_arr; - } - - location /headers_list { - js_content test.headers_list; - } - - location /foo_in { - return 200 $test_foo_in; - } - - location /ifoo_in { - return 200 $test_ifoo_in; - } - - location /hdr_in { - js_content test.hdr_in; - } - - location /raw_hdr_in { - js_content test.raw_hdr_in; - } - - location /hdr_out { - js_content test.hdr_out; - } - - location /raw_hdr_out { - js_content test.raw_hdr_out; - } - - location /hdr_out_array { - js_content test.hdr_out_array; - } - - location /hdr_out_set_cookie { - js_content test.hdr_out_set_cookie; - } - - location /hdr_out_single { - js_content test.hdr_out_single; - } - - location /ihdr_out { - js_content test.ihdr_out; - } - - location /hdr_sorted_keys { - js_content test.hdr_sorted_keys; - } - - location /hdr_out_special_set { - js_content test.hdr_out_special_set; - } - - location /copy_subrequest_hdrs { - js_content test.copy_subrequest_hdrs; - } - - location = /subrequest { - internal; - - js_content test.subrequest; - } - } -} - -EOF - -$t->write_file('test.js', <= 0x000705) { - var clength = r.headersOut['Content-Length']; - if (clength !== undefined) { - r.return(500, `Content-Length "\${clength}" is not empty`); - return; - } - } - - delete r.headersOut['Content-Length']; - r.headersOut['Content-Length'] = ''; - r.headersOut['Content-Length'] = 3; - delete r.headersOut['Content-Length']; - r.headersOut['Content-Length'] = 3; - r.sendHeader(); - r.send('XXX'); - r.finish(); - } - - function content_length_arr(r) { - r.headersOut['Content-Length'] = [5]; - r.headersOut['Content-Length'] = []; - r.headersOut['Content-Length'] = [4,3]; - r.sendHeader(); - r.send('XXX'); - r.finish(); - } - - function content_length_keys(r) { - r.headersOut['Content-Length'] = 3; - var in_keys = Object.keys(r.headersOut).some(v=>v=='Content-Length'); - r.return(200, `B:\${in_keys}`); - } - - function content_type(r) { - if (njs.version_number >= 0x000705) { - var ctype = r.headersOut['Content-Type']; - if (ctype !== undefined) { - r.return(500, `Content-Type "\${ctype}" is not empty`); - return; - } - } - - delete r.headersOut['Content-Type']; - r.headersOut['Content-Type'] = 'text/xml'; - r.headersOut['Content-Type'] = ''; - r.headersOut['Content-Type'] = 'text/xml; charset='; - delete r.headersOut['Content-Type']; - r.headersOut['Content-Type'] = 'text/xml; charset=utf-8'; - r.headersOut['Content-Type'] = 'text/xml; charset="utf-8"'; - var in_keys = Object.keys(r.headersOut).some(v=>v=='Content-Type'); - r.return(200, `B:\${in_keys}`); - } - - function content_type_arr(r) { - r.headersOut['Content-Type'] = ['text/html']; - r.headersOut['Content-Type'] = []; - r.headersOut['Content-Type'] = [ 'text/xml', 'text/html']; - r.return(200); - } - - function content_encoding(r) { - if (njs.version_number >= 0x000705) { - var ce = r.headersOut['Content-Encoding']; - if (ce !== undefined) { - r.return(500, `Content-Encoding "\${ce}" is not empty`); - return; - } - } - - delete r.headersOut['Content-Encoding']; - r.headersOut['Content-Encoding'] = ''; - r.headersOut['Content-Encoding'] = 'test'; - delete r.headersOut['Content-Encoding']; - r.headersOut['Content-Encoding'] = 'gzip'; - r.return(200); - } - - function content_encoding_arr(r) { - r.headersOut['Content-Encoding'] = 'test'; - r.headersOut['Content-Encoding'] = []; - r.headersOut['Content-Encoding'] = ['test', 'gzip']; - r.return(200); - } - - function headers_list(r) { - for (var h in {a:1, b:2, c:3}) { - r.headersOut[h] = h; - } - - delete r.headersOut.b; - r.headersOut.d = 'd'; - - var out = ""; - for (var h in r.headersOut) { - out += h + ":"; - } - - r.return(200, out); - } - - function hdr_in(r) { - var s = '', h; - for (h in r.headersIn) { - s += `\${h.toLowerCase()}: \${r.headersIn[h]}\n`; - } - - r.return(200, s); - } - - function raw_hdr_in(r) { - var filtered = r.rawHeadersIn - .filter(v=>v[0].toLowerCase() == r.args.filter); - r.return(200, 'raw:' + filtered.map(v=>v[1]).join('|')); - } - - function hdr_sorted_keys(r) { - var s = ''; - var hdr = r.args.in ? r.headersIn : r.headersOut; - - if (!r.args.in) { - r.headersOut.b = 'b'; - r.headersOut.c = 'c'; - r.headersOut.a = 'a'; - } - - r.return(200, Object.keys(hdr).sort()); - } - - function foo_in(r) { - return 'hdr=' + r.headersIn.foo; - } - - function ifoo_in(r) { - var s = '', h; - for (h in r.headersIn) { - if (h.substr(0, 3) == 'foo') { - s += r.headersIn[h]; - } - } - return s; - } - - function hdr_out(r) { - r.status = 200; - r.headersOut['Foo'] = r.args.foo; - - if (r.args.bar) { - r.headersOut['Bar'] = - r.headersOut[(r.args.bar == 'empty' ? 'Baz' :'Foo')] - } - - r.sendHeader(); - r.finish(); - } - - function raw_hdr_out(r) { - r.headersOut.a = ['foo', 'bar']; - r.headersOut.b = 'b'; - - var filtered = r.rawHeadersOut - .filter(v=>v[0].toLowerCase() == r.args.filter); - r.return(200, 'raw:' + filtered.map(v=>v[1]).join('|')); - } - - function hdr_out_array(r) { - if (!r.args.hidden) { - r.headersOut['Foo'] = [r.args.foo]; - r.headersOut['Foo'] = []; - r.headersOut['Foo'] = ['bar', r.args.foo]; - } - - if (r.args.scalar_set) { - r.headersOut['Foo'] = 'xxx'; - } - - r.return(200, `B:\${njs.dump(r.headersOut.foo)}`); - } - - function hdr_out_single(r) { - r.headersOut.ETag = ['a', 'b']; - r.return(200, `B:\${njs.dump(r.headersOut.etag)}`); - } - - function hdr_out_set_cookie(r) { - r.headersOut['Set-Cookie'] = []; - r.headersOut['Set-Cookie'] = ['a', 'b']; - delete r.headersOut['Set-Cookie']; - r.headersOut['Set-Cookie'] = 'e'; - r.headersOut['Set-Cookie'] = ['c', '', null, 'd', 'f']; - - r.return(200, `B:\${njs.dump(r.headersOut['Set-Cookie'])}`); - } - - function ihdr_out(r) { - r.status = 200; - r.headersOut['a'] = r.args.a; - r.headersOut['b'] = r.args.b; - - var s = '', h; - for (h in r.headersOut) { - s += r.headersOut[h]; - } - - r.sendHeader(); - r.send(s); - r.finish(); - } - - function hdr_out_special_set(r) { - r.headersOut['Foo'] = "xxx"; - r.headersOut['Content-Encoding'] = 'abc'; - - let ce = r.headersOut['Content-Encoding']; - r.return(200, `CE: \${ce}`); - } - - async function copy_subrequest_hdrs(r) { - let resp = await r.subrequest("/subrequest"); - - for (const h in resp.headersOut) { - r.headersOut[h] = resp.headersOut[h]; - } - - r.return(200, resp.responseText); - } - - function subrequest(r) { - r.headersOut['A'] = 'a'; - r.headersOut['Content-Encoding'] = 'ce'; - r.headersOut['B'] = 'b'; - r.headersOut['C'] = 'c'; - r.headersOut['D'] = 'd'; - r.headersOut['Set-Cookie'] = ['A', 'BB']; - r.headersOut['Content-Length'] = 3; - r.headersOut['Content-Type'] = 'ct'; - r.sendHeader(); - r.send('XXX'); - r.finish(); - } - - export default {njs:test_njs, content_length, content_length_arr, - content_length_keys, content_type, content_type_arr, - content_encoding, content_encoding_arr, headers_list, - hdr_in, raw_hdr_in, hdr_sorted_keys, foo_in, ifoo_in, - hdr_out, raw_hdr_out, hdr_out_array, hdr_out_single, - hdr_out_set_cookie, ihdr_out, hdr_out_special_set, - copy_subrequest_hdrs, subrequest}; - - -EOF - -$t->try_run('no njs')->plan(42); - -############################################################################### - -like(http_get('/content_length'), qr/Content-Length: 3/, - 'set Content-Length'); -like(http_get('/content_type'), qr/Content-Type: text\/xml; charset="utf-8"\r/, - 'set Content-Type'); -unlike(http_get('/content_type'), qr/Content-Type: text\/plain/, - 'set Content-Type 2'); -like(http_get('/content_encoding'), qr/Content-Encoding: gzip/, - 'set Content-Encoding'); -like(http_get('/headers_list'), qr/a:c:d/, 'headers list'); - -like(http_get('/ihdr_out?a=12&b=34'), qr/^1234$/m, 'r.headersOut iteration'); -like(http_get('/ihdr_out'), qr/\x0d\x0a?\x0d\x0a?$/m, 'r.send zero'); -like(http_get('/hdr_out?foo=12345'), qr/Foo: 12345/, 'r.headersOut'); -like(http_get('/hdr_out?foo=123&bar=copy'), qr/Bar: 123/, 'r.headersOut get'); -unlike(http_get('/hdr_out?bar=empty'), qr/Bar:/, 'r.headersOut empty'); -unlike(http_get('/hdr_out?foo='), qr/Foo:/, 'r.headersOut no value'); -unlike(http_get('/hdr_out?foo'), qr/Foo:/, 'r.headersOut no value 2'); - -like(http_get('/content_length_keys'), qr/B:true/, 'Content-Length in keys'); -like(http_get('/content_length_arr'), qr/Content-Length: 3/, - 'set Content-Length arr'); - -like(http_get('/content_type'), qr/B:true/, 'Content-Type in keys'); -like(http_get('/content_type_arr'), qr/Content-Type: text\/html/, - 'set Content-Type arr'); -like(http_get('/content_encoding_arr'), qr/Content-Encoding: gzip/, - 'set Content-Encoding arr'); - -like(http_get('/hdr_out_array?foo=12345'), qr/Foo: bar\r\nFoo: 12345/, - 'r.headersOut arr'); -like(http_get('/hdr_out_array'), qr/Foo: bar/, - 'r.headersOut arr last is empty'); -like(http_get('/hdr_out_array?foo=abc'), qr/B:bar,\s?abc/, - 'r.headersOut get'); -like(http_get('/hdr_out_array'), qr/B:bar/, 'r.headersOut get2'); -like(http_get('/hdr_out_array?hidden=1'), qr/B:undefined/, - 'r.headersOut get3'); -like(http_get('/hdr_out_array?scalar_set=1'), qr/B:xxx/, - 'r.headersOut scalar set'); -like(http_get('/hdr_out_single'), qr/ETag: a\r\nETag: b/, - 'r.headersOut single'); -like(http_get('/hdr_out_single'), qr/B:a/, - 'r.headersOut single get'); -like(http_get('/hdr_out_set_cookie'), qr/Set-Cookie: c\r\nSet-Cookie: d/, - 'set_cookie'); -like(http_get('/hdr_out_set_cookie'), qr/B:\['c','d','f']/, - 'set_cookie2'); -unlike(http_get('/hdr_out_set_cookie'), qr/Set-Cookie: [abe]/, - 'set_cookie3'); - -like(http( - 'GET /hdr_in HTTP/1.0' . CRLF - . 'Cookie: foo' . CRLF - . 'Host: localhost' . CRLF . CRLF -), qr/cookie: foo/, 'r.headersIn cookie'); - -like(http( - 'GET /hdr_in HTTP/1.0' . CRLF - . 'X-Forwarded-For: foo' . CRLF - . 'Host: localhost' . CRLF . CRLF -), qr/x-forwarded-for: foo/, 'r.headersIn xff'); - -like(http( - 'GET /hdr_in HTTP/1.0' . CRLF - . 'Cookie: foo1' . CRLF - . 'Cookie: foo2' . CRLF - . 'Host: localhost' . CRLF . CRLF -), qr/cookie: foo1;\s?foo2/, 'r.headersIn cookie2'); - -like(http( - 'GET /hdr_in HTTP/1.0' . CRLF - . 'X-Forwarded-For: foo1' . CRLF - . 'X-Forwarded-For: foo2' . CRLF - . 'Host: localhost' . CRLF . CRLF -), qr/x-forwarded-for: foo1,\s?foo2/, 'r.headersIn xff2'); - -like(http( - 'GET /hdr_in HTTP/1.0' . CRLF - . 'ETag: bar1' . CRLF - . 'ETag: bar2' . CRLF - . 'Host: localhost' . CRLF . CRLF -), qr/etag: bar1(?!,\s?bar2)/, 'r.headersIn duplicate single'); - -like(http( - 'GET /hdr_in HTTP/1.0' . CRLF - . 'Content-Type: bar1' . CRLF - . 'Content-Type: bar2' . CRLF - . 'Host: localhost' . CRLF . CRLF -), qr/content-type: bar1(?!,\s?bar2)/, 'r.headersIn duplicate single 2'); - -like(http( - 'GET /hdr_in HTTP/1.0' . CRLF - . 'Foo: bar1' . CRLF - . 'Foo: bar2' . CRLF - . 'Host: localhost' . CRLF . CRLF -), qr/foo: bar1,\s?bar2/, 'r.headersIn duplicate generic'); - -like(http( - 'GET /raw_hdr_in?filter=foo HTTP/1.0' . CRLF - . 'foo: bar1' . CRLF - . 'Foo: bar2' . CRLF - . 'Host: localhost' . CRLF . CRLF -), qr/raw: bar1|bar2/, 'r.rawHeadersIn'); - -like(http_get('/raw_hdr_out?filter=a'), qr/raw: foo|bar/, 'r.rawHeadersOut'); - -like(http( - 'GET /hdr_sorted_keys?in=1 HTTP/1.0' . CRLF - . 'Cookie: foo1' . CRLF - . 'Accept: */*' . CRLF - . 'Cookie: foo2' . CRLF - . 'Host: localhost' . CRLF . CRLF -), qr/Accept,Cookie,Host/, 'r.headersIn sorted keys'); - -like(http( - 'GET /hdr_sorted_keys HTTP/1.0' . CRLF - . 'Host: localhost' . CRLF . CRLF -), qr/a,b,c/, 'r.headersOut sorted keys'); - -TODO: { -local $TODO = 'not yet' unless has_version('0.7.6'); - -like(http_get('/hdr_out_special_set'), qr/CE: abc/, - 'r.headerOut special set'); - -like(http_get('/copy_subrequest_hdrs'), - qr/A: a.*B: b.*C: c.*D: d.*Set-Cookie: A.*Set-Cookie: BB/s, - 'subrequest copy'); - -like(http_get('/copy_subrequest_hdrs'), - qr/Content-Type: ct.*Content-Encoding: ce.*Content-Length: 3/s, - 'subrequest copy special'); - -} - -############################################################################### - -sub has_version { - my $need = shift; - - http_get('/njs') =~ /^([.0-9]+)$/m; - - my @v = split(/\./, $1); - my ($n, $v); - - for $n (split(/\./, $need)) { - $v = shift @v || 0; - return 0 if $n > $v; - return 1 if $v > $n; - } - - return 1; -} - -############################################################################### diff --git a/js_import.t b/js_import.t deleted file mode 100644 --- a/js_import.t +++ /dev/null @@ -1,108 +0,0 @@ -#!/usr/bin/perl - -# (C) Dmitry Volyntsev -# (c) Nginx, Inc. - -# Tests for http njs module, js_import directive. - -############################################################################### - -use warnings; -use strict; - -use Test::More; - -BEGIN { use FindBin; chdir($FindBin::Bin); } - -use lib 'lib'; -use Test::Nginx; - -############################################################################### - -select STDERR; $| = 1; -select STDOUT; $| = 1; - -my $t = Test::Nginx->new()->has(qw/http/) - ->write_file_expand('nginx.conf', <<'EOF'); - -%%TEST_GLOBALS%% - -daemon off; - -events { -} - -http { - %%TEST_GLOBALS_HTTP%% - - js_set $test foo.bar.p; - - js_import lib.js; - js_import fun.js; - js_import foo from ./main.js; - - server { - listen 127.0.0.1:8080; - server_name localhost; - - location /njs { - js_content foo.version; - } - - location /test_foo { - js_content foo.test; - } - - location /test_lib { - js_content lib.test; - } - - location /test_fun { - js_content fun; - } - - location /test_var { - return 200 $test; - } - } -} - -EOF - -$t->write_file('lib.js', <write_file('fun.js', <write_file('main.js', <try_run('no njs available')->plan(4); - -############################################################################### - -like(http_get('/test_foo'), qr/MAIN-TEST/s, 'foo.test'); -like(http_get('/test_lib'), qr/LIB-TEST/s, 'lib.test'); -like(http_get('/test_fun'), qr/FUN-TEST/s, 'fun'); -like(http_get('/test_var'), qr/P-TEST/s, 'foo.bar.p'); - -############################################################################### diff --git a/js_import2.t b/js_import2.t deleted file mode 100644 --- a/js_import2.t +++ /dev/null @@ -1,127 +0,0 @@ -#!/usr/bin/perl - -# (C) Dmitry Volyntsev -# (c) Nginx, Inc. - -# Tests for http njs module, js_import directive in server | location contexts. - -############################################################################### - -use warnings; -use strict; - -use Test::More; - -BEGIN { use FindBin; chdir($FindBin::Bin); } - -use lib 'lib'; -use Test::Nginx; - -############################################################################### - -select STDERR; $| = 1; -select STDOUT; $| = 1; - -my $t = Test::Nginx->new()->has(qw/http proxy rewrite/) - ->write_file_expand('nginx.conf', <<'EOF'); - -%%TEST_GLOBALS%% - -daemon off; - -events { -} - -http { - %%TEST_GLOBALS_HTTP%% - - server { - listen 127.0.0.1:8080; - server_name localhost; - - js_set $test foo.bar.p; - - js_import foo from main.js; - - location /njs { - js_content foo.version; - } - - location /test_foo { - js_content foo.test; - } - - location /test_lib { - js_import lib.js; - js_content lib.test; - } - - location /test_fun { - js_import fun.js; - js_content fun; - } - - location /test_var { - return 200 $test; - } - - location /proxy { - proxy_pass http://127.0.0.1:8081/; - } - } - - server { - listen 127.0.0.1:8081; - server_name localhost; - - location /test_fun { - js_import fun.js; - js_content fun; - } - } -} - -EOF - -$t->write_file('lib.js', <write_file('fun.js', <write_file('main.js', <try_run('no njs available')->plan(5); - -############################################################################### - -like(http_get('/test_foo'), qr/MAIN-TEST/s, 'foo.test'); -like(http_get('/test_lib'), qr/LIB-TEST/s, 'lib.test'); -like(http_get('/test_fun'), qr/FUN-TEST/s, 'fun'); -like(http_get('/proxy/test_fun'), qr/FUN-TEST/s, 'proxy fun'); -like(http_get('/test_var'), qr/P-TEST/s, 'foo.bar.p'); - -############################################################################### diff --git a/js_internal_redirect.t b/js_internal_redirect.t deleted file mode 100644 --- a/js_internal_redirect.t +++ /dev/null @@ -1,130 +0,0 @@ -#!/usr/bin/perl - -# (C) Dmitry Volyntsev -# (C) Nginx, Inc. - -# Tests for http njs module, internalRedirect method. - -############################################################################### - -use warnings; -use strict; - -use Test::More; - -BEGIN { use FindBin; chdir($FindBin::Bin); } - -use lib 'lib'; -use Test::Nginx; - -############################################################################### - -select STDERR; $| = 1; -select STDOUT; $| = 1; - -my $t = Test::Nginx->new()->has(qw/http rewrite/) - ->write_file_expand('nginx.conf', <<'EOF'); - -%%TEST_GLOBALS%% - -daemon off; - -events { -} - -http { - %%TEST_GLOBALS_HTTP%% - - js_import test.js; - - server { - listen 127.0.0.1:8080; - server_name localhost; - - location /njs { - js_content test.njs; - } - - location /test { - js_content test.redirect; - } - - location /redirect { - internal; - return 200 redirect$arg_b; - } - - location @named { - return 200 named; - } - } -} - -EOF - -$t->write_file('test.js', <try_run('no njs available')->plan(5); - -############################################################################### - -like(http_get('/test'), qr/redirect/s, 'redirect'); -like(http_get('/test?a=A'), qr/redirectA/s, 'redirect with args'); -like(http_get('/test?dest=named'), qr/named/s, 'redirect to named location'); - -TODO: { -local $TODO = 'not yet' unless has_version('0.7.4'); - -like(http_get('/test?unsafe=1'), qr/500 Internal Server/s, - 'unsafe redirect'); -like(http_get('/test?quoted=1'), qr/200 .*redirect/s, - 'quoted redirect'); -} - -############################################################################### - -sub has_version { - my $need = shift; - - http_get('/njs') =~ /^([.0-9]+)$/m; - - my @v = split(/\./, $1); - my ($n, $v); - - for $n (split(/\./, $need)) { - $v = shift @v || 0; - return 0 if $n > $v; - return 1 if $v > $n; - } - - return 1; -} - -############################################################################### diff --git a/js_modules.t b/js_modules.t deleted file mode 100644 --- a/js_modules.t +++ /dev/null @@ -1,84 +0,0 @@ -#!/usr/bin/perl - -# (C) Dmitry Volyntsev -# (C) Nginx, Inc. - -# Tests for http njs module, ES6 import, export. - -############################################################################### - -use warnings; -use strict; - -use Test::More; - -BEGIN { use FindBin; chdir($FindBin::Bin); } - -use lib 'lib'; -use Test::Nginx; - -############################################################################### - -select STDERR; $| = 1; -select STDOUT; $| = 1; - -my $t = Test::Nginx->new()->has(qw/http/) - ->write_file_expand('nginx.conf', <<'EOF'); - -%%TEST_GLOBALS%% - -daemon off; - -events { -} - -http { - %%TEST_GLOBALS_HTTP%% - - js_import test.js; - - server { - listen 127.0.0.1:8080; - server_name localhost; - - location /test { - js_content test.test; - } - } -} - -EOF - -$t->write_file('test.js', <write_file('module.js', <try_run('no njs modules')->plan(2); - -############################################################################### - -like(http_get('/test?fun=sum&a=3&b=4'), qr/7/s, 'test sum'); -like(http_get('/test?fun=prod&a=3&b=4'), qr/12/s, 'test prod'); - -############################################################################### diff --git a/js_ngx.t b/js_ngx.t deleted file mode 100644 --- a/js_ngx.t +++ /dev/null @@ -1,94 +0,0 @@ -#!/usr/bin/perl - -# (C) Dmitry Volyntsev -# (C) Nginx, Inc. - -# Tests for http njs module, ngx object. - -############################################################################### - -use warnings; -use strict; - -use Test::More; - -BEGIN { use FindBin; chdir($FindBin::Bin); } - -use lib 'lib'; -use Test::Nginx; - -############################################################################### - -select STDERR; $| = 1; -select STDOUT; $| = 1; - -my $t = Test::Nginx->new()->has(qw/http/) - ->write_file_expand('nginx.conf', <<'EOF'); - -%%TEST_GLOBALS%% - -daemon off; - -events { -} - -http { - %%TEST_GLOBALS_HTTP%% - - js_import test.js; - - server { - listen 127.0.0.1:8080; - server_name localhost; - - location /njs { - js_content test.njs; - } - - location /log { - js_content test.log; - } - } -} - -EOF - -$t->write_file('test.js', <try_run('no njs ngx')->plan(3); - -############################################################################### - -http_get('/log?level=INFO&text=FOO'); -http_get('/log?level=WARN&text=BAR'); -http_get('/log?level=ERR&text=BAZ'); - -$t->stop(); - -like($t->read_file('error.log'), qr/\[info\].*ngx.log:FOO/, 'ngx.log info'); -like($t->read_file('error.log'), qr/\[warn\].*ngx.log:BAR/, 'ngx.log warn'); -like($t->read_file('error.log'), qr/\[error\].*ngx.log:BAZ/, 'ngx.log err'); - -############################################################################### diff --git a/js_object.t b/js_object.t deleted file mode 100644 --- a/js_object.t +++ /dev/null @@ -1,137 +0,0 @@ -#!/usr/bin/perl - -# (C) Dmitry Volyntsev -# (C) Nginx, Inc. - -# Tests for http njs module, request object. - -############################################################################### - -use warnings; -use strict; - -use Test::More; -use Socket qw/ CRLF /; - -BEGIN { use FindBin; chdir($FindBin::Bin); } - -use lib 'lib'; -use Test::Nginx; - -############################################################################### - -select STDERR; $| = 1; -select STDOUT; $| = 1; - -my $t = Test::Nginx->new()->has(qw/http/) - ->write_file_expand('nginx.conf', <<'EOF'); - -%%TEST_GLOBALS%% - -daemon off; - -events { -} - -http { - %%TEST_GLOBALS_HTTP%% - - js_import test.js; - - server { - listen 127.0.0.1:8080; - server_name localhost; - - location /to_string { - js_content test.to_string; - } - - location /define_prop { - js_content test.define_prop; - } - - location /in_operator { - js_content test.in_operator; - } - - location /redefine_bind { - js_content test.redefine_bind; - } - - location /redefine_proxy { - js_content test.redefine_proxy; - } - - location /redefine_proto { - js_content test.redefine_proto; - } - - location /get_own_prop_descs { - js_content test.get_own_prop_descs; - } - } -} - -EOF - -$t->write_file('test.js', <v in r.headersIn) - .toString() === 'true,false'); - } - - function redefine_bind(r) { - r.return = r.return.bind(r, 200); - r.return('redefine_bind'); - } - - function redefine_proxy(r) { - r.return_orig = r.return; - r.return = function (body) { this.return_orig(200, body);} - r.return('redefine_proxy'); - } - - function redefine_proto(r) { - r[0] = 'a'; - r[1] = 'b'; - r.length = 2; - Object.setPrototypeOf(r, Array.prototype); - r.return(200, r.join('|')); - } - - function get_own_prop_descs(r) { - r.return(200, - Object.getOwnPropertyDescriptors(r)['log'].value === r.log); - } - - export default {to_string, define_prop, in_operator, redefine_bind, - redefine_proxy, redefine_proto, get_own_prop_descs}; - -EOF - -$t->try_run('no njs request object')->plan(7); - -############################################################################### - -like(http_get('/to_string'), qr/\[object Request\]/, 'toString'); -like(http_get('/define_prop'), qr/Foo: bar/, 'define_prop'); -like(http( - 'GET /in_operator HTTP/1.0' . CRLF - . 'Foo: foo' . CRLF - . 'Host: localhost' . CRLF . CRLF -), qr/true/, 'in_operator'); -like(http_get('/redefine_bind'), qr/redefine_bind/, 'redefine_bind'); -like(http_get('/redefine_proxy'), qr/redefine_proxy/, 'redefine_proxy'); -like(http_get('/redefine_proto'), qr/a|b/, 'redefine_proto'); -like(http_get('/get_own_prop_descs'), qr/true/, 'get_own_prop_descs'); - -############################################################################### diff --git a/js_paths.t b/js_paths.t deleted file mode 100644 --- a/js_paths.t +++ /dev/null @@ -1,110 +0,0 @@ -#!/usr/bin/perl - -# (C) Dmitry Volyntsev -# (C) Nginx, Inc. - -# Tests for http njs module, js_path directive. - -############################################################################### - -use warnings; -use strict; - -use Test::More; - -BEGIN { use FindBin; chdir($FindBin::Bin); } - -use lib 'lib'; -use Test::Nginx; - -############################################################################### - -select STDERR; $| = 1; -select STDOUT; $| = 1; - -my $t = Test::Nginx->new()->has(qw/http/) - ->write_file_expand('nginx.conf', <<'EOF'); - -%%TEST_GLOBALS%% - -daemon off; - -events { -} - -http { - %%TEST_GLOBALS_HTTP%% - - js_path "%%TESTDIR%%/lib1"; - js_path "lib2"; - - js_import test.js; - - server { - listen 127.0.0.1:8080; - server_name localhost; - - location /test { - js_content test.test; - } - - location /test2 { - js_content test.test2; - } - } -} - -EOF - -$t->write_file('test.js', <testdir(); - -mkdir("$d/lib1"); -mkdir("$d/lib2"); - -$t->write_file('lib1/module1.js', <write_file('lib2/module2.js', <try_run('no njs available')->plan(4); - -############################################################################### - -like(http_get('/test?fun=sum&a=3&b=4'), qr/7/s, 'test sum'); -like(http_get('/test?fun=prod&a=3&b=4'), qr/12/s, 'test prod'); -like(http_get('/test2?a=3&b=4'), qr/34/s, 'test2'); -like(http_get('/test2?a=A&b=B'), qr/AB/s, 'test2 relative'); - -############################################################################### diff --git a/js_preload_object.t b/js_preload_object.t deleted file mode 100644 --- a/js_preload_object.t +++ /dev/null @@ -1,181 +0,0 @@ -#!/usr/bin/perl - -# (C) Vadim Zhestikov -# (C) Nginx, Inc. - -# Tests for http njs module, js_preload_object directive. - -############################################################################### - -use warnings; -use strict; - -use Test::More; - -BEGIN { use FindBin; chdir($FindBin::Bin); } - -use lib 'lib'; -use Test::Nginx; - -############################################################################### - -select STDERR; $| = 1; -select STDOUT; $| = 1; - -my $t = Test::Nginx->new()->has(qw/http rewrite/) - ->write_file_expand('nginx.conf', <<'EOF'); - -%%TEST_GLOBALS%% - -daemon off; - -events { -} - -http { - %%TEST_GLOBALS_HTTP%% - - js_preload_object g1 from g.json; - js_preload_object ga from ga.json; - - server { - listen 127.0.0.1:8080; - server_name localhost; - - js_import lib.js; - js_preload_object lx from l.json; - - location /test { - js_content lib.test; - } - - location /test_query { - js_import lib1.js; - js_content lib1.query; - } - - location /test_query_preloaded { - js_import lib1.js; - js_preload_object l.json; - js_content lib1.query; - } - - location /test_var { - js_set $test_var lib.test_var; - return 200 $test_var; - } - - location /test_mutate { - js_content lib.mutate; - } - - location /test_no_suffix { - js_preload_object gg from no_suffix; - js_content lib.suffix; - } - } -} - -EOF - -$t->write_file('lib.js', <write_file('lib1.js', < a[v], globalThis); - - } catch (e) { - res = e.message; - } - - r.return(200, njs.dump(res)); - } - - export default {query}; - -EOF - -$t->write_file('g.json', - '{"a":1, "b":[1,2,"element",4,5], "c":{"prop":[{"a":2}]}}'); -$t->write_file('ga.json', '"ga loaded"'); -$t->write_file('l.json', '"l loaded"'); -$t->write_file('no_suffix', '"no_suffix loaded"'); - -$t->try_run('no js_preload_object available')->plan(12); - -############################################################################### - -like(http_get('/test'), qr/ga loaded 2 l loaded/s, 'direct query'); -like(http_get('/test_query?path=l'), qr/undefined/s, 'unreferenced'); -like(http_get('/test_query_preloaded?path=l'), qr/l loaded/s, - 'reference preload'); -like(http_get('/test_query?path=g1.b.1'), qr/2/s, 'complex query'); -like(http_get('/test_var'), qr/element/s, 'var reference'); - -like(http_get('/test_mutate?method=set_obj'), qr/Cannot assign to read-only/s, - 'preload_object props are const (object)'); -like(http_get('/test_mutate?method=set_arr'), qr/Cannot assign to read-only/s, - 'preload_object props are const (array)'); -like(http_get('/test_mutate?method=add_obj'), qr/Cannot add property "xxx"/s, - 'preload_object props are not extensible (object)'); -like(http_get('/test_mutate?method=add_arr'), qr/Cannot add property "10"/s, - 'preload_object props are not extensible (array)'); -like(http_get('/test_mutate?method=del_obj'), qr/Cannot delete property "a"/s, - 'preload_object props are not deletable (object)'); -like(http_get('/test_mutate?method=del_arr'), qr/Cannot delete property "0"/s, - 'preload_object props are not deletable (array)'); - -like(http_get('/test_no_suffix'), qr/no_suffix loaded/s, - 'load without suffix'); - -############################################################################### diff --git a/js_promise.t b/js_promise.t deleted file mode 100644 --- a/js_promise.t +++ /dev/null @@ -1,201 +0,0 @@ -#!/usr/bin/perl - -# (C) Nginx, Inc. - -# Promise tests for http njs module. - -############################################################################### - -use warnings; -use strict; - -use Test::More; - -BEGIN { use FindBin; chdir($FindBin::Bin); } - -use lib 'lib'; -use Test::Nginx; - -############################################################################### - -select STDERR; $| = 1; -select STDOUT; $| = 1; - -my $t = Test::Nginx->new()->has(qw/http/) - ->write_file_expand('nginx.conf', <<'EOF'); - -%%TEST_GLOBALS%% - -daemon off; - -events { -} - -http { - %%TEST_GLOBALS_HTTP%% - - js_import test.js; - - server { - listen 127.0.0.1:8080; - server_name localhost; - - location /njs { - js_content test.njs; - } - - location /promise { - js_content test.promise; - } - - location /promise_throw { - js_content test.promise_throw; - } - - location /promise_pure { - js_content test.promise_pure; - } - - location /timeout { - js_content test.timeout; - } - - location /sub_token { - js_content test.sub_token; - } - } -} - -EOF - -$t->write_file('test.js', < { - var data = JSON.parse(reply.responseText); - - if (data['token'] !== "a") { - throw new Error('token is not "a"'); - } - - return data['token']; - }) - .then(token => { - promisified_subrequest(r, '/sub_token', 'code=200&token=b') - .then(reply => { - var data = JSON.parse(reply.responseText); - - r.return(200, '{"token": "' + data['token'] + '"}'); - }) - .catch(() => { - throw new Error("failed promise() test"); - }); - }) - .catch(() => { - r.return(500); - }); - } - - function promise_throw(r) { - promisified_subrequest(r, '/sub_token', 'code=200&token=x') - .then(reply => { - var data = JSON.parse(reply.responseText); - - if (data['token'] !== "a") { - throw data['token']; - } - - return data['token']; - }) - .then(() => { - r.return(500); - }) - .catch(token => { - r.return(200, '{"token": "' + token + '"}'); - }); - } - - function promise_pure(r) { - var count = 0; - - Promise.resolve(true) - .then(() => count++) - .then(() => not_exist_ref) - .finally(() => count++) - .catch(() => { - r.return((count != 2) ? 500 : 200); - }); - } - - function timeout(r) { - promisified_subrequest(r, '/sub_token', 'code=200&token=R') - .then(reply => JSON.parse(reply.responseText)) - .then(data => { - setTimeout(timeout_cb, 50, r, '/sub_token', 'code=200&token=T'); - return data; - }) - .then(data => { - setTimeout(timeout_cb, 1, r, '/sub_token', 'code=200&token=' - + data['token']); - }) - .catch(() => { - r.return(500); - }); - } - - function timeout_cb(r, url, args) { - promisified_subrequest(r, url, args) - .then(reply => { - if (global_token == '') { - var data = JSON.parse(reply.responseText); - - global_token = data['token']; - - r.return(200, '{"token": "' + data['token'] + '"}'); - } - }) - .catch(() => { - r.return(500); - }); - } - - function promisified_subrequest(r, uri, args) { - return new Promise((resolve, reject) => { - r.subrequest(uri, args, (reply) => { - if (reply.status < 400) { - resolve(reply); - } else { - reject(reply); - } - }); - }) - } - - function sub_token(r) { - var code = r.variables.arg_code; - var token = r.variables.arg_token; - - r.return(parseInt(code), '{"token": "'+ token +'"}'); - } - - export default {njs:test_njs, promise, promise_throw, promise_pure, - timeout, sub_token}; - -EOF - -$t->try_run('no njs available')->plan(4); - -############################################################################### - -like(http_get('/promise'), qr/{"token": "b"}/, "Promise"); -like(http_get('/promise_throw'), qr/{"token": "x"}/, "Promise throw and catch"); -like(http_get('/timeout'), qr/{"token": "R"}/, "Promise with timeout"); -like(http_get('/promise_pure'), qr/200 OK/, "events handling"); - -############################################################################### diff --git a/js_request_body.t b/js_request_body.t deleted file mode 100644 --- a/js_request_body.t +++ /dev/null @@ -1,110 +0,0 @@ -#!/usr/bin/perl - -# (C) Dmitry Volyntsev -# (C) Nginx, Inc. - -# Tests for http njs module, r.requestText method. - -############################################################################### - -use warnings; -use strict; - -use Test::More; - -use Socket qw/ CRLF /; - -BEGIN { use FindBin; chdir($FindBin::Bin); } - -use lib 'lib'; -use Test::Nginx; - -############################################################################### - -select STDERR; $| = 1; -select STDOUT; $| = 1; - -my $t = Test::Nginx->new()->has(qw/http/) - ->write_file_expand('nginx.conf', <<'EOF'); - -%%TEST_GLOBALS%% - -daemon off; - -events { -} - -http { - %%TEST_GLOBALS_HTTP%% - - js_import test.js; - - server { - listen 127.0.0.1:8080; - server_name localhost; - - location /body { - js_content test.body; - } - - location /in_file { - client_body_in_file_only on; - js_content test.body; - } - } -} - -EOF - -$t->write_file('test.js', <try_run('no njs request body')->plan(3); - -############################################################################### - -like(http_post('/body'), qr/REQ-BODY/, 'request body'); -like(http_post('/in_file'), qr/request body is in a file/, - 'request body in file'); -like(http_post_big('/body'), qr/200.*^(1234567890){1024}$/ms, - 'request body big'); - -############################################################################### - -sub http_post { - my ($url, %extra) = @_; - - my $p = "POST $url HTTP/1.0" . CRLF . - "Host: localhost" . CRLF . - "Content-Length: 8" . CRLF . - CRLF . - "REQ-BODY"; - - return http($p, %extra); -} - -sub http_post_big { - my ($url, %extra) = @_; - - my $p = "POST $url HTTP/1.0" . CRLF . - "Host: localhost" . CRLF . - "Content-Length: 10240" . CRLF . - CRLF . - ("1234567890" x 1024); - - return http($p, %extra); -} - -############################################################################### diff --git a/js_return.t b/js_return.t deleted file mode 100644 --- a/js_return.t +++ /dev/null @@ -1,73 +0,0 @@ -#!/usr/bin/perl - -# (C) Sergey Kandaurov -# (C) Nginx, Inc. - -# Tests for http njs module, return method. - -############################################################################### - -use warnings; -use strict; - -use Test::More; - -use Config; - -BEGIN { use FindBin; chdir($FindBin::Bin); } - -use lib 'lib'; -use Test::Nginx; - -############################################################################### - -select STDERR; $| = 1; -select STDOUT; $| = 1; - -my $t = Test::Nginx->new()->has(qw/http/) - ->write_file_expand('nginx.conf', <<'EOF'); - -%%TEST_GLOBALS%% - -daemon off; - -events { -} - -http { - %%TEST_GLOBALS_HTTP%% - - js_import test.js; - - server { - listen 127.0.0.1:8080; - server_name localhost; - - location / { - js_content test.returnf; - } - } -} - -EOF - -$t->write_file('test.js', <try_run('no njs return')->plan(5); - -############################################################################### - -like(http_get('/?c=200'), qr/200 OK.*\x0d\x0a?\x0d\x0a?$/s, 'return code'); -like(http_get('/?c=200&t=SEE-THIS'), qr/200 OK.*^SEE-THIS$/ms, 'return text'); -like(http_get('/?c=301&t=path'), qr/ 301 .*Location: path/s, 'return redirect'); -like(http_get('/?c=404'), qr/404 Not.*html/s, 'return error page'); -like(http_get('/?c=inv'), qr/ 500 /, 'return invalid'); - -############################################################################### diff --git a/js_subrequests.t b/js_subrequests.t deleted file mode 100644 --- a/js_subrequests.t +++ /dev/null @@ -1,636 +0,0 @@ -#!/usr/bin/perl -# -# (C) Dmitry Volyntsev. -# (C) Nginx, Inc. - -# Tests for subrequests in http njs module. - -############################################################################### - -use warnings; -use strict; - -use Test::More; - -use Socket qw/ CRLF /; - -BEGIN { use FindBin; chdir($FindBin::Bin); } - -use lib 'lib'; -use Test::Nginx; - -############################################################################### - -select STDERR; $| = 1; -select STDOUT; $| = 1; - -eval { require JSON::PP; }; -plan(skip_all => "JSON::PP not installed") if $@; - -my $t = Test::Nginx->new()->has(qw/http rewrite proxy cache/) - ->write_file_expand('nginx.conf', <<'EOF'); - -%%TEST_GLOBALS%% - -daemon off; - -events { -} - -http { - %%TEST_GLOBALS_HTTP%% - - proxy_cache_path %%TESTDIR%%/cache1 - keys_zone=ON:1m use_temp_path=on; - - js_import test.js; - - js_set $async_var test.async_var; - js_set $subrequest_var test.subrequest_var; - - server { - listen 127.0.0.1:8080; - server_name localhost; - - location /njs { - js_content test.njs; - } - - location /sr { - js_content test.sr; - } - - location /sr_pr { - js_content test.sr_pr; - } - - location /sr_args { - js_content test.sr_args; - } - - location /sr_options_args { - js_content test.sr_options_args; - } - - location /sr_options_args_pr { - js_content test.sr_options_args_pr; - } - - location /sr_options_method { - js_content test.sr_options_method; - } - - location /sr_options_method_pr { - js_content test.sr_options_method_pr; - } - - location /sr_options_body { - js_content test.sr_options_body; - } - - location /sr_options_method_head { - js_content test.sr_options_method_head; - } - - location /sr_body { - js_content test.sr_body; - } - - location /sr_body_pr { - js_content test.sr_body_pr; - } - - location /sr_body_special { - js_content test.sr_body_special; - } - - location /sr_in_variable_handler { - set $_ $async_var; - js_content test.sr_in_variable_handler; - } - - location /sr_detached_in_variable_handler { - return 200 $subrequest_var; - } - - location /sr_async_var { - set $_ $async_var; - error_page 404 /return; - return 404; - } - - location /sr_error_page { - js_content test.sr_error_page; - } - - location /sr_js_in_subrequest { - js_content test.sr_js_in_subrequest; - } - - location /sr_js_in_subrequest_pr { - js_content test.sr_js_in_subrequest_pr; - } - - location /sr_file { - js_content test.sr_file; - } - - location /sr_cache { - js_content test.sr_cache; - } - - - location /sr_unavail { - js_content test.sr_unavail; - } - - location /sr_unavail_pr { - js_content test.sr_unavail_pr; - } - - location /sr_broken { - js_content test.sr_broken; - } - - location /sr_too_large { - js_content test.sr_too_large; - } - - location /sr_out_of_order { - js_content test.sr_out_of_order; - } - - location /sr_except_not_a_func { - js_content test.sr_except_not_a_func; - } - - location /sr_except_failed_to_convert_options_arg { - js_content test.sr_except_failed_to_convert_options_arg; - } - - location /sr_except_invalid_options_header_only { - js_content test.sr_except_invalid_options_header_only; - } - - location /sr_in_sr_callback { - js_content test.sr_in_sr_callback; - } - - location /sr_uri_except { - js_content test.sr_uri_except; - } - - - location /file/ { - alias %%TESTDIR%%/; - } - - location /p/ { - proxy_cache $arg_c; - proxy_pass http://127.0.0.1:8081/; - } - - location /daemon/ { - proxy_pass http://127.0.0.1:8082/; - } - - location /too_large/ { - subrequest_output_buffer_size 3; - proxy_pass http://127.0.0.1:8081/; - } - - location /sr_in_sr { - js_content test.sr_in_sr; - } - - location /unavail { - proxy_pass http://127.0.0.1:8084/; - } - - location /sr_parent { - js_content test.sr_parent; - } - - location /js_sub { - js_content test.js_sub; - } - - location /return { - return 200 '["$request_method"]'; - } - - location /error_page_404 { - return 404; - - error_page 404 /404.html; - } - } - - server { - listen 127.0.0.1:8081; - server_name localhost; - - location /sub1 { - add_header H $arg_h; - return 206 '{"a": {"b": 1}}'; - } - - location /sub2 { - return 404 '{"e": "msg"}'; - } - - location /method { - return 200 '["$request_method"]'; - } - - location /body { - js_content test.body; - } - - location /detached { - js_content test.detached; - } - - location /delayed { - js_content test.delayed; - } - } - - server { - listen 127.0.0.1:8084; - server_name localhost; - - return 444; - } -} - -EOF - -$t->write_file('test.js', < r.return(200, JSON.stringify({h:reply.headersOut.h}))) - } - - function sr_args(r) { - r.subrequest('/p/sub1', 'h=xxx', reply => { - r.return(200, JSON.stringify({h:reply.headersOut.h})); - }); - } - - function sr_options_args(r) { - r.subrequest('/p/sub1', {args:'h=xxx'}, reply => { - r.return(200, JSON.stringify({h:reply.headersOut.h})); - }); - } - - function sr_options_args_pr(r) { - r.subrequest('/p/sub1', {args:'h=xxx'}) - .then(reply => r.return(200, JSON.stringify({h:reply.headersOut.h}))) - } - - function sr_options_method(r) { - r.subrequest('/p/method', {method:r.args.m}, body_fwd_cb); - } - - function sr_options_method_pr(r) { - r.subrequest('/p/method', {method:r.args.m}) - .then(body_fwd_cb); - } - - function sr_options_body(r) { - r.subrequest('/p/body', {method:'POST', body:'["REQ-BODY"]'}, - body_fwd_cb); - } - - function sr_options_method_head(r) { - r.subrequest('/p/method', {method:'HEAD'}, reply => { - r.return(200, JSON.stringify({c:reply.status})); - }); - } - - function sr_body(r) { - r.subrequest('/p/sub1', body_fwd_cb); - } - - function sr_body_pr(r) { - r.subrequest('/p/sub1') - .then(body_fwd_cb); - } - - function sr_body_special(r) { - r.subrequest('/p/sub2', body_fwd_cb); - } - - function body(r) { - r.return(200, r.variables.request_body); - } - - function delayed(r) { - setTimeout(r => r.return(200), 100, r); - } - - function detached(r) { - var method = r.variables.request_method; - r.log(`DETACHED: \${method} args: \${r.variables.args}`); - - r.return(200); - } - - function sr_in_variable_handler(r) { - } - - function async_var(r) { - r.subrequest('/p/delayed', reply => { - r.return(200, JSON.stringify(["CB-VAR"])); - }); - - return ""; - } - - function sr_error_page(r) { - r.subrequest('/error_page_404') - .then(reply => {r.return(200, `reply.status:\${reply.status}`)}); - } - - function subrequest_var(r) { - r.subrequest('/p/detached', {detached:true}); - r.subrequest('/p/detached', {detached:true, args:'a=yyy', - method:'POST'}); - - return "subrequest_var"; - } - - function sr_file(r) { - r.subrequest('/file/t', body_fwd_cb); - } - - function sr_cache(r) { - r.subrequest('/p/t', body_fwd_cb); - } - - function sr_unavail(req) { - subrequest_fn(req, ['/unavail'], ['uri', 'status']); - } - - function sr_unavail_pr(req) { - subrequest_fn_pr(req, ['/unavail'], ['uri', 'status']); - } - - function sr_broken(r) { - r.subrequest('/daemon/unfinished', reply => { - r.return(200, JSON.stringify({code:reply.status})); - }); - } - - function sr_too_large(r) { - r.subrequest('/too_large/t', body_fwd_cb); - } - - function sr_in_sr(r) { - r.subrequest('/sr', body_fwd_cb); - } - - function sr_js_in_subrequest(r) { - r.subrequest('/js_sub', body_fwd_cb); - } - - function sr_js_in_subrequest_pr(r) { - r.subrequest('/js_sub') - .then(body_fwd_cb); - } - - function sr_in_sr_callback(r) { - r.subrequest('/return', function (reply) { - try { - reply.subrequest('/return'); - - } catch (err) { - r.return(200, JSON.stringify({e:err.message})); - return; - } - - r.return(200); - }); - } - - function sr_parent(r) { - try { - var parent = r.parent; - - } catch (err) { - r.return(200, JSON.stringify({e:err.message})); - return; - } - - r.return(200); - } - - function sr_out_of_order(r) { - subrequest_fn(r, ['/p/delayed', '/p/sub1', '/unknown'], - ['uri', 'status']); - } - - function collect(replies, props, total, reply) { - reply.log(`subrequest handler: \${reply.uri} status: \${reply.status}`) - - var rep = {}; - props.forEach(p => {rep[p] = reply[p]}); - - replies.push(rep); - - if (replies.length == total) { - reply.parent.return(200, JSON.stringify(replies)); - } - } - - function subrequest_fn(r, subs, props) { - var replies = []; - - subs.forEach(sr => - r.subrequest(sr, collect.bind(null, replies, - props, subs.length))); - } - - function subrequest_fn_pr(r, subs, props) { - var replies = []; - - subs.forEach(sr => r.subrequest(sr) - .then(collect.bind(null, replies, props, subs.length))); - } - - function sr_except_not_a_func(r) { - r.subrequest('/sub1', 'a=1', 'b'); - } - - let Failed = {get toConvert() { return {toString(){return {};}}}}; - - function sr_except_failed_to_convert_options_arg(r) { - r.subrequest('/sub1', {args:Failed.toConvert}, ()=>{}); - } - - function sr_uri_except(r) { - r.subrequest(Failed.toConvert, 'a=1', 'b'); - } - - function body_fwd_cb(r) { - r.parent.return(200, JSON.stringify(JSON.parse(r.responseText))); - } - - function js_sub(r) { - r.return(200, '["JS-SUB"]'); - } - - export default {njs:test_njs, sr, sr_pr, sr_args, sr_options_args, - sr_options_args_pr, sr_options_method, sr_options_method_pr, - sr_options_method_head, sr_options_body, sr_body, - sr_body_pr, sr_body_special, body, delayed, detached, - sr_in_variable_handler, async_var, sr_error_page, - subrequest_var, sr_file, sr_cache, sr_unavail, sr_parent, - sr_unavail_pr, sr_broken, sr_too_large, sr_in_sr, - sr_js_in_subrequest, sr_js_in_subrequest_pr, js_sub, - sr_in_sr_callback, sr_out_of_order, sr_except_not_a_func, - sr_uri_except, sr_except_failed_to_convert_options_arg}; - -EOF - -$t->write_file('t', '["SEE-THIS"]'); - -$t->try_run('no njs available')->plan(32); -$t->run_daemon(\&http_daemon); - -############################################################################### - -is(get_json('/sr'), '[{"status":404,"uri":"/p/sub2"}]', 'sr'); -is(get_json('/sr_args'), '{"h":"xxx"}', 'sr_args'); -is(get_json('/sr_options_args'), '{"h":"xxx"}', 'sr_options_args'); -is(get_json('/sr_options_method?m=POST'), '["POST"]', 'sr method POST'); -is(get_json('/sr_options_method?m=PURGE'), '["PURGE"]', 'sr method PURGE'); -is(get_json('/sr_options_body'), '["REQ-BODY"]', 'sr_options_body'); -is(get_json('/sr_options_method_head'), '{"c":200}', 'sr_options_method_head'); -is(get_json('/sr_body'), '{"a":{"b":1}}', 'sr_body'); -is(get_json('/sr_body_special'), '{"e":"msg"}', 'sr_body_special'); -is(get_json('/sr_in_variable_handler'), '["CB-VAR"]', 'sr_in_variable_handler'); -is(get_json('/sr_file'), '["SEE-THIS"]', 'sr_file'); -is(get_json('/sr_cache?c=1'), '["SEE-THIS"]', 'sr_cache'); -is(get_json('/sr_cache?c=1'), '["SEE-THIS"]', 'sr_cached'); -is(get_json('/sr_js_in_subrequest'), '["JS-SUB"]', 'sr_js_in_subrequest'); -is(get_json('/sr_unavail'), '[{"status":502,"uri":"/unavail"}]', - 'sr_unavail'); -is(get_json('/sr_out_of_order'), - '[{"status":404,"uri":"/unknown"},' . - '{"status":206,"uri":"/p/sub1"},' . - '{"status":200,"uri":"/p/delayed"}]', - 'sr_multi'); - -is(get_json('/sr_pr'), '{"h":"xxx"}', 'sr_promise'); -is(get_json('/sr_options_args_pr'), '{"h":"xxx"}', 'sr_options_args_pr'); -is(get_json('/sr_options_method_pr?m=PUT'), '["PUT"]', 'sr method PUT'); -is(get_json('/sr_body_pr'), '{"a":{"b":1}}', 'sr_body_pr'); -is(get_json('/sr_js_in_subrequest_pr'), '["JS-SUB"]', 'sr_js_in_subrequest_pr'); -is(get_json('/sr_unavail_pr'), '[{"status":502,"uri":"/unavail"}]', - 'sr_unavail_pr'); - -like(http_get('/sr_detached_in_variable_handler'), qr/subrequest_var/, - 'sr_detached_in_variable_handler'); - -like(http_get('/sr_error_page'), qr/reply\.status:404/, - 'sr_error_page'); - -http_get('/sr_broken'); -http_get('/sr_in_sr'); -http_get('/sr_in_variable_handler'); -http_get('/sr_async_var'); -http_get('/sr_too_large'); -http_get('/sr_except_not_a_func'); -http_get('/sr_except_failed_to_convert_options_arg'); -http_get('/sr_uri_except'); - -is(get_json('/sr_in_sr_callback'), - '{"e":"subrequest can only be created for the primary request"}', - 'subrequest for non-primary request'); - -$t->stop(); - -ok(index($t->read_file('error.log'), 'callback is not a function') > 0, - 'subrequest cb exception'); -ok(index($t->read_file('error.log'), 'failed to convert uri arg') > 0, - 'subrequest uri exception'); -ok(index($t->read_file('error.log'), 'failed to convert options.args') > 0, - 'subrequest invalid args exception'); -ok(index($t->read_file('error.log'), 'too big subrequest response') > 0, - 'subrequest too large body'); -ok(index($t->read_file('error.log'), 'subrequest creation failed') > 0, - 'subrequest creation failed'); -ok(index($t->read_file('error.log'), - 'js subrequest: failed to get the parent context') > 0, - 'zero parent ctx'); - -ok(index($t->read_file('error.log'), 'DETACHED') > 0, - 'detached subrequest'); - -############################################################################### - -sub recode { - my $json; - eval { $json = JSON::PP::decode_json(shift) }; - - if ($@) { - return ""; - } - - JSON::PP->new()->canonical()->encode($json); -} - -sub get_json { - http_get(shift) =~ /\x0d\x0a?\x0d\x0a?(.*)/ms; - recode($1); -} - -############################################################################### - -sub http_daemon { - my $server = IO::Socket::INET->new( - Proto => 'tcp', - LocalAddr => '127.0.0.1:' . port(8082), - Listen => 5, - Reuse => 1 - ) - or die "Can't create listening socket: $!\n"; - - local $SIG{PIPE} = 'IGNORE'; - - while (my $client = $server->accept()) { - $client->autoflush(1); - - my $headers = ''; - my $uri = ''; - - while (<$client>) { - $headers .= $_; - last if (/^\x0d?\x0a?$/); - } - - $uri = $1 if $headers =~ /^\S+\s+([^ ]+)\s+HTTP/i; - - if ($uri eq '/unfinished') { - print $client - "HTTP/1.1 200 OK" . CRLF . - "Transfer-Encoding: chunked" . CRLF . - "Content-Length: 100" . CRLF . - CRLF . - "unfinished" . CRLF; - close($client); - } - } -} - -############################################################################### diff --git a/js_var.t b/js_var.t deleted file mode 100644 --- a/js_var.t +++ /dev/null @@ -1,90 +0,0 @@ -#!/usr/bin/perl - -# (C) Dmitry Volyntsev -# (C) Nginx, Inc. - -# Tests for http njs module, js_var directive. - -############################################################################### - -use warnings; -use strict; - -use Test::More; - -BEGIN { use FindBin; chdir($FindBin::Bin); } - -use lib 'lib'; -use Test::Nginx; - -############################################################################### - -select STDERR; $| = 1; -select STDOUT; $| = 1; - -my $t = Test::Nginx->new()->has(qw/http rewrite/) - ->write_file_expand('nginx.conf', <<'EOF'); - -%%TEST_GLOBALS%% - -daemon off; - -events { -} - -http { - %%TEST_GLOBALS_HTTP%% - - js_import test.js; - - js_var $foo; - js_var $bar a:$arg_a; - - server { - listen 127.0.0.1:8080; - server_name localhost; - - location /test { - js_content test.test; - } - - location /sub { - return 200 DONE; - } - - location /dest { - return 200 $bar; - } - } -} - -EOF - -$t->write_file('test.js', < { - r.variables.bar = reply.responseText; - r.internalRedirect('/dest'); - }); - - return; - } - - r.return(200, `V:\${r.variables[r.args.var]}`); - } - - export default {test}; - -EOF - -$t->try_run('no njs js_var')->plan(3); - -############################################################################### - -like(http_get('/test?var=bar&a=qq'), qr/200 OK.*V:a:qq$/s, 'default value'); -like(http_get('/test?var=foo'), qr/200 OK.*V:$/s, 'default empty value'); -like(http_get('/test?sub=1&var=bar&a=qq'), qr/200 OK.*DONE$/s, 'value set'); - -############################################################################### diff --git a/js_var2.t b/js_var2.t deleted file mode 100644 --- a/js_var2.t +++ /dev/null @@ -1,90 +0,0 @@ -#!/usr/bin/perl - -# (C) Dmitry Volyntsev -# (C) Nginx, Inc. - -# Tests for http njs module, js_var directive in server | location contexts. - -############################################################################### - -use warnings; -use strict; - -use Test::More; - -BEGIN { use FindBin; chdir($FindBin::Bin); } - -use lib 'lib'; -use Test::Nginx; - -############################################################################### - -select STDERR; $| = 1; -select STDOUT; $| = 1; - -my $t = Test::Nginx->new()->has(qw/http rewrite/) - ->write_file_expand('nginx.conf', <<'EOF'); - -%%TEST_GLOBALS%% - -daemon off; - -events { -} - -http { - %%TEST_GLOBALS_HTTP%% - - js_import test.js; - - server { - listen 127.0.0.1:8080; - server_name localhost; - - js_var $foo; - - location /test { - js_content test.test; - } - - location /sub { - return 200 DONE; - } - - location /dest { - js_var $bar a:$arg_a; - return 200 $bar; - } - } -} - -EOF - -$t->write_file('test.js', < { - r.variables.bar = reply.responseText; - r.internalRedirect('/dest'); - }); - - return; - } - - r.return(200, `V:\${r.variables[r.args.var]}`); - } - - export default {test}; - -EOF - -$t->try_run('no njs js_var')->plan(3); - -############################################################################### - -like(http_get('/test?var=bar&a=qq'), qr/200 OK.*V:a:qq$/s, 'default value'); -like(http_get('/test?var=foo'), qr/200 OK.*V:$/s, 'default empty value'); -like(http_get('/test?sub=1&var=bar&a=qq'), qr/200 OK.*DONE$/s, 'value set'); - -############################################################################### diff --git a/js_variables.t b/js_variables.t deleted file mode 100644 --- a/js_variables.t +++ /dev/null @@ -1,95 +0,0 @@ -#!/usr/bin/perl - -# (C) Dmitry Volyntsev -# (C) Nginx, Inc. - -# Tests for http njs module, setting nginx variables. - -############################################################################### - -use warnings; -use strict; - -use Test::More; - -BEGIN { use FindBin; chdir($FindBin::Bin); } - -use lib 'lib'; -use Test::Nginx; - -############################################################################### - -select STDERR; $| = 1; -select STDOUT; $| = 1; - -my $t = Test::Nginx->new()->has(qw/http rewrite/) - ->write_file_expand('nginx.conf', <<'EOF'); - -%%TEST_GLOBALS%% - -daemon off; - -events { -} - -http { - %%TEST_GLOBALS_HTTP%% - - js_set $test_var test.variable; - - js_import test.js; - - server { - listen 127.0.0.1:8080; - server_name localhost; - - set $foo test.foo_orig; - - location /var_set { - return 200 $test_var$foo; - } - - location /content_set { - js_content test.content_set; - } - - location /not_found_set { - js_content test.not_found_set; - } - } -} - -EOF - -$t->write_file('test.js', <try_run('no njs')->plan(3); - -############################################################################### - -like(http_get('/var_set?a=bar'), qr/test_varbar/, 'var set'); -like(http_get('/content_set?a=bar'), qr/bar/, 'content set'); -like(http_get('/not_found_set'), qr/variable not found/, 'not found exception'); - -############################################################################### diff --git a/stream_js.t b/stream_js.t deleted file mode 100644 --- a/stream_js.t +++ /dev/null @@ -1,502 +0,0 @@ -#!/usr/bin/perl - -# (C) Andrey Zelenkov -# (C) Dmitry Volyntsev -# (C) Nginx, Inc. - -# Tests for stream njs module. - -############################################################################### - -use warnings; -use strict; - -use Test::More; - -BEGIN { use FindBin; chdir($FindBin::Bin); } - -use lib 'lib'; -use Test::Nginx; -use Test::Nginx::Stream qw/ dgram stream /; - -############################################################################### - -select STDERR; $| = 1; -select STDOUT; $| = 1; - -my $t = Test::Nginx->new()->has(qw/http proxy rewrite stream stream_return udp/) - ->write_file_expand('nginx.conf', <<'EOF'); - -%%TEST_GLOBALS%% - -daemon off; - -events { -} - -http { - %%TEST_GLOBALS_HTTP%% - - js_import test.js; - - server { - listen 127.0.0.1:8079; - server_name localhost; - - location /njs { - js_content test.njs; - } - - location /p/ { - proxy_pass http://127.0.0.1:8095/; - - } - - location /return { - return 200 $http_foo; - } - } -} - -stream { - %%TEST_GLOBALS_STREAM%% - - js_set $js_addr test.addr; - js_set $js_var test.variable; - js_set $js_log test.log; - js_set $js_unk test.unk; - js_set $js_req_line test.req_line; - js_set $js_sess_unk test.sess_unk; - js_set $js_async test.asyncf; - - js_import test.js; - - log_format status $server_port:$status; - - server { - listen 127.0.0.1:8080; - return $js_addr; - } - - server { - listen 127.0.0.1:8081; - return $js_log; - } - - server { - listen 127.0.0.1:8082; - return $js_var; - } - - server { - listen 127.0.0.1:8083; - return $js_unk; - } - - server { - listen 127.0.0.1:8084; - return $js_sess_unk; - } - - server { - listen 127.0.0.1:%%PORT_8985_UDP%% udp; - return $js_addr; - } - - server { - listen 127.0.0.1:8086; - js_access test.access_step; - js_preread test.preread_step; - js_filter test.filter_step; - proxy_pass 127.0.0.1:8090; - } - - server { - listen 127.0.0.1:8087; - js_access test.access_undecided; - return OK; - access_log %%TESTDIR%%/status.log status; - } - - server { - listen 127.0.0.1:8088; - js_access test.access_allow; - return OK; - access_log %%TESTDIR%%/status.log status; - } - - server { - listen 127.0.0.1:8089; - js_access test.access_deny; - return OK; - access_log %%TESTDIR%%/status.log status; - } - - server { - listen 127.0.0.1:8091; - js_preread test.preread_async; - proxy_pass 127.0.0.1:8090; - } - - server { - listen 127.0.0.1:8092; - js_preread test.preread_data; - proxy_pass 127.0.0.1:8090; - } - - server { - listen 127.0.0.1:8093; - js_preread test.preread_req_line; - return $js_req_line; - } - - server { - listen 127.0.0.1:8094; - js_filter test.filter_empty; - proxy_pass 127.0.0.1:8090; - } - - server { - listen 127.0.0.1:8095; - js_filter test.filter_header_inject; - proxy_pass 127.0.0.1:8079; - } - - server { - listen 127.0.0.1:8096; - js_filter test.filter_search; - proxy_pass 127.0.0.1:8090; - } - - server { - listen 127.0.0.1:8097; - js_access test.access_except; - proxy_pass 127.0.0.1:8090; - } - - server { - listen 127.0.0.1:8098; - js_preread test.preread_except; - proxy_pass 127.0.0.1:8090; - } - - server { - listen 127.0.0.1:8099; - js_filter test.filter_except; - proxy_pass 127.0.0.1:8090; - } - - server { - listen 127.0.0.1:8100; - return $js_async; - } -} - -EOF - -$t->write_file('test.js', <= 3) { - s.done(); - } - }); - } - - function filter_step(s) { - s.on('upload', function(data, flags) { - s.send(data); - res += '3'; - }); - - s.on('download', function(data, flags) { - - if (!flags.last) { - res += '4'; - s.send(data); - - } else { - res += '5'; - s.send(res, {last:1}); - s.off('download'); - } - }); - } - - function access_undecided(s) { - s.decline(); - } - - function access_allow(s) { - if (s.remoteAddress.match('127.0.0.1')) { - s.done(); - return; - } - - s.deny(); - } - - function access_deny(s) { - if (s.remoteAddress.match('127.0.0.1')) { - s.deny(); - return; - } - - s.allow(); - } - - - function preread_async(s) { - setTimeout(function() { - s.done(); - }, 1); - } - - function preread_data(s) { - s.on('upload', function (data, flags) { - if (data.indexOf('z') != -1) { - s.done(); - } - }); - } - - var line = ''; - - function preread_req_line(s) { - s.on('upload', function (data, flags) { - var n = data.indexOf('\\n'); - if (n != -1) { - line = data.substr(0, n); - s.done(); - } - }); - } - - function req_line(s) { - return line; - } - - function filter_empty(s) { - } - - function filter_header_inject(s) { - var req = ''; - - s.on('upload', function(data, flags) { - req += data; - - var n = req.search('\\n'); - if (n != -1) { - var rest = req.substr(n + 1); - req = req.substr(0, n + 1); - - s.send(req + 'Foo: foo' + '\\r\\n' + rest, flags); - - s.off('upload'); - } - }); - } - - function filter_search(s) { - s.on('download', function(data, flags) { - var n = data.search('y'); - if (n != -1) { - s.send('z'); - } - }); - - s.on('upload', function(data, flags) { - var n = data.search('x'); - if (n != -1) { - s.send('y'); - } - }); - } - - function access_except(s) { - function done() {return s.a.a}; - - setTimeout(done, 1); - setTimeout(done, 2); - } - - function preread_except(s) { - var fs = require('fs'); - fs.readFileSync(); - } - - function filter_except(s) { - s.on('unknown', function() {}); - } - - function pr(x) { - return new Promise(resolve => {resolve(x)}).then(v => v).then(v => v); - } - - async function asyncf(s) { - const a1 = await pr(10); - const a2 = await pr(20); - - s.setReturnValue(`retval: \${a1 + a2}`); - } - - export default {njs:test_njs, addr, variable, sess_unk, log, access_step, - preread_step, filter_step, access_undecided, access_allow, - access_deny, preread_async, preread_data, preread_req_line, - req_line, filter_empty, filter_header_inject, filter_search, - access_except, preread_except, filter_except, asyncf}; - -EOF - -$t->run_daemon(\&stream_daemon, port(8090)); -$t->try_run('no stream njs available')->plan(23); -$t->waitforsocket('127.0.0.1:' . port(8090)); - -############################################################################### - -is(stream('127.0.0.1:' . port(8080))->read(), 'addr=127.0.0.1', - 's.remoteAddress'); -is(dgram('127.0.0.1:' . port(8985))->io('.'), 'addr=127.0.0.1', - 's.remoteAddress udp'); -is(stream('127.0.0.1:' . port(8081))->read(), 'undefined', 's.log'); -is(stream('127.0.0.1:' . port(8082))->read(), 'variable=127.0.0.1', - 's.variables'); -is(stream('127.0.0.1:' . port(8083))->read(), '', 'stream js unknown function'); -is(stream('127.0.0.1:' . port(8084))->read(), 'sess_unk=undefined', 's.unk'); - -is(stream('127.0.0.1:' . port(8086))->io('0'), '0122345', - 'async handlers order'); -is(stream('127.0.0.1:' . port(8087))->io('#'), 'OK', 'access_undecided'); -is(stream('127.0.0.1:' . port(8088))->io('#'), 'OK', 'access_allow'); -is(stream('127.0.0.1:' . port(8089))->io('#'), '', 'access_deny'); - -is(stream('127.0.0.1:' . port(8091))->io('#'), '#', 'preread_async'); -is(stream('127.0.0.1:' . port(8092))->io('#z'), '#z', 'preread_async_data'); -is(stream('127.0.0.1:' . port(8093))->io("xy\na"), 'xy', 'preread_req_line'); - -is(stream('127.0.0.1:' . port(8094))->io('x'), 'x', 'filter_empty'); -like(get('/p/return'), qr/foo/, 'filter_injected_header'); -is(stream('127.0.0.1:' . port(8096))->io('x'), 'z', 'filter_search'); - -stream('127.0.0.1:' . port(8097))->io('x'); -stream('127.0.0.1:' . port(8098))->io('x'); -stream('127.0.0.1:' . port(8099))->io('x'); - -TODO: { -local $TODO = 'not yet' unless has_version('0.7.0'); - -is(stream('127.0.0.1:' . port(8100))->read(), 'retval: 30', 'asyncf'); - -} - -$t->stop(); - -ok(index($t->read_file('error.log'), 'SEE-THIS') > 0, 'stream js log'); -ok(index($t->read_file('error.log'), 'at fs.readFileSync') > 0, - 'stream js_preread backtrace'); -ok(index($t->read_file('error.log'), 'at filter_except') > 0, - 'stream js_filter backtrace'); - -my @p = (port(8087), port(8088), port(8089)); -like($t->read_file('status.log'), qr/$p[0]:200/, 'status undecided'); -like($t->read_file('status.log'), qr/$p[1]:200/, 'status allow'); -like($t->read_file('status.log'), qr/$p[2]:403/, 'status deny'); - -############################################################################### - -sub has_version { - my $need = shift; - - get('/njs') =~ /^([.0-9]+)$/m; - - my @v = split(/\./, $1); - my ($n, $v); - - for $n (split(/\./, $need)) { - $v = shift @v || 0; - return 0 if $n > $v; - return 1 if $v > $n; - } - - return 1; -} - -############################################################################### - -sub stream_daemon { - my $server = IO::Socket::INET->new( - Proto => 'tcp', - LocalAddr => '127.0.0.1:' . port(8090), - Listen => 5, - Reuse => 1 - ) - or die "Can't create listening socket: $!\n"; - - local $SIG{PIPE} = 'IGNORE'; - - while (my $client = $server->accept()) { - $client->autoflush(1); - - log2c("(new connection $client)"); - - $client->sysread(my $buffer, 65536) or next; - - log2i("$client $buffer"); - - log2o("$client $buffer"); - - $client->syswrite($buffer); - - close $client; - } -} - -sub log2i { Test::Nginx::log_core('|| <<', @_); } -sub log2o { Test::Nginx::log_core('|| >>', @_); } -sub log2c { Test::Nginx::log_core('||', @_); } - -sub get { - my ($url, %extra) = @_; - - my $s = IO::Socket::INET->new( - Proto => 'tcp', - PeerAddr => '127.0.0.1:' . port(8079) - ) or die "Can't connect to nginx: $!\n"; - - return http_get($url, socket => $s); -} - -############################################################################### diff --git a/stream_js_buffer.t b/stream_js_buffer.t deleted file mode 100644 --- a/stream_js_buffer.t +++ /dev/null @@ -1,177 +0,0 @@ -#!/usr/bin/perl - -# (C) Dmitry Volyntsev -# (C) Nginx, Inc. - -# Tests for stream njs module, buffer properties. - -############################################################################### - -use warnings; -use strict; - -use Test::More; - -BEGIN { use FindBin; chdir($FindBin::Bin); } - -use lib 'lib'; -use Test::Nginx; -use Test::Nginx::Stream qw/ stream /; - -############################################################################### - -select STDERR; $| = 1; -select STDOUT; $| = 1; - -my $t = Test::Nginx->new()->has(qw/http proxy rewrite stream stream_return/) - ->write_file_expand('nginx.conf', <<'EOF'); - -%%TEST_GLOBALS%% - -daemon off; - -events { -} - -http { - %%TEST_GLOBALS_HTTP%% - - js_import test.js; - - server { - listen 127.0.0.1:8080; - server_name localhost; - - location /njs { - js_content test.njs; - } - - location /p/ { - proxy_pass http://127.0.0.1:8085/; - } - - location /return { - return 200 'RETURN:$http_foo'; - } - } -} - -stream { - %%TEST_GLOBALS_STREAM%% - - js_import test.js; - - js_set $type test.type; - js_set $binary_var test.binary_var; - - server { - listen 127.0.0.1:8081; - return $type; - } - - server { - listen 127.0.0.1:8082; - return $binary_var; - } - - server { - listen 127.0.0.1:8083; - js_preread test.cb_mismatch; - proxy_pass 127.0.0.1:8090; - } - - server { - listen 127.0.0.1:8084; - js_preread test.cb_mismatch2; - proxy_pass 127.0.0.1:8090; - } - - server { - listen 127.0.0.1:8085; - js_filter test.header_inject; - proxy_pass 127.0.0.1:8080; - } -} - -EOF - -$t->write_file('test.js', < {}); - s.on('downstream', () => {}); - } catch (e) { - throw new Error(`cb_mismatch:\${e.message}`) - } - } - - function cb_mismatch2(s) { - try { - s.on('upstream', () => {}); - s.on('download', () => {}); - } catch (e) { - throw new Error(`cb_mismatch2:\${e.message}`) - } - } - - function header_inject(s) { - var req = Buffer.from([]); - - s.on('upstream', function(data, flags) { - req = Buffer.concat([req, data]); - - var n = req.indexOf('\\n'); - if (n != -1) { - var rest = req.slice(n + 1); - req = req.slice(0, n + 1); - - s.send(req, flags); - s.send('Foo: foo\\r\\n', flags); - s.send(rest, flags); - - s.off('upstream'); - } - }); - } - - export default {njs: test_njs, type, binary_var, cb_mismatch, cb_mismatch2, - header_inject}; - -EOF - -$t->try_run('no njs ngx')->plan(5); - -############################################################################### - -is(stream('127.0.0.1:' . port(8081))->read(), 'buffer', 'var type'); -is(stream('127.0.0.1:' . port(8082))->read(), 'true', 'binary var'); - -stream('127.0.0.1:' . port(8083))->io('x'); -stream('127.0.0.1:' . port(8084))->io('x'); - -like(http_get('/p/return'), qr/RETURN:foo/, 'injected header'); - -$t->stop(); - -ok(index($t->read_file('error.log'), 'cb_mismatch:mixing string and buffer') - > 0, 'cb mismatch'); -ok(index($t->read_file('error.log'), 'cb_mismatch2:mixing string and buffer') - > 0, 'cb mismatch'); - -############################################################################### diff --git a/stream_js_exit.t b/stream_js_exit.t deleted file mode 100644 --- a/stream_js_exit.t +++ /dev/null @@ -1,152 +0,0 @@ -#!/usr/bin/perl - -# (C) Dmitry Volyntsev -# (C) Nginx, Inc. - -# Tests for stream njs module, exit hook. - -############################################################################### - -use warnings; -use strict; - -use Test::More; - -BEGIN { use FindBin; chdir($FindBin::Bin); } - -use lib 'lib'; -use Test::Nginx; -use Test::Nginx::Stream qw/ stream /; - -############################################################################### - -select STDERR; $| = 1; -select STDOUT; $| = 1; - -my $t = Test::Nginx->new()->has(qw/http stream/) - ->write_file_expand('nginx.conf', <<'EOF'); - -%%TEST_GLOBALS%% - -daemon off; - -events { -} - -http { - %%TEST_GLOBALS_HTTP%% - - js_import test.js; - - server { - listen 127.0.0.1:8080; - server_name localhost; - - location /njs { - js_content test.njs; - } - } -} - -stream { - %%TEST_GLOBALS_STREAM%% - - js_import test.js; - - server { - listen 127.0.0.1:8081; - js_access test.access; - js_filter test.filter; - proxy_pass 127.0.0.1:8090; - } - - server { - listen 127.0.0.1:8082; - js_access test.access; - proxy_pass 127.0.0.1:1; - } -} - -EOF - -$t->write_file('test.js', < { - var v = s.variables; - var c = `\${v.bytes_received}/\${v.bytes_sent}`; - var u = `\${v.upstream_bytes_received}/\${v.upstream_bytes_sent}`; - s.error(`s:\${s.status} C: \${c} U: \${u}`); - }); - - s.allow(); - } - - function filter(s) { - s.on('upload', (data, flags) => { - s.send(`@\${data}`, flags); - }); - - s.on('download', (data, flags) => { - s.send(data.slice(2), flags); - }); - } - - export default {njs: test_njs, access, filter}; -EOF - -$t->try_run('no stream njs available')->plan(2); - -$t->run_daemon(\&stream_daemon, port(8090)); -$t->waitforsocket('127.0.0.1:' . port(8090)); - -############################################################################### - -stream('127.0.0.1:' . port(8081))->io('###'); -stream('127.0.0.1:' . port(8082))->io('###'); - -$t->stop(); - -ok(index($t->read_file('error.log'), 's:200 C: 3/6 U: 8/4') > 0, 'normal'); -ok(index($t->read_file('error.log'), 's:502 C: 0/0 U: 0/0') > 0, 'failed conn'); - -############################################################################### - -sub stream_daemon { - my $server = IO::Socket::INET->new( - Proto => 'tcp', - LocalAddr => '127.0.0.1:' . port(8090), - Listen => 5, - Reuse => 1 - ) - or die "Can't create listening socket: $!\n"; - - local $SIG{PIPE} = 'IGNORE'; - - while (my $client = $server->accept()) { - $client->autoflush(1); - - log2c("(new connection $client)"); - - $client->sysread(my $buffer, 65536) or next; - - log2i("$client $buffer"); - - $buffer = $buffer . $buffer; - - log2o("$client $buffer"); - - $client->syswrite($buffer); - - close $client; - } -} - -sub log2i { Test::Nginx::log_core('|| <<', @_); } -sub log2o { Test::Nginx::log_core('|| >>', @_); } -sub log2c { Test::Nginx::log_core('||', @_); } - -############################################################################### diff --git a/stream_js_fetch.t b/stream_js_fetch.t deleted file mode 100644 --- a/stream_js_fetch.t +++ /dev/null @@ -1,277 +0,0 @@ -#!/usr/bin/perl - -# (C) Dmitry Volyntsev -# (C) Nginx, Inc. - -# Tests for stream njs module, fetch method. - -############################################################################### - -use warnings; -use strict; - -use Test::More; - -BEGIN { use FindBin; chdir($FindBin::Bin); } - -use lib 'lib'; -use Test::Nginx; -use Test::Nginx::Stream qw/ stream /; - -############################################################################### - -select STDERR; $| = 1; -select STDOUT; $| = 1; - -my $t = Test::Nginx->new()->has(qw/http stream/) - ->write_file_expand('nginx.conf', <<'EOF'); - -%%TEST_GLOBALS%% - -daemon off; - -events { -} - -http { - %%TEST_GLOBALS_HTTP%% - - js_import test.js; - - server { - listen 127.0.0.1:8080; - server_name localhost; - - location /njs { - js_content test.njs; - } - - location /validate { - js_content test.validate; - } - - location /success { - return 200; - } - - location /fail { - return 403; - } - } -} - -stream { - %%TEST_GLOBALS_STREAM%% - - js_import test.js; - - server { - listen 127.0.0.1:8081; - js_preread test.preread_verify; - proxy_pass 127.0.0.1:8090; - } - - server { - listen 127.0.0.1:8082; - js_filter test.filter_verify; - proxy_pass 127.0.0.1:8091; - } - - server { - listen 127.0.0.1:8083; - js_access test.access_ok; - proxy_pass 127.0.0.1:8090; - } - - server { - listen 127.0.0.1:8084; - js_access test.access_nok; - proxy_pass 127.0.0.1:8090; - } -} - -EOF - -my $p = port(8080); - -$t->write_file('test.js', <= 4 && collect.readUInt16BE(0) == 0xabcd) { - s.off('upstream'); - - let reply = await ngx.fetch('http://127.0.0.1:$p/validate', - {body: collect.slice(2,4)}); - - (reply.status == 200) ? s.done(): s.deny(); - - } else if (collect.length) { - s.deny(); - } - }); - } - - function filter_verify(s) { - var collect = Buffer.from([]); - - s.on('upstream', async function (data, flags) { - collect = Buffer.concat([collect, data]); - - if (collect.length >= 4 && collect.readUInt16BE(0) == 0xabcd) { - s.off('upstream'); - - let reply = await ngx.fetch('http://127.0.0.1:$p/validate', - {body: collect.slice(2,4)}); - - if (reply.status == 200) { - s.send(collect.slice(4), flags); - - } else { - s.send("__CLOSE__", flags); - } - } - }); - } - - async function access_ok(s) { - let reply = await ngx.fetch('http://127.0.0.1:$p/success'); - - (reply.status == 200) ? s.allow(): s.deny(); - } - - async function access_nok(s) { - let reply = await ngx.fetch('http://127.0.0.1:$p/fail'); - - (reply.status == 200) ? s.allow(): s.deny(); - } - - export default {njs: test_njs, validate, preread_verify, filter_verify, - access_ok, access_nok}; -EOF - -$t->try_run('no stream njs available')->plan(9); - -$t->run_daemon(\&stream_daemon, port(8090), port(8091)); -$t->waitforsocket('127.0.0.1:' . port(8090)); -$t->waitforsocket('127.0.0.1:' . port(8091)); - -############################################################################### - -is(stream('127.0.0.1:' . port(8081))->io('###'), '', 'preread not enough'); -is(stream('127.0.0.1:' . port(8081))->io("\xAB\xCDQZ##"), "\xAB\xCDQZ##", - 'preread validated'); -is(stream('127.0.0.1:' . port(8081))->io("\xAC\xCDQZ##"), '', - 'preread invalid magic'); -is(stream('127.0.0.1:' . port(8081))->io("\xAB\xCDQQ##"), '', - 'preread validation failed'); - -TODO: { -todo_skip 'leaves coredump', 3 unless $ENV{TEST_NGINX_UNSAFE} - or has_version('0.7.7'); - -my $s = stream('127.0.0.1:' . port(8082)); -is($s->io("\xAB\xCDQZ##", read => 1), '##', 'filter validated'); -is($s->io("@@", read => 1), '@@', 'filter off'); - -is(stream('127.0.0.1:' . port(8082))->io("\xAB\xCDQQ##"), '', - 'filter validation failed'); - -} - -is(stream('127.0.0.1:' . port(8083))->io('ABC'), 'ABC', 'access fetch ok'); -is(stream('127.0.0.1:' . port(8084))->io('ABC'), '', 'access fetch nok'); - -############################################################################### - -sub has_version { - my $need = shift; - - http_get('/njs') =~ /^([.0-9]+)$/m; - - my @v = split(/\./, $1); - my ($n, $v); - - for $n (split(/\./, $need)) { - $v = shift @v || 0; - return 0 if $n > $v; - return 1 if $v > $n; - } - - return 1; -} - -############################################################################### - -sub stream_daemon { - my (@ports) = @_; - my (@socks, @clients); - - for my $port (@ports) { - my $server = IO::Socket::INET->new( - Proto => 'tcp', - LocalAddr => "127.0.0.1:$port", - Listen => 5, - Reuse => 1 - ) - or die "Can't create listening socket: $!\n"; - push @socks, $server; - } - - my $sel = IO::Select->new(@socks); - - local $SIG{PIPE} = 'IGNORE'; - - while (my @ready = $sel->can_read) { - foreach my $fh (@ready) { - if (grep $_ == $fh, @socks) { - my $new = $fh->accept; - $new->autoflush(1); - $sel->add($new); - - } elsif (stream_handle_client($fh) - || $fh->sockport() == port(8090)) - { - $sel->remove($fh); - $fh->close; - } - } - } -} - -sub stream_handle_client { - my ($client) = @_; - - log2c("(new connection $client)"); - - $client->sysread(my $buffer, 65536) or return 1; - - log2i("$client $buffer"); - - if ($buffer eq "__CLOSE__") { - return 1; - } - - log2o("$client $buffer"); - - $client->syswrite($buffer); - - return 0; -} - -sub log2i { Test::Nginx::log_core('|| <<', @_); } -sub log2o { Test::Nginx::log_core('|| >>', @_); } -sub log2c { Test::Nginx::log_core('||', @_); } - -############################################################################### diff --git a/stream_js_fetch_https.t b/stream_js_fetch_https.t deleted file mode 100644 --- a/stream_js_fetch_https.t +++ /dev/null @@ -1,425 +0,0 @@ -#!/usr/bin/perl - -# (C) Dmitry Volyntsev -# (C) Nginx, Inc. - -# Tests for stream njs module, fetch method, https support. - -############################################################################### - -use warnings; -use strict; - -use Test::More; - -BEGIN { use FindBin; chdir($FindBin::Bin); } - -use lib 'lib'; -use Test::Nginx; -use Test::Nginx::Stream qw/ stream /; - -############################################################################### - -select STDERR; $| = 1; -select STDOUT; $| = 1; - -my $t = Test::Nginx->new() - ->has(qw/http http_ssl rewrite stream stream_return socket_ssl/) - ->has_daemon('openssl') - ->write_file_expand('nginx.conf', <<'EOF'); - -%%TEST_GLOBALS%% - -daemon off; - -events { -} - -http { - %%TEST_GLOBALS_HTTP%% - - js_import test.js; - - server { - listen 127.0.0.1:8080; - server_name localhost; - - location /njs { - js_content test.njs; - } - } - - server { - listen 127.0.0.1:8081 ssl default; - server_name default.example.com; - - ssl_certificate default.example.com.chained.crt; - ssl_certificate_key default.example.com.key; - - location /loc { - return 200 "You are at default.example.com."; - } - - location /success { - return 200; - } - - location /fail { - return 403; - } - - location /backend { - return 200 "BACKEND OK"; - } - } - - server { - listen 127.0.0.1:8081 ssl; - server_name 1.example.com; - - ssl_certificate 1.example.com.chained.crt; - ssl_certificate_key 1.example.com.key; - - location /loc { - return 200 "You are at 1.example.com."; - } - } -} - -stream { - %%TEST_GLOBALS_STREAM%% - - js_import test.js; - js_var $message; - - resolver 127.0.0.1:%%PORT_8981_UDP%%; - resolver_timeout 1s; - - server { - listen 127.0.0.1:8082; - js_preread test.preread; - return "default CA $message"; - } - - server { - listen 127.0.0.1:8083; - js_preread test.preread; - return "my CA $message"; - - js_fetch_ciphers HIGH:!aNull:!MD5; - js_fetch_protocols TLSv1.1 TLSv1.2; - js_fetch_trusted_certificate myca.crt; - } - - server { - listen 127.0.0.1:8084; - js_preread test.preread; - return "my CA with verify_depth=0 $message"; - - js_fetch_verify_depth 0; - js_fetch_trusted_certificate myca.crt; - } - - server { - listen 127.0.0.1:8085; - - js_access test.access_ok; - ssl_preread on; - - js_fetch_ciphers HIGH:!aNull:!MD5; - js_fetch_protocols TLSv1.1 TLSv1.2; - js_fetch_trusted_certificate myca.crt; - - proxy_pass 127.0.0.1:8081; - } - - server { - listen 127.0.0.1:8086; - - js_access test.access_nok; - ssl_preread on; - - js_fetch_ciphers HIGH:!aNull:!MD5; - js_fetch_protocols TLSv1.1 TLSv1.2; - js_fetch_trusted_certificate myca.crt; - - proxy_pass 127.0.0.1:8081; - } -} - -EOF - -my $p1 = port(8081); -my $p2 = port(8082); -my $p3 = port(8083); -my $p4 = port(8084); - -$t->write_file('test.js', < { - s.variables.message = 'https OK - ' + reply.status; - s.done(); - }) - .catch(e => { - s.variables.message = 'https NOK - ' + e.message; - s.done(); - }) - - } else if (data.length) { - s.deny(); - } - }); - } - - async function access_ok(s) { - let r = await ngx.fetch('https://default.example.com:$p1/success', - {body: s.remoteAddress}); - - (r.status == 200) ? s.allow(): s.deny(); - } - - async function access_nok(s) { - let r = await ngx.fetch('https://default.example.com:$p1/fail', - {body: s.remoteAddress}); - - (r.status == 200) ? s.allow(): s.deny(); - } - - export default {njs: test_njs, preread, access_ok, access_nok}; -EOF - -my $d = $t->testdir(); - -$t->write_file('openssl.conf', <write_file('myca.conf', <>$d/openssl.out 2>&1") == 0 - or die "Can't create self-signed certificate for CA: $!\n"; - -foreach my $name ('intermediate', 'default.example.com', '1.example.com') { - system("openssl req -new " - . "-config $d/openssl.conf -subj /CN=$name/ " - . "-out $d/$name.csr -keyout $d/$name.key " - . ">>$d/openssl.out 2>&1") == 0 - or die "Can't create certificate signing req for $name: $!\n"; -} - -$t->write_file('certserial', '1000'); -$t->write_file('certindex', ''); - -system("openssl ca -batch -config $d/myca.conf " - . "-keyfile $d/myca.key -cert $d/myca.crt " - . "-subj /CN=intermediate/ -in $d/intermediate.csr " - . "-out $d/intermediate.crt " - . ">>$d/openssl.out 2>&1") == 0 - or die "Can't sign certificate for intermediate: $!\n"; - -foreach my $name ('default.example.com', '1.example.com') { - system("openssl ca -batch -config $d/myca.conf " - . "-keyfile $d/intermediate.key -cert $d/intermediate.crt " - . "-subj /CN=$name/ -in $d/$name.csr -out $d/$name.crt " - . ">>$d/openssl.out 2>&1") == 0 - or die "Can't sign certificate for $name $!\n"; - $t->write_file("$name.chained.crt", $t->read_file("$name.crt") - . $t->read_file('intermediate.crt')); -} - -$t->try_run('no njs.fetch')->plan(6); - -$t->run_daemon(\&dns_daemon, port(8981), $t); -$t->waitforfile($t->testdir . '/' . port(8981)); - -############################################################################### - -local $TODO = 'not yet' unless has_version('0.7.0'); - -like(stream("127.0.0.1:$p2")->io('GOdefault.example.com'), - qr/connect failed/s, 'stream non trusted CA'); -like(stream("127.0.0.1:$p3")->io('GOdefault.example.com'), - qr/https OK/s, 'stream trusted CA'); -like(stream("127.0.0.1:$p3")->io('GOlocalhost'), - qr/connect failed/s, 'stream wrong CN'); -like(stream("127.0.0.1:$p4")->io('GOdefaul.example.com'), - qr/connect failed/s, 'stream verify_depth too small'); - -like(https_get('default.example.com', port(8085), '/backend'), - qr!BACKEND OK!, 'access https fetch'); -is(https_get('default.example.com', port(8086), '/backend'), '', - 'access https fetch not'); - -############################################################################### - -sub has_version { - my $need = shift; - - http_get('/njs') =~ /^([.0-9]+)$/m; - - my @v = split(/\./, $1); - my ($n, $v); - - for $n (split(/\./, $need)) { - $v = shift @v || 0; - return 0 if $n > $v; - return 1 if $v > $n; - } - - return 1; -} - -############################################################################### - -sub get_ssl_socket { - my ($host, $port) = @_; - my $s; - - eval { - local $SIG{ALRM} = sub { die "timeout\n" }; - local $SIG{PIPE} = sub { die "sigpipe\n" }; - alarm(8); - $s = IO::Socket::SSL->new( - Proto => 'tcp', - PeerAddr => '127.0.0.1:' . $port, - SSL_verify_mode => IO::Socket::SSL::SSL_VERIFY_NONE(), - SSL_error_trap => sub { die $_[1] } - ); - - alarm(0); - }; - - alarm(0); - - if ($@) { - log_in("died: $@"); - return undef; - } - - return $s; -} - -sub https_get { - my ($host, $port, $url) = @_; - my $s = get_ssl_socket($host, $port); - - if (!$s) { - return ''; - } - - return http(< $s); -GET $url HTTP/1.0 -Host: $host - -EOF -} - -############################################################################### - -sub reply_handler { - my ($recv_data, $port, %extra) = @_; - - my (@name, @rdata); - - use constant NOERROR => 0; - use constant A => 1; - use constant IN => 1; - - # default values - - my ($hdr, $rcode, $ttl) = (0x8180, NOERROR, 3600); - - # decode name - - my ($len, $offset) = (undef, 12); - while (1) { - $len = unpack("\@$offset C", $recv_data); - last if $len == 0; - $offset++; - push @name, unpack("\@$offset A$len", $recv_data); - $offset += $len; - } - - $offset -= 1; - my ($id, $type, $class) = unpack("n x$offset n2", $recv_data); - - my $name = join('.', @name); - - if ($type == A) { - push @rdata, rd_addr($ttl, '127.0.0.1'); - } - - $len = @name; - pack("n6 (C/a*)$len x n2", $id, $hdr | $rcode, 1, scalar @rdata, - 0, 0, @name, $type, $class) . join('', @rdata); -} - -sub rd_addr { - my ($ttl, $addr) = @_; - - my $code = 'split(/\./, $addr)'; - - return pack 'n3N', 0xc00c, A, IN, $ttl if $addr eq ''; - - pack 'n3N nC4', 0xc00c, A, IN, $ttl, eval "scalar $code", eval($code); -} - -sub dns_daemon { - my ($port, $t) = @_; - - my ($data, $recv_data); - my $socket = IO::Socket::INET->new( - LocalAddr => '127.0.0.1', - LocalPort => $port, - Proto => 'udp', - ) - or die "Can't create listening socket: $!\n"; - - local $SIG{PIPE} = 'IGNORE'; - - # signal we are ready - - open my $fh, '>', $t->testdir() . '/' . $port; - close $fh; - - while (1) { - $socket->recv($recv_data, 65536); - $data = reply_handler($recv_data, $port); - $socket->send($data); - } -} - -############################################################################### diff --git a/stream_js_fetch_init.t b/stream_js_fetch_init.t deleted file mode 100644 --- a/stream_js_fetch_init.t +++ /dev/null @@ -1,149 +0,0 @@ -#!/usr/bin/perl - -# (C) Dmitry Volyntsev -# (C) Nginx, Inc. - -# Tests for stream njs module, Response prototype reinitialization. - -############################################################################### - -use warnings; -use strict; - -use Test::More; - -BEGIN { use FindBin; chdir($FindBin::Bin); } - -use lib 'lib'; -use Test::Nginx; -use Test::Nginx::Stream qw/ stream /; - -############################################################################### - -select STDERR; $| = 1; -select STDOUT; $| = 1; - -my $t = Test::Nginx->new()->has(qw/http rewrite stream/) - ->write_file_expand('nginx.conf', <<'EOF'); - -%%TEST_GLOBALS%% - -daemon off; - -events { -} - -stream { - %%TEST_GLOBALS_STREAM%% - - js_import test.js; - - server { - listen 127.0.0.1:8081; - js_access test.access_ok; - proxy_pass 127.0.0.1:8090; - } -} - -http { - %%TEST_GLOBALS_HTTP%% - - js_import test.js; - - server { - listen 127.0.0.1:8080; - server_name localhost; - - location /njs { - js_content test.njs; - } - - location /success { - return 200; - } - } -} - -EOF - -my $p = port(8080); - -$t->write_file('test.js', <try_run('no stream njs available')->plan(1); - -$t->run_daemon(\&stream_daemon, port(8090)); -$t->waitforsocket('127.0.0.1:' . port(8090)); - -############################################################################### - -local $TODO = 'not yet' unless has_version('0.7.9'); - -is(stream('127.0.0.1:' . port(8081))->io('ABC'), 'ABC', 'access fetch ok'); - -############################################################################### - -sub has_version { - my $need = shift; - - http_get('/njs') =~ /^([.0-9]+)$/m; - - my @v = split(/\./, $1); - my ($n, $v); - - for $n (split(/\./, $need)) { - $v = shift @v || 0; - return 0 if $n > $v; - return 1 if $v > $n; - } - - return 1; -} - -############################################################################### - -sub stream_daemon { - my $server = IO::Socket::INET->new( - Proto => 'tcp', - LocalAddr => '127.0.0.1:' . port(8090), - Listen => 5, - Reuse => 1 - ) - or die "Can't create listening socket: $!\n"; - - local $SIG{PIPE} = 'IGNORE'; - - while (my $client = $server->accept()) { - $client->autoflush(1); - - log2c("(new connection $client)"); - - $client->sysread(my $buffer, 65536) or next; - - log2i("$client $buffer"); - - log2o("$client $buffer"); - - $client->syswrite($buffer); - - close $client; - } -} - -sub log2i { Test::Nginx::log_core('|| <<', @_); } -sub log2o { Test::Nginx::log_core('|| >>', @_); } -sub log2c { Test::Nginx::log_core('||', @_); } - -############################################################################### diff --git a/stream_js_import.t b/stream_js_import.t deleted file mode 100644 --- a/stream_js_import.t +++ /dev/null @@ -1,117 +0,0 @@ -#!/usr/bin/perl - -# (C) Dmitry Volyntsev -# (C) Nginx, Inc. - -# Tests for stream njs module, js_import directive. - -############################################################################### - -use warnings; -use strict; - -use Test::More; - -BEGIN { use FindBin; chdir($FindBin::Bin); } - -use lib 'lib'; -use Test::Nginx; -use Test::Nginx::Stream qw/ stream /; - -############################################################################### - -select STDERR; $| = 1; -select STDOUT; $| = 1; - -my $t = Test::Nginx->new()->has(qw/http stream stream_return/) - ->write_file_expand('nginx.conf', <<'EOF'); - -%%TEST_GLOBALS%% - -daemon off; - -events { -} - -stream { - %%TEST_GLOBALS_STREAM%% - - js_set $test foo.bar.p; - - js_import lib.js; - js_import foo from ./main.js; - - server { - listen 127.0.0.1:8081; - return $test; - } - - server { - listen 127.0.0.1:8082; - js_access lib.access; - js_preread lib.preread; - js_filter lib.filter; - proxy_pass 127.0.0.1:8083; - } - - server { - listen 127.0.0.1:8083; - return "x"; - } -} - -EOF - -$t->write_file('lib.js', <= 3) { - s.done(); - } - }); - } - - function filter(s) { - s.on('upload', function(data, flags) { - s.send(data); - res += '3'; - }); - - s.on('download', function(data, flags) { - if (!flags.last) { - res += '4'; - s.send(data); - - } else { - res += '5'; - s.send(res, {last:1}); - s.off('download'); - } - }); - } - - export default {access, preread, filter}; - -EOF - -$t->write_file('main.js', <try_run('no njs available')->plan(2); - -############################################################################### - -is(stream('127.0.0.1:' . port(8081))->read(), 'P-TEST', 'foo.bar.p'); -is(stream('127.0.0.1:' . port(8082))->io('0'), 'x122345', 'lib.access'); - -############################################################################### diff --git a/stream_js_import2.t b/stream_js_import2.t deleted file mode 100644 --- a/stream_js_import2.t +++ /dev/null @@ -1,117 +0,0 @@ -#!/usr/bin/perl - -# (C) Dmitry Volyntsev -# (C) Nginx, Inc. - -# Tests for stream njs module, js_import directive in server context. - -############################################################################### - -use warnings; -use strict; - -use Test::More; - -BEGIN { use FindBin; chdir($FindBin::Bin); } - -use lib 'lib'; -use Test::Nginx; -use Test::Nginx::Stream qw/ stream /; - -############################################################################### - -select STDERR; $| = 1; -select STDOUT; $| = 1; - -my $t = Test::Nginx->new()->has(qw/stream stream_return/) - ->write_file_expand('nginx.conf', <<'EOF'); - -%%TEST_GLOBALS%% - -daemon off; - -events { -} - -stream { - %%TEST_GLOBALS_STREAM%% - - server { - listen 127.0.0.1:8081; - js_import foo from ./main.js; - js_set $test foo.bar.p; - return $test; - } - - server { - listen 127.0.0.1:8082; - - js_import lib.js; - - js_access lib.access; - js_preread lib.preread; - js_filter lib.filter; - proxy_pass 127.0.0.1:8083; - } - - server { - listen 127.0.0.1:8083; - return "x"; - } -} - -EOF - -$t->write_file('lib.js', <= 3) { - s.done(); - } - }); - } - - function filter(s) { - s.on('upload', function(data, flags) { - s.send(data); - res += '3'; - }); - - s.on('download', function(data, flags) { - if (!flags.last) { - res += '4'; - s.send(data); - - } else { - res += '5'; - s.send(res, {last:1}); - s.off('download'); - } - }); - } - - export default {access, preread, filter}; - -EOF - -$t->write_file('main.js', <try_run('no njs available')->plan(2); - -############################################################################### - -is(stream('127.0.0.1:' . port(8081))->read(), 'P-TEST', 'foo.bar.p'); -is(stream('127.0.0.1:' . port(8082))->io('0'), 'x122345', 'lib.access'); - -############################################################################### diff --git a/stream_js_ngx.t b/stream_js_ngx.t deleted file mode 100644 --- a/stream_js_ngx.t +++ /dev/null @@ -1,94 +0,0 @@ -#!/usr/bin/perl - -# (C) Dmitry Volyntsev -# (C) Nginx, Inc. - -# Tests for stream njs module, ngx object. - -############################################################################### - -use warnings; -use strict; - -use Test::More; - -BEGIN { use FindBin; chdir($FindBin::Bin); } - -use lib 'lib'; -use Test::Nginx; -use Test::Nginx::Stream qw/ stream /; - -############################################################################### - -select STDERR; $| = 1; -select STDOUT; $| = 1; - -my $t = Test::Nginx->new()->has(qw/stream stream_return/) - ->write_file_expand('nginx.conf', <<'EOF'); - -%%TEST_GLOBALS%% - -daemon off; - -events { -} - -http { - %%TEST_GLOBALS_HTTP%% - - js_import test.js; - - server { - listen 127.0.0.1:8080; - server_name localhost; - - location /njs { - js_content test.njs; - } - } -} - -stream { - %%TEST_GLOBALS_STREAM%% - - js_import test.js; - - js_set $log test.log; - - server { - listen 127.0.0.1:8081; - return $log; - } -} - -EOF - -$t->write_file('test.js', <try_run('no njs ngx')->plan(4); - -############################################################################### - -is(stream('127.0.0.1:' . port(8081))->read(), 'OK', 'log var'); - -$t->stop(); - -like($t->read_file('error.log'), qr/\[info\].*ngx.log:FOO/, 'ngx.log info'); -like($t->read_file('error.log'), qr/\[warn\].*ngx.log:BAR/, 'ngx.log warn'); -like($t->read_file('error.log'), qr/\[error\].*ngx.log:BAZ/, 'ngx.log err'); - -############################################################################### diff --git a/stream_js_object.t b/stream_js_object.t deleted file mode 100644 --- a/stream_js_object.t +++ /dev/null @@ -1,98 +0,0 @@ -#!/usr/bin/perl - -# (C) Dmitry Volyntsev -# (C) Nginx, Inc. - -# Tests for stream njs module, stream session object. - -############################################################################### - -use warnings; -use strict; - -use Test::More; - -BEGIN { use FindBin; chdir($FindBin::Bin); } - -use lib 'lib'; -use Test::Nginx; -use Test::Nginx::Stream qw/ stream /; - -############################################################################### - -select STDERR; $| = 1; -select STDOUT; $| = 1; - -my $t = Test::Nginx->new()->has(qw/stream stream_return/) - ->write_file_expand('nginx.conf', <<'EOF'); - -%%TEST_GLOBALS%% - -daemon off; - -events { -} - -stream { - %%TEST_GLOBALS_STREAM%% - - js_set $test test.test; - - js_import test.js; - - server { - listen 127.0.0.1:8081; - return $test$status; - } -} - -EOF - -$t->write_file('test.js', <v in s.variables) - .toString() === 'true,false'; - } - - function redefine_proto(s) { - s[0] = 'a'; - s[1] = 'b'; - s.length = 2; - Object.setPrototypeOf(s, Array.prototype); - return s.join('|') === 'a|b'; - } - - function get_own_prop_descs(s) { - return Object.getOwnPropertyDescriptors(s)['on'].value === s.on; - } - - function test(s) { - return [ to_string, - define_prop, - in_operator, - redefine_proto, - get_own_prop_descs, - ].every(v=>v(s)); - } - - export default {test}; - -EOF - -$t->try_run('no njs stream session object')->plan(1); - -############################################################################### - -is(stream('127.0.0.1:' . port(8081))->read(), 'true400', 'var set'); - -############################################################################### diff --git a/stream_js_preload_object.t b/stream_js_preload_object.t deleted file mode 100644 --- a/stream_js_preload_object.t +++ /dev/null @@ -1,122 +0,0 @@ -#!/usr/bin/perl - -# (C) Vadim Zhestikov -# (C) Nginx, Inc. - -# Tests for stream njs module, js_preload_object directive. - -############################################################################### - -use warnings; -use strict; - -use Test::More; - -BEGIN { use FindBin; chdir($FindBin::Bin); } - -use lib 'lib'; -use Test::Nginx; -use Test::Nginx::Stream qw/ stream /; - -############################################################################### - -select STDERR; $| = 1; -select STDOUT; $| = 1; - -my $t = Test::Nginx->new()->has(qw/stream stream_return/) - ->write_file_expand('nginx.conf', <<'EOF'); - -%%TEST_GLOBALS%% - -daemon off; - -events { -} - -stream { - %%TEST_GLOBALS_STREAM%% - - js_preload_object g1 from g.json; - - js_set $test foo.bar.p; - - js_import lib.js; - js_import foo from ./main.js; - - server { - listen 127.0.0.1:8081; - return $test; - } - - server { - listen 127.0.0.1:8082; - js_access lib.access; - js_preread lib.preread; - js_filter lib.filter; - proxy_pass 127.0.0.1:8083; - } - - server { - listen 127.0.0.1:8083; - return "x"; - } -} - -EOF - -$t->write_file('lib.js', <= 3) { - s.done(); - } - }); - } - - function filter(s) { - s.on('upload', function(data, flags) { - s.send(data); - res += g1.c.prop[0].a; - }); - - s.on('download', function(data, flags) { - if (!flags.last) { - res += g1.b[3]; - s.send(data); - - } else { - res += g1.b[4]; - s.send(res, {last:1}); - s.off('download'); - } - }); - } - - export default {access, preread, filter}; - -EOF - -$t->write_file('main.js', <write_file('g.json', - '{"a":1, "b":[1,2,"element",4,5], "c":{"prop":[{"a":3}]}}'); - -$t->try_run('no js_preload_object available')->plan(2); - -############################################################################### - -is(stream('127.0.0.1:' . port(8081))->read(), 'element', 'foo.bar.p'); -is(stream('127.0.0.1:' . port(8082))->io('0'), 'x122345', 'lib.access'); - -############################################################################### diff --git a/stream_js_send.t b/stream_js_send.t deleted file mode 100644 --- a/stream_js_send.t +++ /dev/null @@ -1,205 +0,0 @@ -#!/usr/bin/perl - -# (C) Dmitry Volyntsev -# (C) Nginx, Inc. - -# Tests for s.send() in stream njs module. - -############################################################################### - -use warnings; -use strict; - -use Test::More; - -BEGIN { use FindBin; chdir($FindBin::Bin); } - -use lib 'lib'; -use Test::Nginx; -use Test::Nginx::Stream qw/ stream /; - -############################################################################### - -select STDERR; $| = 1; -select STDOUT; $| = 1; - -my $t = Test::Nginx->new()->has(qw/http stream/) - ->write_file_expand('nginx.conf', <<'EOF'); - -%%TEST_GLOBALS%% - -daemon off; - -events { -} - -http { - %%TEST_GLOBALS_HTTP%% - - js_import test.js; - - server { - listen 127.0.0.1:8080; - server_name localhost; - - location /njs { - js_content test.njs; - } - } -} - -stream { - %%TEST_GLOBALS_STREAM%% - - js_import test.js; - - server { - listen 127.0.0.1:8081; - js_filter test.filter; - proxy_pass 127.0.0.1:8090; - } - - server { - listen 127.0.0.1:8082; - js_filter test.filter_direct; - proxy_pass 127.0.0.1:8090; - } -} - -EOF - -$t->write_file('test.js', < { - s.send("__HANDSHAKE__", flags); - - const p = new Promise((resolve, reject) => { - s.on("download", (data, flags) => { - s.off("download"); - resolve(data); - }); - }); - - s.off("upload"); - - const handshakeResponse = await p; - if (handshakeResponse != '__HANDSHAKE_RESPONSE__') { - throw `Handshake failed: \${handshakeResponse}`; - } - - s.send(data, flags); - }); - } - - function filter_direct(s) { - s.on("upload", async (data, flags) => { - s.sendUpstream("__HANDSHAKE__", flags); - - const p = new Promise((resolve, reject) => { - s.on("download", (data, flags) => { - s.off("download"); - resolve(data); - }); - }); - - s.off("upload"); - - const handshakeResponse = await p; - if (handshakeResponse != '__HANDSHAKE_RESPONSE__') { - throw `Handshake failed: \${handshakeResponse}`; - } - - s.sendDownstream('xxx', flags); - s.sendUpstream(data, flags); - }); - } - - export default {njs:test_njs, filter, filter_direct}; - -EOF - -$t->run_daemon(\&stream_daemon, port(8090)); -$t->try_run('no stream njs available')->plan(2); -$t->waitforsocket('127.0.0.1:' . port(8090)); - -############################################################################### - -is(stream('127.0.0.1:' . port(8081))->io('abc'), 'ABC', - 'async filter');; -is(stream('127.0.0.1:' . port(8082))->io('abc'), 'xxxABC', - 'async filter direct'); - -$t->stop(); - -############################################################################### - -sub has_version { - my $need = shift; - - http_get('/njs') =~ /^([.0-9]+)$/m; - - my @v = split(/\./, $1); - my ($n, $v); - - for $n (split(/\./, $need)) { - $v = shift @v || 0; - return 0 if $n > $v; - return 1 if $v > $n; - } - - return 1; -} - -############################################################################### - -sub stream_daemon { - my $server = IO::Socket::INET->new( - Proto => 'tcp', - LocalAddr => '127.0.0.1:' . port(8090), - Listen => 5, - Reuse => 1 - ) - or die "Can't create listening socket: $!\n"; - - local $SIG{PIPE} = 'IGNORE'; - - while (my $client = $server->accept()) { - $client->autoflush(1); - - log2c("(new connection $client)"); - - $client->sysread(my $buffer, 65536) or next; - - log2i("$client $buffer"); - - if ($buffer ne "__HANDSHAKE__") { - $buffer = "__HANDSHAKE_INVALID__"; - log2o("$client $buffer"); - $client->syswrite($buffer); - - close $client; - } - - $buffer = "__HANDSHAKE_RESPONSE__"; - log2o("$client $buffer"); - $client->syswrite($buffer); - - $client->sysread($buffer, 65536) or next; - - $buffer = uc($buffer); - log2o("$client $buffer"); - $client->syswrite($buffer); - - close $client; - } -} - -sub log2i { Test::Nginx::log_core('|| <<', @_); } -sub log2o { Test::Nginx::log_core('|| >>', @_); } -sub log2c { Test::Nginx::log_core('||', @_); } - -############################################################################### diff --git a/stream_js_var.t b/stream_js_var.t deleted file mode 100644 --- a/stream_js_var.t +++ /dev/null @@ -1,75 +0,0 @@ -#!/usr/bin/perl - -# (C) Dmitry Volyntsev -# (C) Nginx, Inc. - -# Tests for stream njs module, js_var directive. - -############################################################################### - -use warnings; -use strict; - -use Test::More; - -BEGIN { use FindBin; chdir($FindBin::Bin); } - -use lib 'lib'; -use Test::Nginx; -use Test::Nginx::Stream qw/ stream /; - -############################################################################### - -select STDERR; $| = 1; -select STDOUT; $| = 1; - -my $t = Test::Nginx->new()->has(qw/stream stream_return/) - ->write_file_expand('nginx.conf', <<'EOF'); - -%%TEST_GLOBALS%% - -daemon off; - -events { -} - -stream { - %%TEST_GLOBALS_STREAM%% - - js_import test.js; - - js_var $foo; - js_var $bar a:$remote_addr; - js_set $var test.varr; - - server { - listen 127.0.0.1:8081; - return $bar$foo; - } - - server { - listen 127.0.0.1:8082; - return $var$foo; - } -} - -EOF - -$t->write_file('test.js', <try_run('no stream js_var')->plan(2); - -############################################################################### - -is(stream('127.0.0.1:' . port(8081))->io('###'), 'a:127.0.0.1', - 'default value'); -is(stream('127.0.0.1:' . port(8082))->io('###'), 'xxx', 'value set'); - -############################################################################### diff --git a/stream_js_var2.t b/stream_js_var2.t deleted file mode 100644 --- a/stream_js_var2.t +++ /dev/null @@ -1,75 +0,0 @@ -#!/usr/bin/perl - -# (C) Dmitry Volyntsev -# (C) Nginx, Inc. - -# Tests for stream njs module, js_var directive in server context. - -############################################################################### - -use warnings; -use strict; - -use Test::More; - -BEGIN { use FindBin; chdir($FindBin::Bin); } - -use lib 'lib'; -use Test::Nginx; -use Test::Nginx::Stream qw/ stream /; - -############################################################################### - -select STDERR; $| = 1; -select STDOUT; $| = 1; - -my $t = Test::Nginx->new()->has(qw/stream stream_return/) - ->write_file_expand('nginx.conf', <<'EOF'); - -%%TEST_GLOBALS%% - -daemon off; - -events { -} - -stream { - %%TEST_GLOBALS_STREAM%% - - js_import test.js; - - js_var $foo; - - server { - listen 127.0.0.1:8081; - js_var $bar a:$remote_addr; - return $bar$foo; - } - - server { - listen 127.0.0.1:8082; - js_set $var test.varr; - return $var$foo; - } -} - -EOF - -$t->write_file('test.js', <try_run('no stream js_var')->plan(2); - -############################################################################### - -is(stream('127.0.0.1:' . port(8081))->io('###'), 'a:127.0.0.1', - 'default value'); -is(stream('127.0.0.1:' . port(8082))->io('###'), 'xxx', 'value set'); - -############################################################################### diff --git a/stream_js_variables.t b/stream_js_variables.t deleted file mode 100644 --- a/stream_js_variables.t +++ /dev/null @@ -1,84 +0,0 @@ -#!/usr/bin/perl - -# (C) Dmitry Volyntsev -# (C) Nginx, Inc. - -# Tests for stream njs module, setting nginx variables. - -############################################################################### - -use warnings; -use strict; - -use Test::More; - -BEGIN { use FindBin; chdir($FindBin::Bin); } - -use lib 'lib'; -use Test::Nginx; -use Test::Nginx::Stream qw/ stream /; - -############################################################################### - -select STDERR; $| = 1; -select STDOUT; $| = 1; - -my $t = Test::Nginx->new()->has(qw/stream stream_return/) - ->write_file_expand('nginx.conf', <<'EOF'); - -%%TEST_GLOBALS%% - -daemon off; - -events { -} - -stream { - %%TEST_GLOBALS_STREAM%% - - js_set $test_var test.variable; - js_set $test_not_found test.not_found; - - js_import test.js; - - server { - listen 127.0.0.1:8081; - return $test_var$status; - } - - server { - listen 127.0.0.1:8082; - return $test_not_found; - } -} - -EOF - -$t->write_file('test.js', <try_run('no stream njs available')->plan(2); - -############################################################################### - -is(stream('127.0.0.1:' . port(8081))->read(), 'test_var400', 'var set'); -is(stream('127.0.0.1:' . port(8082))->read(), 'not_found', 'not found set'); - -$t->stop(); - -###############################################################################