summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xplugins/tests/check_curl.t194
1 files changed, 193 insertions, 1 deletions
diff --git a/plugins/tests/check_curl.t b/plugins/tests/check_curl.t
index 52c5ad1c..bc0101a2 100755
--- a/plugins/tests/check_curl.t
+++ b/plugins/tests/check_curl.t
@@ -20,6 +20,11 @@ use Test::More;
20use NPTest; 20use NPTest;
21use FindBin qw($Bin); 21use FindBin qw($Bin);
22 22
23use URI;
24use URI::QueryParam;
25use HTTP::Daemon;
26use HTTP::Daemon::SSL;
27
23$ENV{'LC_TIME'} = "C"; 28$ENV{'LC_TIME'} = "C";
24 29
25my $common_tests = 75; 30my $common_tests = 75;
@@ -186,6 +191,149 @@ sub run_server {
186 $c->send_response('moved to /redirect2'); 191 $c->send_response('moved to /redirect2');
187 } elsif ($r->url->path eq "/redir_timeout") { 192 } elsif ($r->url->path eq "/redir_timeout") {
188 $c->send_redirect( "/timeout" ); 193 $c->send_redirect( "/timeout" );
194 } elsif ($r->url->path =~ m{^/redirect_with_increment}) {
195 # <scheme>://<username>:<password>@<host>:<port>/<path>;<parameters>?<query>#<fragment>
196 # Find every parameter, query , and fragment keys and increment them
197
198 my $content = "";
199
200 # Use URI to help with query/fragment; parse path params manually.
201 my $original_url = $r->url->as_string;
202 $content .= " original_url: ${original_url}\n";
203 my $uri = URI->new($original_url);
204 $content .= " uri: ${uri}\n";
205
206 my $path = $uri->path // '';
207 my $query = $uri->query // '';
208 my $fragment = $uri->fragment // '';
209
210 $content .= " path: ${path}\n";
211 $content .= " query: ${query}\n";
212 $content .= " fragment: ${fragment}\n";
213
214 # Sets and returns the scheme-specific part of the $uri (everything between the scheme and the fragment) as an escaped string.
215 #my $opaque = $uri->opaque;
216 #$content .= " opaque: ${opaque}\n";
217
218 # group 1 is captured: anything that is not '/' : ([^/]*)
219 # / matches the / directly
220 # group 2 is captured: anything : (.*)
221 #my ($before_slash, $after_slash) = $opaque =~ m{^/([^/]*)/(.*)$};
222 #$before_slash //= '';
223 #$after_slash //= '';
224 #$content .= " before_slash: ${before_slash}\n";
225 #$content .= " after_slash: ${after_slash}\n";
226
227 # split the uri part and parameters. uri package cannot do this
228 # group 1 is captured: anything without a semicolon: ([^;])
229 # group 2 is uncaptured: (?:;(.*))?
230 # (? )? prevents the capture
231 # in between the ';' matches the first ever semicolon
232 # group3 is captured: any character stirng : (.*)
233 my ($before_params, $params) = $uri =~ m{^([^;]*)(?:;(.*))?\?};
234 $before_params //= '';
235 $params //= '';
236 $content .= " before_params: ${before_params}\n";
237 $content .= " params: ${params}\n";
238 my @parameter_pairs;
239 if (defined $params && length $params) {
240 for my $p (split /;/, $params) {
241 my ($key,$value) = split /=/, $p, 2;
242 $value //= '';
243 push @parameter_pairs, [ $key, $value ];
244 $content .= " parameter: ${key} -> ${value}\n";
245 }
246 }
247
248 # query parameters are offered directly from the library
249 my @query_form = $uri->query_form;
250 my @query_parameter_pairs;
251 while (@query_form) {
252 my $key = shift @query_form;
253 my $value = shift @query_form;
254 $value //= ''; # there can be valueless keys
255 push @query_parameter_pairs, [ $key, $value ];
256 $content .= " query: ${key} -> ${value}\n";
257 }
258
259 # fragment: try to split into key=value pairs on ';' or '&' if present
260 my @fragment_pairs;
261 my $fragment_seperator = '';
262 if ($fragment ne '') {
263 $fragment_seperator = ($fragment =~ /&/ ? '&' : ';');
264 for my $f (split /[&;]/, $fragment) {
265 next unless length $f;
266 my ($key,$value) = split /=/, $f, 2;
267 $value //= '';
268 push @fragment_pairs, [ $key, $value ];
269 $content .= " fragment: ${key} -> ${value}\n";
270 }
271 }
272
273 # helper to increment value
274 my $increment = sub {
275 my ($v) = @_;
276 return $v if !defined $v || $v eq '';
277 # numeric integer
278 if ($v =~ /^-?\d+$/) {
279 return $v + 1;
280 }
281 # otherwise -> increment as if its an ascii character
282 # sed replacement syntax, but the $& holds the matched character
283 if (length($v)) {
284 (my $new_v = $v) =~ s/./chr(ord($&) + 1)/ge;
285 return $new_v;
286 }
287 };
288
289 # increment values in pairs
290 for my $pair (@parameter_pairs) {
291 $pair->[1] = $increment->($pair->[1]);
292 $content .= " parameter new: " . $pair->[0] . " -> " . $pair->[1] . "\n";
293 }
294 for my $pair (@query_parameter_pairs) {
295 $pair->[1] = $increment->($pair->[1]);
296 $content .= " query parameter new: " . $pair->[0] . " -> " . $pair->[1] . "\n";
297 }
298 for my $pair (@fragment_pairs) {
299 $pair->[1] = $increment->($pair->[1]);
300 $content .= " fragment new: " . $pair->[0] . " -> " . $pair->[1] . "\n";
301 }
302
303 # rebuild strings
304 my $new_parameter_str = join(';', map { $_->[0] . '=' . $_->[1] } @parameter_pairs);
305 $content .= " new_parameter_str: ${new_parameter_str}\n";
306
307 # library can rebuild from an array
308 my @new_query_form;
309 for my $p (@query_parameter_pairs) { push @new_query_form, $p->[0], $p->[1] }
310
311 my $new_fragment_str = '';
312 if (@fragment_pairs) {
313 $new_fragment_str = join($fragment_seperator, map { $_->[0] . '=' . $_->[1] } @fragment_pairs);
314 }
315 $content .= " new_fragment_str: ${new_fragment_str}\n";
316
317 # construct new URI using the library
318 my $new_uri = URI->new('');
319 $new_uri->path( $before_params . ($new_parameter_str ? ';' . $new_parameter_str : '') );
320 $new_uri->query_form( \@new_query_form ) if @new_query_form;
321 $new_uri->fragment( $new_fragment_str ) if $new_fragment_str ne '';
322 $content .= " new_uri: ${new_uri}\n";
323
324 # Redirect until fail_count or redirect_count reaches 3
325 if ($new_uri =~ /fail_count=3/){
326 $c->send_error(HTTP::Status->RC_FORBIDDEN, "fail count reached 3, url path:" . $r->url->path );
327 } elsif ($new_uri =~ /redirect_count=3/){
328 $c->send_response(HTTP::Response->new( 200, 'OK', undef , $content ));
329 } elsif ($new_uri =~ /location_redirect_count=3/){
330 $c->send_basic_header(302);
331 $c->send_header("Location", "$new_uri" );
332 $c->send_crlf;
333 $c->send_response("$content \n moved to $new_uri");
334 } else {
335 $c->send_redirect( $new_uri->as_string, 301, $content );
336 }
189 } elsif ($r->url->path eq "/timeout") { 337 } elsif ($r->url->path eq "/timeout") {
190 # Keep $c from being destroyed, but prevent severe leaks 338 # Keep $c from being destroyed, but prevent severe leaks
191 unshift @persist, $c; 339 unshift @persist, $c;
@@ -215,7 +363,7 @@ sub run_server {
215 return($chunk); 363 return($chunk);
216 })); 364 }));
217 } else { 365 } else {
218 $c->send_error(HTTP::Status->RC_FORBIDDEN); 366 $c->send_error(HTTP::Status->RC_FORBIDDEN, "unknown url path:" . $r->url->path );
219 } 367 }
220 $c->close; 368 $c->close;
221 } 369 }
@@ -482,6 +630,50 @@ sub run_common_tests {
482 is( $result->return_code, 0, $cmd); 630 is( $result->return_code, 0, $cmd);
483 like( $result->output, '/.*HTTP/1.1 200 OK - \d+ bytes in [\d\.]+ second.*/', "Output correct: ".$result->output ); 631 like( $result->output, '/.*HTTP/1.1 200 OK - \d+ bytes in [\d\.]+ second.*/', "Output correct: ".$result->output );
484 632
633 # Redirect with increment tests. These are for checking if the url parameters, query parameters and fragment are parsed.
634 # The server at this point has dynamic redirection. It tries to increment values that it sees in these fields, then redirects.
635 # It also appends some debug log and writes it into HTTP content, pass the -vvv parameter to see them.
636
637 $cmd = "$command -p $port_http -u '/redirect_with_increment/path1/path2/path3/path4' --onredirect=follow -vvv";
638 $result = NPTest->testCmd( "$cmd" );
639 is( $result->return_code, 1, $cmd);
640 like( $result->output, '/.*HTTP/1.1 403 Forbidden - \d+ bytes in [\d\.]+ second.*/', "Output correct, redirect_count was not present, got redirected to / : ".$result->output );
641
642 $cmd = "$command -p $port_http -u '/redirect_with_increment/path1/path2;redirect_count=0;p1=1;p2=ab?qp1=10&qp2=kl#f1=test' --onredirect=follow -vvv";
643 $result = NPTest->testCmd( "$cmd" );
644 is( $result->return_code, 0, $cmd);
645 like( $result->output, '/.*HTTP/1.1 200 OK - \d+ bytes in [\d\.]+ second.*/', "Output correct, redirect_count went up to 3: ".$result->output );
646
647 $cmd = "$command -p $port_http -u '/redirect_with_increment/path1/path2;location_redirect_count=0;p1=1;p2=ab?qp1=10&qp2=kl#f1=test' --onredirect=follow -vvv";
648 $result = NPTest->testCmd( "$cmd" );
649 is( $result->return_code, 0, $cmd);
650 like( $result->output, '/.*HTTP/1.1 200 OK - \d+ bytes in [\d\.]+ second.*/', "Output correct, location_redirect_count went up to 3: ".$result->output );
651
652 $cmd = "$command -p $port_http -u '/redirect_with_increment/path1/path2;redirect_count=0;fail_count=2' --onredirect=follow -vvv";
653 $result = NPTest->testCmd( "$cmd" );
654 is( $result->return_code, 1, $cmd);
655 like( $result->output, '/.*HTTP/1.1 403 Forbidden - \d+ bytes in [\d\.]+ second.*/', "Output correct, early due to fail_count reaching 3: ".$result->output );
656
657 $cmd = "$command -p $port_http -u '/redirect_with_increment/path1/path2;redirect_count=0;p1=1;p2=ab?qp1=10&qp2=kl#f1=test' --onredirect=follow -vvv";
658 $result = NPTest->testCmd( "$cmd" );
659 is( $result->return_code, 0, $cmd);
660 like( $result->output, '/.*;p1=3;p2=cd\?*/', "Output correct, parsed and incremented both parameters p1 and p2 : ".$result->output );
661
662 $cmd = "$command -p $port_http -u '/redirect_with_increment/path1/path2;redirect_count=0;p1=1;p2=ab?qp1=10&qp2=kl#f1=test' --onredirect=follow -vvv";
663 $result = NPTest->testCmd( "$cmd" );
664 is( $result->return_code, 0, $cmd);
665 like( $result->output, '/.*\?qp1=12&qp2=mn*/', "Output correct, parsed and incremented both query parameters qp1 and qp2 : ".$result->output );
666
667 $cmd = "$command -p $port_http -u '/redirect_with_increment;redirect_count=0;?qp0=0&qp1=1&qp2=2&qp3=3&qp4=4&qp5=5' --onredirect=follow -vvv";
668 $result = NPTest->testCmd( "$cmd" );
669 is( $result->return_code, 0, $cmd);
670 like( $result->output, '/.*\?qp0=2&qp1=3&qp2=4&qp3=5&qp4=6&qp5=7*/', "Output correct, parsed and incremented query parameters qp1,qp2,qp3,qp4,qp5 in order : ".$result->output );
671
672 $cmd = "$command -p $port_http -u '/redirect_with_increment/path1/path2;redirect_count=0;p1=1;p2=ab?qp1=10&qp2=kl#f1=test' --onredirect=follow -vvv";
673 $result = NPTest->testCmd( "$cmd" );
674 is( $result->return_code, 0, $cmd);
675 like( $result->output, '/.*#f1=vguv*/', "Output correct, parsed and incremented fragment f1 : ".$result->output );
676
485 # These tests may block 677 # These tests may block
486 # stickyport - on full urlS port is set back to 80 otherwise 678 # stickyport - on full urlS port is set back to 80 otherwise
487 $cmd = "$command -f stickyport -u /redir_external -t 5 -s redirected"; 679 $cmd = "$command -f stickyport -u /redir_external -t 5 -s redirected";