From fbab273c815a16de266f6391e24d52497d21d5d1 Mon Sep 17 00:00:00 2001 From: evazion Date: Mon, 21 Feb 2022 17:47:06 -0600 Subject: [PATCH] Upgrade http.rb gem to 5.0.4. Fixes a bug where the Foundation source strategy failed because http.rb automatically sent a `Content-Length: 0` header with all GET requests, which caused Foundation to return a 400 Bad Request error. This behavior was fixed in http.rb 5.x. http.rb 5.x has a breaking change where it now includes the request object inside the response object, which we have to handle in a few places. --- Gemfile | 2 +- Gemfile.lock | 13 +++++++------ app/logical/danbooru/http.rb | 2 +- app/logical/danbooru/http/cache.rb | 3 +++ test/test_helpers/iqdb_test_helper.rb | 2 +- test/test_helpers/reportbooru_helper.rb | 2 +- test/unit/danbooru_http_test.rb | 14 +++++++------- test/unit/reportbooru_service_test.rb | 4 ++-- 8 files changed, 23 insertions(+), 19 deletions(-) diff --git a/Gemfile b/Gemfile index fa7972140..07fd358e1 100644 --- a/Gemfile +++ b/Gemfile @@ -30,7 +30,7 @@ gem 'builder' gem 'puma' gem 'scenic' gem 'ipaddress_2' -gem 'http', "~> 4.4.1" +gem 'http' gem 'activerecord-hierarchical_query', git: "https://github.com/danbooru/activerecord-hierarchical_query" gem 'http-cookie', git: "https://github.com/danbooru/http-cookie" gem 'pundit' diff --git a/Gemfile.lock b/Gemfile.lock index 15c45e070..5362fe340 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -266,14 +266,12 @@ GEM heapy (0.2.0) thor hsluv (1.0.1) - http (4.4.1) - addressable (~> 2.3) + http (5.0.4) + addressable (~> 2.8) http-cookie (~> 1.0) http-form_data (~> 2.2) - http-parser (~> 1.2.0) + llhttp-ffi (~> 0.4.0) http-form_data (2.3.0) - http-parser (1.2.3) - ffi-compiler (>= 1.0, < 2.0) httpclient (2.8.3) i18n (1.9.1) concurrent-ruby (~> 1.0) @@ -290,6 +288,9 @@ GEM listen (3.7.1) rb-fsevent (~> 0.10, >= 0.10.3) rb-inotify (~> 0.9, >= 0.9.10) + llhttp-ffi (0.4.0) + ffi-compiler (~> 1.0) + rake (~> 13.0) loofah (2.14.0) crass (~> 1.0.2) nokogiri (>= 1.5.9) @@ -568,7 +569,7 @@ DEPENDENCIES google-cloud-bigquery google-cloud-storage hsluv - http (~> 4.4.1) + http http-cookie! ipaddress_2 listen diff --git a/app/logical/danbooru/http.rb b/app/logical/danbooru/http.rb index c327c9c74..d03858f3c 100644 --- a/app/logical/danbooru/http.rb +++ b/app/logical/danbooru/http.rb @@ -206,7 +206,7 @@ module Danbooru end def fake_response(status) - ::HTTP::Response.new(status: status, version: "1.1", body: "") + ::HTTP::Response.new(status: status, version: "1.1", body: "", request: nil) end end end diff --git a/app/logical/danbooru/http/cache.rb b/app/logical/danbooru/http/cache.rb index 38b4e4f18..9eea01a3b 100644 --- a/app/logical/danbooru/http/cache.rb +++ b/app/logical/danbooru/http/cache.rb @@ -19,6 +19,9 @@ module Danbooru response.flush response.body.instance_variable_set(:@connection, nil) response.body.instance_variable_set(:@stream, nil) + response.instance_exec { @request = request.dup } + response.request.instance_exec { @uri_normalizer = nil } + response.request.body.instance_exec { @source = nil } response end diff --git a/test/test_helpers/iqdb_test_helper.rb b/test/test_helpers/iqdb_test_helper.rb index 69179553e..cebed66c4 100644 --- a/test/test_helpers/iqdb_test_helper.rb +++ b/test/test_helpers/iqdb_test_helper.rb @@ -1,7 +1,7 @@ module IqdbTestHelper def mock_iqdb_matches(matches) Danbooru.config.stubs(:iqdb_url).returns("http://localhost:5588") - response = HTTP::Response.new(status: 200, body: matches.to_json, headers: { "Content-Type": "application/json" }, version: "1.1") + response = HTTP::Response.new(status: 200, body: matches.to_json, headers: { "Content-Type": "application/json" }, version: "1.1", request: nil) HTTP::Client.any_instance.stubs(:post).returns(response) end end diff --git a/test/test_helpers/reportbooru_helper.rb b/test/test_helpers/reportbooru_helper.rb index 3ec926202..3970f9c55 100644 --- a/test/test_helpers/reportbooru_helper.rb +++ b/test/test_helpers/reportbooru_helper.rb @@ -1,6 +1,6 @@ module ReportbooruHelper def mock_request(url, method: :get, status: 200, body: nil, http: Danbooru::Http.any_instance, **options) - response = HTTP::Response.new(status: status, body: body, version: "1.1") + response = HTTP::Response.new(status: status, body: body, version: "1.1", request: nil) http.stubs(method).with(url, **options).returns(response) end diff --git a/test/unit/danbooru_http_test.rb b/test/unit/danbooru_http_test.rb index 29e7fb509..1502aad23 100644 --- a/test/unit/danbooru_http_test.rb +++ b/test/unit/danbooru_http_test.rb @@ -123,8 +123,8 @@ class DanbooruHttpTest < ActiveSupport::TestCase context "retriable feature" do should "retry immediately if no Retry-After header is sent" do - response_429 = ::HTTP::Response.new(status: 429, version: "1.1", body: "") - response_200 = ::HTTP::Response.new(status: 200, version: "1.1", body: "") + response_429 = ::HTTP::Response.new(status: 429, version: "1.1", body: "", request: nil) + response_200 = ::HTTP::Response.new(status: 200, version: "1.1", body: "", request: nil) HTTP::Client.any_instance.expects(:perform).times(2).returns(response_429, response_200) response = Danbooru::Http.use(:retriable).get(httpbin_url("status/429")) @@ -132,8 +132,8 @@ class DanbooruHttpTest < ActiveSupport::TestCase end should "retry if the Retry-After header is an integer" do - response_503 = ::HTTP::Response.new(status: 503, version: "1.1", headers: { "Retry-After": "1" }, body: "") - response_200 = ::HTTP::Response.new(status: 200, version: "1.1", body: "") + response_503 = ::HTTP::Response.new(status: 503, version: "1.1", headers: { "Retry-After": "1" }, body: "", request: nil) + response_200 = ::HTTP::Response.new(status: 200, version: "1.1", body: "", request: nil) HTTP::Client.any_instance.expects(:perform).times(2).returns(response_503, response_200) response = Danbooru::Http.use(:retriable).get(httpbin_url("status/503")) @@ -141,8 +141,8 @@ class DanbooruHttpTest < ActiveSupport::TestCase end should "retry if the Retry-After header is a date" do - response_503 = ::HTTP::Response.new(status: 503, version: "1.1", headers: { "Retry-After": 2.seconds.from_now.httpdate }, body: "") - response_200 = ::HTTP::Response.new(status: 200, version: "1.1", body: "") + response_503 = ::HTTP::Response.new(status: 503, version: "1.1", headers: { "Retry-After": 2.seconds.from_now.httpdate }, body: "", request: nil) + response_200 = ::HTTP::Response.new(status: 200, version: "1.1", body: "", request: nil) HTTP::Client.any_instance.expects(:perform).times(2).returns(response_503, response_200) response = Danbooru::Http.use(:retriable).get(httpbin_url("status/503")) @@ -166,7 +166,7 @@ class DanbooruHttpTest < ActiveSupport::TestCase url = "https://cdnb.artstation.com/p/assets/images/images/025/273/307/4k/atey-ghailan-a-sage-keyart-s-ch-04-outlined-1.jpg?1585246642" response = Danbooru::Http.use(:unpolish_cloudflare).get(url) - assert_equal(200, response.status) + assert_equal(200, response.status.to_i) assert_equal(622_784, response.content_length) end end diff --git a/test/unit/reportbooru_service_test.rb b/test/unit/reportbooru_service_test.rb index d31e340f6..3541441e3 100644 --- a/test/unit/reportbooru_service_test.rb +++ b/test/unit/reportbooru_service_test.rb @@ -16,8 +16,8 @@ class ReportbooruServiceTest < ActiveSupport::TestCase end should "return nothing on failure" do - Danbooru::Http.any_instance.expects(:get).with("http://localhost:1234/post_views/rank?date=#{@date}").returns(HTTP::Response.new(status: 500, body: "", version: "1.1")) - Danbooru::Http.any_instance.expects(:get).with("http://localhost:1234/post_views/rank?date=#{@date.yesterday}").returns(HTTP::Response.new(status: 500, body: "", version: "1.1")) + Danbooru::Http.any_instance.expects(:get).with("http://localhost:1234/post_views/rank?date=#{@date}").returns(HTTP::Response.new(status: 500, body: "", version: "1.1", request: nil)) + Danbooru::Http.any_instance.expects(:get).with("http://localhost:1234/post_views/rank?date=#{@date.yesterday}").returns(HTTP::Response.new(status: 500, body: "", version: "1.1", request: nil)) assert_equal([], @service.popular_posts(@date)) end