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

Use Net:HTTP instead of Typhoeus #26

Merged
merged 10 commits into from
May 14, 2018
Merged

Use Net:HTTP instead of Typhoeus #26

merged 10 commits into from
May 14, 2018

Conversation

benbalter
Copy link
Owner

@benbalter benbalter commented May 7, 2018

This PR moves the project to use OpenURI Net:HTTP to download themes, rather than Typhoeus. Typhoeus is a wrapper for Libcurl, which has Windows compatibility issues (#9, #18). OpenURI Net:HTTP is native Ruby, and thus shouldn't suffer from the same problems.

This implementation is largely based on https://twin.github.io/improving-open-uri/ and to a lesser extent https://gist.github.com/janko-m/7cd94b8b4dd113c2c193. I looked at using @janko-m's Down which would provide a nice abstraction layer, but didn't want to add a dependency on a project with only 3 contributors (although it looks to be a great project).

For the most part, this approach appears to be a drop-in replacement, with tests passing with only minor modifications.

@parkr would you be able to review this?

Copy link

@parkr parkr left a comment

Choose a reason for hiding this comment

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

Looking wonderful to me so far!

request.run
io = URI(zip_url).open(OPTIONS)
IO.copy_stream io, zip_file
OpenURI::Meta.init zip_file, io
Copy link

Choose a reason for hiding this comment

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

Hm, I couldn't find this method in Dash from the ruby stdlib, and rubydoc.info didn't have any docs for the method I did find. What does this do?

Copy link
Owner Author

Choose a reason for hiding this comment

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

@benbalter
Copy link
Owner Author

benbalter commented May 7, 2018

@ptoomey3, @mastahyeti I know open uri has a bad history, in terms of security. Wondering if you have a minute to share any thoughts one way or the other with using it in a Jekyll plugin?

We build the URL ourselves, normalize it with Addressable::URI, and sanitize the repository name + owner with /a-z0-9\._-/, which is the only user-supplied input.

Edit: Also to note we're calling uri.open rather than open(uri).

@btoews
Copy link

btoews commented May 7, 2018

It seems like it would be better to just use a purpose built HTTP client than to use something with a bunch of "extra features". If you're concerned with platform compatibility issues, you could maybe use Faraday, which would allow you to select different adapters based on the platform.

@benbalter
Copy link
Owner Author

@mastahyeti thanks for the 👀, as always.

Given that we're making a single, predictable call to download a (potentially large) file to a known location, I was able to implement everything using native Net:HTTP streaming, using about the same lines of code it took to implement Typhous and open URI.

@parkr mind taking another look? (tests are passing).

@benbalter benbalter changed the title Use OpenURI instead of Typhoeus Use Net:HTTP instead of Typhoeus May 9, 2018
Copy link

@parkr parkr left a comment

Choose a reason for hiding this comment

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

This is brilliant work!


def raise_unless_sucess(response)
return if response.is_a?(Net::HTTPSuccess)
raise DownloadError, "#{response.code} - #{response.message}"
Copy link

Choose a reason for hiding this comment

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

Would it be helpful to include the URL that failed to return a helpful response?

Copy link
Owner Author

Choose a reason for hiding this comment

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

It would theoretically be in the log output immediately above.

:verbose => (Jekyll.logger.level == :debug),
}.freeze
USER_AGENT = "Jekyll Remote Theme/#{VERSION} (+#{PROJECT_URL})".freeze
MAX_FILE_SIZE = 1 * (1024 * 1024 * 1024) # Size in bytes (1 GB)
Copy link

Choose a reason for hiding this comment

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

Do you have any thoughts on whether this should be configurable? Maybe my host’s disks aren’t quite so large?

Copy link
Owner Author

Choose a reason for hiding this comment

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

Assume you're talking about the max file size? I put it in largely as a guard against abuse. Not sure how a malicious user might create a never-ending zip since we control the source server, but figured it'd be better to be safe than sorry.

Net::HTTP.start(zip_url.host, zip_url.port, :use_ssl => true) do |http|
http.request(request) do |response|
raise_unless_sucess(response)
enforce_max_file_size(response.content_length)
Copy link

Choose a reason for hiding this comment

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

The Content-Length header won't be set for chunked responses, right? Seems like you may also want to enforce your size limits by summing up chunk sizes.

Copy link
Owner Author

Choose a reason for hiding this comment

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

I looked into this and there is not a clean way to do this with our clean implementation. We don't have any limit on master, so what's currently implemented should be some protection, and we can look into adding better chunk support, if necessary, in a subsequent pass.

@benbalter benbalter merged commit 0f22991 into master May 14, 2018
@benbalter benbalter deleted the open-uri branch May 14, 2018 14:05
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.

3 participants