downloads: refactor Downloads::File into Danbooru::Http.
Remove the Downloads::File class. Move download methods to Danbooru::Http instead. This means that: * HTTParty has been replaced with http.rb for downloading files. * Downloading is no longer tightly coupled to source strategies. Before Downloads::File tried to automatically look up the source and download the full size image instead if we gave it a sample url. Now we can do plain downloads without source strategies altering the url. * The Cloudflare Polish check has been changed from checking for a Cloudflare IP to checking for the CF-Polished header. Looking up the list of Cloudflare IPs was slow and flaky during testing. * The SSRF protection code has been factored out so it can be used for normal http requests, not just for downloads. * The Webmock gem can be removed, since it was only used for stubbing out certain HTTParty requests in the download tests. The Webmock gem is buggy and caused certain tests to fail during CI. * The retriable gem can be removed, since we no longer autoretry failed downloads. We assume that if a download fails once then retrying probably won't help.
This commit is contained in:
@@ -3,53 +3,27 @@ require 'test_helper'
|
||||
module Downloads
|
||||
class ArtStationTest < ActiveSupport::TestCase
|
||||
context "a download for a (small) artstation image" do
|
||||
setup do
|
||||
@asset = "https://cdnb3.artstation.com/p/assets/images/images/003/716/071/small/aoi-ogata-hate-city.jpg?1476754974"
|
||||
@download = Downloads::File.new(@asset)
|
||||
end
|
||||
|
||||
should "download the /4k/ image instead" do
|
||||
file, strategy = @download.download!
|
||||
assert_equal(1_880_910, ::File.size(file.path))
|
||||
assert_downloaded(1_880_910, "https://cdnb3.artstation.com/p/assets/images/images/003/716/071/small/aoi-ogata-hate-city.jpg?1476754974")
|
||||
end
|
||||
end
|
||||
|
||||
context "for an image where an original does not exist" do
|
||||
setup do
|
||||
@asset = "https://cdna.artstation.com/p/assets/images/images/004/730/278/large/mendel-oh-dragonll.jpg"
|
||||
@download = Downloads::File.new(@asset)
|
||||
end
|
||||
|
||||
should "not try to download the original" do
|
||||
file, strategy = @download.download!
|
||||
assert_equal(483_192, ::File.size(file.path))
|
||||
assert_downloaded(483_192, "https://cdna.artstation.com/p/assets/images/images/004/730/278/large/mendel-oh-dragonll.jpg")
|
||||
end
|
||||
end
|
||||
|
||||
context "a download for an ArtStation image hosted on CloudFlare" do
|
||||
setup do
|
||||
@asset = "https://cdnb.artstation.com/p/assets/images/images/003/716/071/large/aoi-ogata-hate-city.jpg?1476754974"
|
||||
end
|
||||
|
||||
should "return the original file, not the polished file" do
|
||||
@asset = "https://cdnb.artstation.com/p/assets/images/images/003/716/071/large/aoi-ogata-hate-city.jpg?1476754974"
|
||||
assert_downloaded(1_880_910, @asset)
|
||||
end
|
||||
|
||||
should "return the original filesize, not the polished filesize" do
|
||||
assert_equal(1_880_910, Downloads::File.new(@asset).size)
|
||||
end
|
||||
end
|
||||
|
||||
context "a download for a https://$artist.artstation.com/projects/$id page" do
|
||||
setup do
|
||||
@source = "https://dantewontdie.artstation.com/projects/YZK5q"
|
||||
@download = Downloads::File.new(@source)
|
||||
end
|
||||
|
||||
should "download the original image instead" do
|
||||
file, strategy = @download.download!
|
||||
|
||||
assert_equal(247_350, ::File.size(file.path))
|
||||
assert_downloaded(247_350, "https://dantewontdie.artstation.com/projects/YZK5q")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,81 +0,0 @@
|
||||
require 'test_helper'
|
||||
|
||||
module Downloads
|
||||
class FileTest < ActiveSupport::TestCase
|
||||
context "A post download" do
|
||||
setup do
|
||||
@source = "http://www.google.com/intl/en_ALL/images/logo.gif"
|
||||
@download = Downloads::File.new(@source)
|
||||
end
|
||||
|
||||
context "for a banned IP" do
|
||||
setup do
|
||||
Resolv.expects(:getaddress).returns("127.0.0.1").at_least_once
|
||||
end
|
||||
|
||||
should "not try to download the file" do
|
||||
assert_raise(Downloads::File::Error) { Downloads::File.new("http://evil.com").download! }
|
||||
end
|
||||
|
||||
should "not try to fetch the size" do
|
||||
assert_raise(Downloads::File::Error) { Downloads::File.new("http://evil.com").size }
|
||||
end
|
||||
|
||||
should "not follow redirects to banned IPs" do
|
||||
url = "http://httpbin.org/redirect-to?url=http://127.0.0.1"
|
||||
stub_request(:get, url).to_return(status: 301, headers: { "Location": "http://127.0.0.1" })
|
||||
|
||||
assert_raise(Downloads::File::Error) { Downloads::File.new(url).download! }
|
||||
end
|
||||
|
||||
should "not follow redirects that resolve to a banned IP" do
|
||||
url = "http://httpbin.org/redirect-to?url=http://127.0.0.1.nip.io"
|
||||
stub_request(:get, url).to_return(status: 301, headers: { "Location": "http://127.0.0.1.xip.io" })
|
||||
|
||||
assert_raise(Downloads::File::Error) { Downloads::File.new(url).download! }
|
||||
end
|
||||
end
|
||||
|
||||
context "that fails" do
|
||||
should "retry three times before giving up" do
|
||||
HTTParty.expects(:get).times(3).raises(Errno::ETIMEDOUT)
|
||||
assert_raises(Errno::ETIMEDOUT) { @download.download! }
|
||||
end
|
||||
|
||||
should "return an uncorrupted file on the second try" do
|
||||
bomb = stub("bomb")
|
||||
bomb.stubs(:code).raises(IOError)
|
||||
resp = stub("resp", success?: true)
|
||||
|
||||
chunk = stub("a")
|
||||
chunk.stubs(:code).returns(200)
|
||||
chunk.stubs(:size).returns(1)
|
||||
chunk.stubs(:to_s).returns("a")
|
||||
|
||||
HTTParty.expects(:get).twice.multiple_yields(chunk, bomb).then.multiple_yields(chunk, chunk).returns(resp)
|
||||
@download.stubs(:is_cloudflare?).returns(false)
|
||||
tempfile, _strategy = @download.download!
|
||||
|
||||
assert_equal("aa", tempfile.read)
|
||||
end
|
||||
end
|
||||
|
||||
should "throw an exception when the file is larger than the maximum" do
|
||||
assert_raise(Downloads::File::Error) do
|
||||
@download.download!(max_size: 1)
|
||||
end
|
||||
end
|
||||
|
||||
should "store the file in the tempfile path" do
|
||||
tempfile, strategy = @download.download!
|
||||
assert_operator(tempfile.size, :>, 0, "should have data")
|
||||
end
|
||||
|
||||
should "correctly save the file when following 302 redirects" do
|
||||
download = Downloads::File.new("https://yande.re/post/show/578014")
|
||||
file, strategy = download.download!(url: download.preview_url)
|
||||
assert_equal(19134, file.size)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -136,18 +136,14 @@ module Downloads
|
||||
end
|
||||
|
||||
context "An ugoira site for pixiv" do
|
||||
setup do
|
||||
@download = Downloads::File.new("http://www.pixiv.net/member_illust.php?mode=medium&illust_id=62247364")
|
||||
@tempfile, strategy = @download.download!
|
||||
@tempfile.close!
|
||||
end
|
||||
|
||||
should "capture the data" do
|
||||
assert_equal(2, @download.data[:ugoira_frame_data].size)
|
||||
if @download.data[:ugoira_frame_data][0]["file"]
|
||||
@strategy = Sources::Strategies.find("http://www.pixiv.net/member_illust.php?mode=medium&illust_id=62247364")
|
||||
|
||||
assert_equal(2, @strategy.data[:ugoira_frame_data].size)
|
||||
if @strategy.data[:ugoira_frame_data][0]["file"]
|
||||
assert_equal([{"file" => "000000.jpg", "delay" => 125}, {"file" => "000001.jpg", "delay" => 125}], @download.data[:ugoira_frame_data])
|
||||
else
|
||||
assert_equal([{"delay_msec" => 125}, {"delay_msec" => 125}], @download.data[:ugoira_frame_data])
|
||||
assert_equal([{"delay_msec" => 125}, {"delay_msec" => 125}], @strategy.data[:ugoira_frame_data])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user