Skip to content

Fix: Handle relative URLs in HTTP redirects#448

Open
langtind wants to merge 1 commit intoDragonBox:masterfrom
langtind:fix/handle-relative-redirects
Open

Fix: Handle relative URLs in HTTP redirects#448
langtind wants to merge 1 commit intoDragonBox:masterfrom
langtind:fix/handle-relative-redirects

Conversation

@langtind
Copy link
Contributor

Fixes #442

Pull Request Checklist

  • My pull request has been rebased on master
  • I ran bundle exec rspec to make sure that my PR didn't break any test
  • I ran bundle exec rubocop to make sure that my PR is inline with our code style
  • I have read the code of conduct

Pull Request Description

This PR fixes issue #442 where u3d available fails with "Failed to open TCP connection to :80 (Connection refused - connect(2) for nil port 80)".

Problem:
When following HTTP redirects, relative URLs (e.g., /new-path) were not being converted to absolute URLs. This caused URI(url) to parse the relative URL, resulting in uri.host being nil, which led to Net::HTTP.start failing with a connection error.

Solution:
Added logic in Utils.follow_redirects to detect relative redirect URLs and convert them to absolute URLs using the current URI as the base before following the redirect.

Changes:

  • Modified lib/u3d/utils.rb to handle relative URLs in HTTP redirects
  • Added test in spec/u3d/utils_spec.rb to verify relative URL handling

Testing:

  • All existing tests pass (286 examples, 0 failures)
  • Rubocop shows no offenses
  • New test validates that relative redirects are correctly converted to absolute URLs
  • Manually tested u3d available command which now works correctly

@langtind langtind force-pushed the fix/handle-relative-redirects branch from 1969b70 to c57a52a Compare September 29, 2025 21:18
Copy link
Member

@niezbop niezbop left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me! Thanks @langtind for submitting this fix! I've left a small comment which touches on the specificities of how URI#+ works, nothing mandatory.

follow_redirects(response['location'], redirect_limit: redirect_limit - 1, http_method: http_method, request_headers: request_headers, &block)
location = response['location']
# Handle relative URLs in redirects
location = (uri + location).to_s if location && !location.start_with?('http://', 'https://')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One alternative there would be to go less string-oriented and more URI-oriented by parsing the response['location'] as a URI and then call location.relative?.

I was also wondering about what was happening when adding onto a URI when a path is already present (http://foo.org/bat), and it would seem that URI#+ gets rid of the existing path when adding a relative path. Sort of weird, but TIL.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

u3d available fails with Failed to open TCP connection to :80

2 participants