Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

improvement: include response body on fetch_http error #7148

Conversation

Paul-Bob
Copy link
Contributor

@Paul-Bob Paul-Bob commented Nov 9, 2023

What was the end-user or developer problem that led to this PR?

We would like to show custom error messages on our private rubygems server (https://packager.dev) that serves private Avo gems.

Right now the error message looks like (using local-host for testing purposes):

Bundler::HTTPError: Could not download gem from http://localhost:4567/avo-hq/ due to underlying error <bad response Forbidden 403 (http://localhost:4567/avo-hq/gems/avo-menu-0.1.18.gem)>

It would be helpful to us to make this message more customized so we can inform our users about the reason that download failed.

@adrianthedev opened this issue and @duckinator pointed us in the right direction in this comment.

Here is where we can fully customize the message lib/bundler/rubygems_integration.rb L519 but I noticed that the error that is rescued on that line it's already pre-processed here (remote_fetcher.rb L237) and it passes only the response.message and the response.code.

What is your fix for the problem, implemented in this PR?

With this PR the error message also includes the response's body and looks like:

Bundler::HTTPError: Could not download gem from http://localhost:4567/avo-hq/ due to underlying error <bad response Forbidden 403 Invalid License tier for 'avo-menu'. (http://localhost:4567/avo-hq/gems/avo-menu-0.1.18.gem)>

Notice that the error now includes the response's body Invalid License tier for 'avo-menu'..

Not sure if is the best approach, open for any kind of improvement.

Make sure the following tasks are checked

PS:

Alternative approach

What if we add an attribute on FetchError that will store the original response and we would be able to manipulate it on lib/bundler/rubygems_integration.rb L519 ?

This way the error message can be fully customizable.

Copy link

welcome bot commented Nov 9, 2023

Thanks for opening a pull request and helping make RubyGems and Bundler better! Someone from the RubyGems team will take a look at your pull request shortly and leave any feedback. Please make sure that your pull request has tests for any changes or added functionality.

We use GitHub Actions to test and make sure your change works functionally and uses acceptable conventions, you can review the current progress of GitHub Actions in the PR status window below.

If you have any questions or concerns that you wish to ask, feel free to leave a comment in this PR or join our #rubygems or #bundler channel on Slack.

For more information about contributing to the RubyGems project feel free to review our CONTRIBUTING guide

@adrianthedev
Copy link

@duckinator does this look good?

@duckinator
Copy link
Member

At a glance, this looks good. I'll test it locally when I'm at my computer later today (mainly to see what errors from rubygems.org look like with it), but don't expect any problems. 👍

@adrianthedev
Copy link

Thank you! We appreciate it!
Let us know if we need to update anything else.

@duckinator
Copy link
Member

The test failures don't seem to be related to this PR; I asked the other maintainers if they know what's up. I'll get back to you when I have more info. 🙂

@duckinator
Copy link
Member

duckinator commented Nov 14, 2023

Looks like that issue is resolved by #7156. Merging master back into this branch to get the latest changes. CI should in theory pass now.

@duckinator duckinator merged commit e5a4fd9 into rubygems:master Nov 14, 2023
60 checks passed
@duckinator
Copy link
Member

Thanks for the PR, @Paul-Bob!

@@ -234,7 +234,7 @@ def fetch_http(uri, last_modified = nil, head = false, depth = 0)

fetch_http(location, last_modified, head, depth + 1)
else
raise FetchError.new("bad response #{response.message} #{response.code}", uri)
raise FetchError.new("bad response #{response.message} #{response.code} #{response.body.strip}", uri)
Copy link
Member

Choose a reason for hiding this comment

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

This can be suuuuuuuuuuuuper messy IMHO when remote provides like 404 HTML page. Would it make sense to limit this to first X characters at least or scan for friendly response and report back only when recognized format is returned? What's returned by RubyGems.org in here?

Copy link
Member

Choose a reason for hiding this comment

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

Referencing a gem that doesn't exist doesn't result in this message being displayed.

I'm not opposed to adding a character limit, though.

puppy@orthrus:~/test$ ls -a
./       ../      Gemfile
puppy@orthrus:~/test$ cat Gemfile
source 'https://rubygems.org'

gem 'asdfasdfsadfihgjklsadkjfhakljfhsaf-this-gem-does-not-exist'
puppy@orthrus:~/test$ bundle install
Fetching gem metadata from https://rubygems.org/.
Could not find gem 'asdfasdfsadfihgjklsadkjfhakljfhsaf-this-gem-does-not-exist' in rubygems repository
https://rubygems.org/ or installed locally.
puppy@orthrus:~/test$ 

Copy link
Member

Choose a reason for hiding this comment

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

There are other gem servers which can return super long 500 HTML page for example. I would suggest to revert this and instead build some kind of "protocol" to let the error message propagate to client. IMHO it is not good idea to propagate licensing error back to clients using HTTP message on gem install. There is no guarantee how RubyGems handles HTTP errors and IMHO it should not be mis-used to handing over messages to client.

Copy link
Member

Choose a reason for hiding this comment

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

I would be happy to keep this output, but only in kind of "verbose" mode and that is most likely against the original need of @adrianthedev.

Copy link
Member

Choose a reason for hiding this comment

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

We have also sometimes needed this in Bundler, for example when rate-limiting certain requests. I like the idea of this being officially supported, but I agree that an unlimited message size is messy and unhelpful.

Copy link
Member

Choose a reason for hiding this comment

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

Oh, sorry, I misunderstood! I thought you were saying only responses not 4xx or 5xx. 🙃 Sounds good to me.

Copy link
Member

Choose a reason for hiding this comment

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

@adrianthedev would that work for you? ^ Are you in control of returned HTTP headers for 403 on your gemserver?

Choose a reason for hiding this comment

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

Yes @simi, we are in control of the returned HTTP headers. Our gem server is operated by a sinatra app.

Not completely sure how to send the message.
Is it something like this?

halt 403, {'Content-Type' => 'application/vnd.rubygems.text'}, { message: 'some text' }.to_json

Our message is something like this. That's 164 characters. We might play around with it so the number of chars might increase.

It seems that you don't have a valid GEM_SERVER_TOKEN for Avo (https://bundler.dev/). Please read this for more information
https://docs.avohq.io/3.0/some-path-here

Copy link
Member

Choose a reason for hiding this comment

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

Did I understand correctly that we'd rather revert this PR and go with the cleaner solution that @simi proposed?

Copy link
Member

Choose a reason for hiding this comment

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

Yes, if possible, don't release this. 🙏

@adrianthedev
Copy link

Thanks for the help!
This be available in newer versions of bundler, right?

deivid-rodriguez added a commit that referenced this pull request Dec 7, 2023
…sponse_body_on_fetch_http_error"

This reverts commit e5a4fd9, reversing
changes made to c5a5363.
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.

None yet

6 participants