diff options
author | Eric Wong <BOFH@YHBT.net> | 2023-06-05 10:12:49 +0000 |
---|---|---|
committer | Eric Wong <bofh@yhbt.net> | 2023-06-05 10:39:01 +0000 |
commit | f2e34f618dc012973cf7fff1e4ca82817e5b5c48 (patch) | |
tree | 234ad6510ca38590aeb1d406f06e49f57961a78f | |
parent | f542e431401fa2dbd8bd15847a6540da81680754 (diff) | |
download | unicorn-f2e34f618dc012973cf7fff1e4ca82817e5b5c48.tar.gz |
MD5 is faster, and these tests aren't meant to be secure, they're just for checking for data corruption. Furthermore, Content-MD5 is a supported HTTP trailer and we can verify that here to obsolete other tests. Furthermore, we can reuse buffers on env['rack.input'].read calls to avoid malloc(3) and GC overhead. Combined, these give roughly a 3% speedup for t/integration.t on my system.
-rw-r--r-- | t/integration.ru | 20 | ||||
-rw-r--r-- | t/integration.t | 5 | ||||
-rw-r--r-- | t/preread_input.ru | 17 |
3 files changed, 29 insertions, 13 deletions
diff --git a/t/integration.ru b/t/integration.ru index dab384d..086126a 100644 --- a/t/integration.ru +++ b/t/integration.ru @@ -55,8 +55,8 @@ end def rack_input_tests(env) return [ 100, {}, [] ] if /\A100-continue\z/i =~ env['HTTP_EXPECT'] cap = 16384 - require 'digest/sha1' - digest = Digest::SHA1.new + require 'digest/md5' + dig = Digest::MD5.new input = env['rack.input'] case env['PATH_INFO'] when '/rack_input/size_first'; input.size @@ -68,11 +68,21 @@ def rack_input_tests(env) if buf = input.read(rand(cap)) begin raise "#{buf.size} > #{cap}" if buf.size > cap - digest.update(buf) + dig.update(buf) end while input.read(rand(cap), buf) + buf.clear # remove this call if Ruby ever gets escape analysis end - [ 200, {'content-length' => '40', 'content-type' => 'text/plain'}, - [ digest.hexdigest ] ] + h = { 'content-type' => 'text/plain' } + if env['HTTP_TRAILER'] =~ /\bContent-MD5\b/i + cmd5_b64 = env['HTTP_CONTENT_MD5'] or return [500, {}, ['No Content-MD5']] + cmd5_bin = cmd5_b64.unpack('m')[0] + if cmd5_bin != dig.digest + h['content-length'] = cmd5_b64.size.to_s + return [ 500, h, [ cmd5_b64 ] ] + end + end + h['content-length'] = '32' + [ 200, h, [ dig.hexdigest ] ] end run(lambda do |env| diff --git a/t/integration.t b/t/integration.t index 8433497..38a9675 100644 --- a/t/integration.t +++ b/t/integration.t @@ -27,7 +27,6 @@ my %PUT = ( chunked_md5 => sub { my ($in, $out, $path, %opt) = @_; my $bs = $opt{bs} // 16384; - require Digest::MD5; my $dig = Digest::MD5->new; print $out <<EOM; PUT $path HTTP/1.1\r @@ -186,8 +185,8 @@ SKIP: { CORE::open(my $rh, '<', 't/random_blob') or skip "t/random_blob not generated $!", 1; $blob_size = -s $rh; - require Digest::SHA; - $blob_hash = Digest::SHA->new(1)->addfile($rh)->hexdigest; + require Digest::MD5; + $blob_hash = Digest::MD5->new->addfile($rh)->hexdigest; my $ck_hash = sub { my ($sub, $path, %opt) = @_; diff --git a/t/preread_input.ru b/t/preread_input.ru index f0a1748..18af221 100644 --- a/t/preread_input.ru +++ b/t/preread_input.ru @@ -1,15 +1,22 @@ #\-E none -require 'digest/sha1' +require 'digest/md5' require 'unicorn/preread_input' use Unicorn::PrereadInput nr = 0 run lambda { |env| $stderr.write "app dispatch: #{nr += 1}\n" input = env["rack.input"] - dig = Digest::SHA1.new - while buf = input.read(16384) - dig.update(buf) + dig = Digest::MD5.new + if buf = input.read(16384) + begin + dig.update(buf) + end while input.read(16384, buf) + buf.clear # remove this call if Ruby ever gets escape analysis + end + if env['HTTP_TRAILER'] =~ /\bContent-MD5\b/i + cmd5_b64 = env['HTTP_CONTENT_MD5'] or return [500, {}, ['No Content-MD5']] + cmd5_bin = cmd5_b64.unpack('m')[0] + return [500, {}, [ cmd5_b64 ] ] if cmd5_bin != dig.digest end - [ 200, {}, [ dig.hexdigest ] ] } |