Skip to content

Commit

Permalink
Merge pull request nix-community#107 from sourcespectrum/master
Browse files Browse the repository at this point in the history
Add redirection support
  • Loading branch information
marsam authored Nov 8, 2023
2 parents e9f533a + 6599974 commit 1b7df69
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 17 deletions.
9 changes: 8 additions & 1 deletion lib/bundix/source.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ def sh(*args, &block)
Bundix.sh(*args, &block)
end

def download(file, url)
def download(file, url, limit = 10)
warn "Downloading #{file} from #{url}"
uri = URI(url)

Expand All @@ -28,6 +28,13 @@ def download(file, url)
File.open(file, 'wb+') do |local|
resp.read_body { |chunk| local.write(chunk) }
end
when Net::HTTPRedirection
location = resp['location']
raise "http error: Redirection loop detected" if location == url
raise "http error: Too many redirects" if limit < 1

warn "Redirected to #{location}"
download(file, location, limit - 1)
when Net::HTTPUnauthorized, Net::HTTPForbidden
debrief_access_denied(uri.host)
raise "http error #{resp.code}: #{uri.host}"
Expand Down
75 changes: 59 additions & 16 deletions test/fetcher_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ class Bundix
class FetcherTest < MiniTest::Test
def test_download_with_credentials
with_dir(bundler_credential: 'secret') do |dir|
with_server(returning_content: 'ok') do |port|
with_server do |port|
file = 'some-file'

assert_equal(File.realpath(dir), Bundler.root.to_s)
Expand All @@ -27,7 +27,7 @@ def test_download_with_credentials

def test_download_without_credentials
with_dir(bundler_credential: nil) do |dir|
with_server(returning_content: 'ok') do |port|
with_server do |port|
file = 'some-file'

assert_equal(File.realpath(dir), Bundler.root.to_s)
Expand All @@ -43,6 +43,43 @@ def test_download_without_credentials
end
end
end

def test_handle_redirection_response
with_dir(bundler_credential: nil) do |dir|
build_responses = ->(port) {
[
{
route: "/test/redirection",
returning_content: 'You are being redirected',
returning_status: "302 Found",
returning_headers: ["Location: http://127.0.0.1:#{port}/test"]
},
{
route: "/test",
returning_content: 'ok',
returning_status: "200 OK",
returning_headers: []
}
]
}

with_server(build_responses) do |port|
file = 'some-file'

assert_equal(File.realpath(dir), Bundler.root.to_s)

out, err = capture_io do
Bundix::Fetcher.new.download(file, "http://127.0.0.1:#{port}/test/redirection")
end

assert_equal(File.read(file), 'ok')
assert_empty(out)
assert_match(/^Downloading .* from http.*$/, err)
assert_match(/^Redirected to http.*$/, err)
end
end
end

private

def with_dir(bundler_credential:)
Expand All @@ -61,28 +98,34 @@ def with_dir(bundler_credential:)
end
end

def with_server(returning_content:)
def with_server(build_responses = ->(port) { [{ route: "/test", returning_content: 'ok', returning_status: "200 OK", returning_headers: [] }] })
server = TCPServer.new('127.0.0.1', 0)
port_num = server.addr[1]

@request = ''
responses = build_responses.call(port_num)

Thread.abort_on_exception = true
thr = Thread.new do
conn = server.accept
until (line = conn.readline) == "\r\n"
@request << line
end
responses.length.times.each do
conn = server.accept
@request = ''

conn.write(
"HTTP/1.1 200 OK\r\n" \
"Content-Length: #{returning_content.length}\r\n" \
"Content-Type: text/plain\r\n" \
"\r\n" \
"#{returning_content}",
)
until (line = conn.readline) == "\r\n"
@request << line
end

conn.close
response = responses.find { |r| r[:route] == @request.split(' ')[1] }

conn.write(
"HTTP/1.1 #{response[:returning_status]}\r\n" \
"Content-Length: #{response[:returning_content].length}\r\n" \
"Content-Type: text/plain\r\n" \
"#{response[:returning_headers].map { |h| "#{h}\r\n" }.join("")}" \
"\r\n" \
"#{response[:returning_content]}",
)
conn.close
end
end

yield(port_num)
Expand Down

0 comments on commit 1b7df69

Please sign in to comment.