From 6ad9f4b54ee16ffecea7e16b710552b45db33a16 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Mon, 5 Jun 2023 10:12:47 +0000 Subject: [PATCH 18/23] early_hints supports Rack 3 array headers We can hoist out append_headers into a new method and use it in both e103_response_write and http_response_write. t/integration.t now tests early_hints with both possible values of check_client_connection. --- t/integration.ru | 7 +++++++ t/integration.t | 47 ++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 49 insertions(+), 5 deletions(-) diff --git a/t/integration.ru b/t/integration.ru index edc408c..dab384d 100644 --- a/t/integration.ru +++ b/t/integration.ru @@ -5,6 +5,11 @@ # this goes for t/integration.t We'll try to put as many tests # in here as possible to avoid startup overhead of Ruby. +def early_hints(env, val) + env['rack.early_hints'].call('link' => val) # val may be ary or string + [ 200, {}, [ val.class.to_s ] ] +end + $orig_rack_200 = nil def tweak_status_code $orig_rack_200 = Rack::Utils::HTTP_STATUS_CODES[200] @@ -81,6 +86,8 @@ def rack_input_tests(env) when '/env_dump'; [ 200, {}, [ env_dump(env) ] ] when '/write_on_close'; write_on_close when '/pid'; [ 200, {}, [ "#$$\n" ] ] + when '/early_hints_rack2'; early_hints(env, "r\n2") + when '/early_hints_rack3'; early_hints(env, %w(r 3)) else '/'; [ 200, {}, [ env_dump(env) ] ] end # case PATH_INFO (GET) when 'POST' diff --git a/t/integration.t b/t/integration.t index 855c260..8433497 100644 --- a/t/integration.t +++ b/t/integration.t @@ -13,8 +13,16 @@ my $t0 = time; my $conf = "$tmpdir/u.conf.rb"; open my $conf_fh, '>', $conf; $conf_fh->autoflush(1); +my $u1 = "$tmpdir/u1"; +print $conf_fh < $srv }); my $curl = which('curl'); +my $fifo = "$tmpdir/fifo"; +POSIX::mkfifo($fifo, 0600) or die "mkfifo: $!"; my %PUT = ( chunked_md5 => sub { my ($in, $out, $path, %opt) = @_; @@ -102,6 +110,26 @@ $c = tcp_start($srv, 'GET /nil-header-value HTTP/1.0'); is_deeply([grep(/^X-Nil:/, @$hdr)], ['X-Nil: '], 'nil header value accepted for broken apps') or diag(explain($hdr)); +my $ck_early_hints = sub { + my ($note) = @_; + $c = unix_start($u1, 'GET /early_hints_rack2 HTTP/1.0'); + ($status, $hdr) = slurp_hdr($c); + like($status, qr!\AHTTP/1\.[01] 103\b!, 'got 103 for rack 2 value'); + is_deeply(['link: r', 'link: 2'], $hdr, 'rack 2 hints match '.$note); + ($status, $hdr) = slurp_hdr($c); + like($status, qr!\AHTTP/1\.[01] 200\b!, 'got 200 afterwards'); + is(readline($c), 'String', 'early hints used a String for rack 2'); + + $c = unix_start($u1, 'GET /early_hints_rack3 HTTP/1.0'); + ($status, $hdr) = slurp_hdr($c); + like($status, qr!\AHTTP/1\.[01] 103\b!, 'got 103 for rack 3'); + is_deeply(['link: r', 'link: 3'], $hdr, 'rack 3 hints match '.$note); + ($status, $hdr) = slurp_hdr($c); + like($status, qr!\AHTTP/1\.[01] 200\b!, 'got 200 afterwards'); + is(readline($c), 'Array', 'early hints used a String for rack 3'); +}; +$ck_early_hints->('ccc off'); # we'll retest later + if ('TODO: ensure Rack::Utils::HTTP_STATUS_CODES is available') { $c = tcp_start($srv, 'POST /tweak-status-code HTTP/1.0'); ($status, $hdr) = slurp_hdr($c); @@ -154,6 +182,7 @@ if ('bad requests') { # input tests my ($blob_size, $blob_hash); SKIP: { + skip 'SKIP_EXPENSIVE on', 1 if $ENV{SKIP_EXPENSIVE}; CORE::open(my $rh, '<', 't/random_blob') or skip "t/random_blob not generated $!", 1; $blob_size = -s $rh; @@ -232,16 +261,24 @@ SKIP: { # SIGHUP-able stuff goes here +if ('check_client_connection') { + print $conf_fh <do_kill('HUP'); + open my $fifo_fh, '<', $fifo; + my $wpid = readline($fifo_fh); + like($wpid, qr/\Apid=\d+\z/a , 'new worker ready'); + $ck_early_hints->('ccc on'); +} + if ('max_header_len internal API') { undef $c; my $req = 'GET / HTTP/1.0'; my $len = length($req."\r\n\r\n"); - my $fifo = "$tmpdir/fifo"; - POSIX::mkfifo($fifo, 0600) or die "mkfifo: $!"; - print $conf_fh <do_kill('HUP'); open my $fifo_fh, '<', $fifo;