I've setup some test cases with yahns on https://80x24.org:8443/
to handle large uploads and return the MD5
curl -v -T large_file https://80x24.org:8443/
curl -v -T large_file https://80x24.org:8443/gets_read_mix
curl -v -T large_file https://80x24.org:8443/each
Where large_file is <= 1GB
For each of the endpoints, the MD5 hexdigest matches
the output of md5sum large_file
.
All of these match for me with random-sized buffers at the Rack
app level. yahns always uses the buffer arg for
SSLSocket#read_nonblock
I run yahns with the following command and config files below:
/path/to/bin/yahns -c /path/to/yahns.conf.rb
==> /path/to/yahns.conf.rb <==
disclaimer: I don't know if this HTTPS configuration is correct¶
require 'openssl'
ctx = OpenSSL::SSL::SSLContext.new
ctx.cert = OpenSSL::X509::Certificate.new(IO.read(
'/path/to/ssl/certs/example.com.crt'))
ctx.extra_chain_cert = [ OpenSSL::X509::Certificate.new(IO.read(
'/path/to/ssl/certs/example.com.chain.crt')) ]
ctx.key = OpenSSL::PKey::RSA.new(IO.read(
'/path/to/ssl/private/example.com.key'))
ctx.set_params(verify_mode: OpenSSL::SSL::VERIFY_NONE)
ctx.session_cache_mode = OpenSSL::SSL::SSLContext::SESSION_CACHE_SERVER
app(:rack, '/path/to/config.ru', preload: true) do
listen 8443, ssl_ctx: ctx
listen '[::]:8443', ipv6only: true, ssl_ctx: ctx
client_max_body_size(1024 * 1024 * 1024)
client_timeout 5
output_buffering false
input_buffering false
end
==> /path/to/config.ru <==
map('http://80x24.org/') do
use Rack::Head
run(lambda do |env|
case env['REQUEST_METHOD']
when 'PUT'
cap = 0x1000000
/\A100-continue\z/i =~ env['HTTP_EXPECT'] and return [ 100, {}, [] ]
digest = Digest::MD5.new
input = env['rack.input']
case env["PATH_INFO"]
when "/gets_read_mix"
if buf = input.gets
begin
digest.update(buf)
end while input.read(rand(cap), buf)
end
when "/each"
input.each do |b|
digest.update(b)
b.clear
end
else
if buf = input.read(rand(cap))
begin
raise "#{buf.size} > #{cap}" if buf.size > cap
digest.update(buf)
end while input.read(rand(cap), buf)
end
end
buf&.clear
[ 200, {
'Content-Type' => -'text/plain',
'Content-Length' => -'33',
}, [ "#{digest.hexdigest}\n" ] ]
else
[ 405, {
'Content-Type' => -'text/plain',
'Content-Length' => -'3'
}, [ "no\n" ] ]
end
end)
end