I had a deeper look. I tried to convert the test suite to using Rack3 (and rackup). I pushed my changes to branch 'rack3'.
But then I run into the following test failures: 1) Ethon::Easy::Http::Custom#setup when body when multipart when requesting submits a body Failure/Error: expect(easy.response_body).to match('"body":".+"') expected "{\"CONTENT_LENGTH\":\"5029\",\"CONTENT_TYPE\":\"multipart/form-data; boundary=----------------------...ackup::Handler::WEBrick::Input:0x00007ff04c22a1c0>\",\"sinatra.route\":\"PURGE /**\",\"body\":\"\"}" to match "\"body\":\".+\"" # ./spec/ethon/easy/http/custom_spec.rb:83:in `block (6 levels) in <top (required)>' 2) Ethon::Easy::Http::Custom#setup when body when not multipart when requesting submits a body Failure/Error: expect(easy.response_body).to match('"body":"a=1%26b%3D2"') expected "{\"CONTENT_LENGTH\":\"11\",\"CONTENT_TYPE\":\"application/x-www-form-urlencoded\",\"GATEWAY_INTERFAC...ackup::Handler::WEBrick::Input:0x00007ff04c0f4cd8>\",\"sinatra.route\":\"PURGE /**\",\"body\":\"\"}" to match "\"body\":\"a=1%26b%3D2\"" # ./spec/ethon/easy/http/custom_spec.rb:126:in `block (6 levels) in <top (required)>' 3) Ethon::Easy::Http::Custom#setup when body when string when requesting sends string Failure/Error: expect(easy.response_body).to include('"body":"{a: 1}"') expected "{\"CONTENT_LENGTH\":\"6\",\"CONTENT_TYPE\":\"application/x-www-form-urlencoded\",\"GATEWAY_INTERFACE...ackup::Handler::WEBrick::Input:0x00007ff04dd58230>\",\"sinatra.route\":\"PURGE /**\",\"body\":\"\"}" to include "\"body\":\"{a: 1}\"" # ./spec/ethon/easy/http/custom_spec.rb:150:in `block (6 levels) in <top (required)>' 4) Ethon::Easy::Http::Custom#setup when params and body when requesting body contains form Failure/Error: expect(easy.response_body).to include('"body":"a=1"') expected "{\"CONTENT_LENGTH\":\"3\",\"CONTENT_TYPE\":\"application/x-www-form-urlencoded\",\"GATEWAY_INTERFACE...ackup::Handler::WEBrick::Input:0x00007ff04c75ed30>\",\"sinatra.route\":\"PURGE /**\",\"body\":\"\"}" to include "\"body\":\"a=1\"" # ./spec/ethon/easy/http/custom_spec.rb:172:in `block (5 levels) in <top (required)>' 5) Ethon::Easy::Http::Post#setup when body when multipart when requesting submits a body Failure/Error: expect(easy.response_body).to match('"body":".+"') expected "{\"CONTENT_LENGTH\":\"8779\",\"CONTENT_TYPE\":\"multipart/form-data; boundary=----------------------...Rackup::Handler::WEBrick::Input:0x00007ff04dd28170>\",\"sinatra.route\":\"POST /**\",\"body\":\"\"}" to match "\"body\":\".+\"" # ./spec/ethon/easy/http/post_spec.rb:183:in `block (6 levels) in <top (required)>' 6) Ethon::Easy::Http::Post#setup when body when not multipart when requesting submits a body Failure/Error: expect(easy.response_body).to match('"body":"a=1%26b%3D2"') expected "{\"CONTENT_LENGTH\":\"11\",\"CONTENT_TYPE\":\"application/x-www-form-urlencoded\",\"GATEWAY_INTERFAC...Rackup::Handler::WEBrick::Input:0x00007ff04c5c2d78>\",\"sinatra.route\":\"POST /**\",\"body\":\"\"}" to match "\"body\":\"a=1%26b%3D2\"" # ./spec/ethon/easy/http/post_spec.rb:226:in `block (6 levels) in <top (required)>' 7) Ethon::Easy::Http::Post#setup when body when string when requesting sends string Failure/Error: expect(easy.response_body).to include('"body":"{a: 1}"') expected "{\"CONTENT_LENGTH\":\"6\",\"CONTENT_TYPE\":\"application/x-www-form-urlencoded\",\"GATEWAY_INTERFACE...Rackup::Handler::WEBrick::Input:0x00007ff04c22c448>\",\"sinatra.route\":\"POST /**\",\"body\":\"\"}" to include "\"body\":\"{a: 1}\"" # ./spec/ethon/easy/http/post_spec.rb:250:in `block (6 levels) in <top (required)>' 8) Ethon::Easy::Http::Post#setup when body when binary with null bytes when requesting sends binary data Failure/Error: expect(easy.response_body).to include('"body":"\\u0001\\u0000\\u0001"') expected "{\"CONTENT_LENGTH\":\"3\",\"CONTENT_TYPE\":\"application/x-www-form-urlencoded\",\"GATEWAY_INTERFACE...Rackup::Handler::WEBrick::Input:0x00007ff04c364bd0>\",\"sinatra.route\":\"POST /**\",\"body\":\"\"}" to include "\"body\":\"\\u0001\\u0000\\u0001\"" # ./spec/ethon/easy/http/post_spec.rb:270:in `block (6 levels) in <top (required)>' 9) Ethon::Easy::Http::Post#setup when params and body when requesting body contains form Failure/Error: expect(easy.response_body).to include('"body":"a=1"') expected "{\"CONTENT_LENGTH\":\"3\",\"CONTENT_TYPE\":\"application/x-www-form-urlencoded\",\"GATEWAY_INTERFACE...Rackup::Handler::WEBrick::Input:0x00007ff04c0eabc0>\",\"sinatra.route\":\"POST /**\",\"body\":\"\"}" to include "\"body\":\"a=1\"" # ./spec/ethon/easy/http/post_spec.rb:312:in `block (5 levels) in <top (required)>' Lucas