From 76fd6caba8a3f661a4b8fdf8c82cd5856874be6f Mon Sep 17 00:00:00 2001 From: Samuel Williams Date: Wed, 3 Jan 2024 20:10:11 +1300 Subject: [PATCH] Minor rewrite of streaming upload example. --- examples/streaming_upload/config.ru | 108 +++++++++--------- .../{Gemfile.lock => gems.locked} | 36 +++--- .../streaming_upload/{Gemfile => gems.rb} | 0 .../{README.txt => readme.md} | 8 +- 4 files changed, 74 insertions(+), 78 deletions(-) rename examples/streaming_upload/{Gemfile.lock => gems.locked} (73%) rename examples/streaming_upload/{Gemfile => gems.rb} (100%) rename examples/streaming_upload/{README.txt => readme.md} (90%) diff --git a/examples/streaming_upload/config.ru b/examples/streaming_upload/config.ru index 98a253a7..e0882a2d 100755 --- a/examples/streaming_upload/config.ru +++ b/examples/streaming_upload/config.ru @@ -5,65 +5,59 @@ require 'digest' require 'securerandom' -module Protocol - module HTTP1 - class Connection - def write_continue - @stream.write("HTTP/1.1 100 Continue\r\n\r\n") - @stream.flush - end - end - end -end - class BodyHandler - attr_reader :time, :md5, :size, :uuid - - def initialize(input, length) - @uuid = SecureRandom.uuid - @input = input - @length = length - end - - def receive - start = Time.now - @md5 = Digest::MD5.new - @size = 0 - @done = false - - until @done - begin - chunk = @input.read(10_240) # read will raise EOF so we have to check - rescue EOFError - puts "Seems we're done" - chunk = nil - end - if chunk.nil? - @done = true - else - @md5.update(chunk) - @size += chunk.bytesize - @done = true if @length == @size - end - end - - @time = Time.now - start - end + attr_reader :time, :md5, :size, :uuid + + def initialize(input, length) + @uuid = SecureRandom.uuid + @input = input + @length = length + end + + def receive + start = Time.now + @md5 = Digest::MD5.new + @size = 0 + @done = false + + until @done + begin + chunk = @input.read(1024*1024) # read will raise EOF so we have to check + rescue EOFError + Console.info(self, "Received EOF") + chunk = nil + end + + if chunk.nil? + @done = true + else + @md5.update(chunk) + @size += chunk.bytesize + @done = true if @length == @size + end + end + + @time = Time.now - start + end end run lambda { |env| - request = env['protocol.http.request'] - handler = BodyHandler.new(env['rack.input'], env['CONTENT_LENGTH']) - puts "#{env['REQUEST_METHOD']} #{handler.uuid}: #{request.path} #{env['CONTENT_LENGTH']}" - - if env['REQUEST_METHOD'] == 'POST' - request.connection.write_continue if request.headers['expect'] == ['100-continue'] - handler.receive - msg = "Uploaded #{handler.uuid}: #{handler.md5} #{handler.time} #{handler.size}" - puts msg - [200, {}, [msg]] - else - sleep 1 - [200, {}, ["#{env['REQUEST_METHOD']}: #{request.path}\n"]] - end + request = env['protocol.http.request'] + handler = BodyHandler.new(env['rack.input'], env['CONTENT_LENGTH']) + Console.info(self, "#{env['REQUEST_METHOD']} #{handler.uuid}: #{request.path} #{env['CONTENT_LENGTH']}") + + if env['REQUEST_METHOD'] == 'POST' + if request.headers['expect']&.include?('100-continue') + request.write_interim_response(Protocol::HTTP::Response[100]) + end + + handler.receive + + Console.info(handler, "Received #{handler.size} bytes in #{handler.time} seconds", uuid: handler.uuid, md5: handler.md5) + + [200, {}, ["Uploaded #{handler.uuid}: #{handler.md5} #{handler.time} #{handler.size}"]] + else + sleep 1 + [200, {}, ["#{env['REQUEST_METHOD']}: #{request.path}\n"]] + end } diff --git a/examples/streaming_upload/Gemfile.lock b/examples/streaming_upload/gems.locked similarity index 73% rename from examples/streaming_upload/Gemfile.lock rename to examples/streaming_upload/gems.locked index 00dac55f..be774b6f 100644 --- a/examples/streaming_upload/Gemfile.lock +++ b/examples/streaming_upload/gems.locked @@ -1,29 +1,31 @@ GEM remote: https://rubygems.org/ specs: - async (2.5.0) + async (2.8.0) console (~> 1.10) + fiber-annotation io-event (~> 1.1) timers (~> 4.1) async-container (0.16.12) async async-io - async-http (0.60.1) + async-http (0.61.0) async (>= 1.25) async-io (>= 1.28) async-pool (>= 0.2) - protocol-http (~> 0.24.0) - protocol-http1 (~> 0.15.0) + protocol-http (~> 0.25.0) + protocol-http1 (~> 0.16.0) protocol-http2 (~> 0.15.0) - traces (>= 0.8.0) + traces (>= 0.10.0) async-http-cache (0.4.3) async-http (~> 0.56) - async-io (1.34.3) + async-io (1.38.1) async async-pool (0.4.0) async (>= 1.25) build-environment (1.13.0) - console (1.16.2) + console (1.23.3) + fiber-annotation fiber-local falcon (0.42.3) async @@ -38,36 +40,38 @@ GEM process-metrics (~> 0.2.0) protocol-rack (~> 0.1) samovar (~> 2.1) + fiber-annotation (0.2.0) fiber-local (1.0.0) - io-event (1.1.7) + io-event (1.4.0) localhost (1.1.10) mapping (1.1.1) - openssl (3.1.0) + openssl (3.2.0) process-metrics (0.2.1) console (~> 1.8) samovar (~> 2.1) protocol-hpack (1.4.2) - protocol-http (0.24.1) - protocol-http1 (0.15.0) + protocol-http (0.25.0) + protocol-http1 (0.16.1) protocol-http (~> 0.22) protocol-http2 (0.15.1) protocol-hpack (~> 1.4) protocol-http (~> 0.18) - protocol-rack (0.2.4) + protocol-rack (0.4.1) protocol-http (~> 0.23) rack (>= 1.0) - rack (3.0.7) - samovar (2.1.4) + rack (3.0.8) + samovar (2.2.0) console (~> 1.0) mapping (~> 1.0) timers (4.3.5) - traces (0.9.1) + traces (0.11.1) PLATFORMS + ruby x86_64-linux DEPENDENCIES falcon BUNDLED WITH - 2.4.6 + 2.5.3 diff --git a/examples/streaming_upload/Gemfile b/examples/streaming_upload/gems.rb similarity index 100% rename from examples/streaming_upload/Gemfile rename to examples/streaming_upload/gems.rb diff --git a/examples/streaming_upload/README.txt b/examples/streaming_upload/readme.md similarity index 90% rename from examples/streaming_upload/README.txt rename to examples/streaming_upload/readme.md index 1bd8ff7b..e6a6eee8 100644 --- a/examples/streaming_upload/README.txt +++ b/examples/streaming_upload/readme.md @@ -4,17 +4,15 @@ The filesize was 82078050 bytes. - - - ## concurrent requests ``` -bundle exec falcon host ./falcon.rb +> bundle exec falcon host ./falcon.rb ``` - ``` +> dd if=/dev/zero of=./testfile bs=82078050 count=1 +> ab -n 100 -c 8 -p ./testfile -H "Expect: 100-continue" http://localhost:9292/ This is ApacheBench, Version 2.3 <$Revision: 1879490 $> Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/ Licensed to The Apache Software Foundation, http://www.apache.org/