janko/down

A breakdown of the popular remote file opener

Down is a popular library that is self-described as “a utility tool for streaming, flexible and safe downloading of remote files”. I have personally used it in several applications and love the simple interface, robust errors, and HTTP library choice selection. The library does one thing and does it very well. It is memory efficient and cleans up after itself.

Documentation

The documentation for the gem is very detailed and thoroughly explains how to configure and use the library. It goes in depth with examples of several of the different backends (HTTP libraries) and the various options such as max file size and authentication.

Backends

Down uses backends to select which HTTP library is used to make the requests. It supports NetHttp, http, httpx, and wget out of the box. You can implement your own backend as long as it implements the download and open class methods.

Getter/Setter Method

Something that is a bit of a common pattern but I am not a fan of is how you set the backend. Down.backend is both the getter and the setter method for the backend. Passing a value sets the backend while calling it without a value returns the current value stored in @backend. In my opinion it would be much more intuitive to have a backend= method to set the backend while leaving backend to retrieve the value.

backend getter/setter

Dependencies

I really like that the library only has a single dependency of addressable. You must manually install the gem for the given backend that you wish to use, for example http. The backend and thus the gem are dynamically required at runtime as pictured below.

Dynamic require

In the example of http it requires down/http which in turn requires http loading only the libraries needed into memory.

down/http

Facade

The library has a simple facade and only implements 3 methods, download, open, and backend. The download and open methods in turn call a class method with the same name on the backend.

All of the included backends inherit from Down::Backend which implements download and open. The methods simply initialize an instance of the backend and call the corresponding method once again. It’s download and open all the way down.

Tempfiles

The library download the remote file to a Tempfile locally. It extends the Tempfile instance with some methods to expose things like the content_type, original_filename, and charset. I think that is a handy addition to have when working with remote files as you often find yourself needing to know these attributes.

Tempfile additions

When Down downloads a file to a Tempfile it ensures that it cleans up after itself by rescuing all exceptions, closing the tempfile and then re-raising the exception for the application to handle as it sees fit. That simple addition goes a long way to ensure you do not accidentally blow up your file system.

Tempfile clean up

Exceptions

Probably one of my favorite parts of working with the library is that the exceptions are robust and informative. The gem attempts to raise a semantic error when possible. This allows you as the developer to rescue the exceptions you may expect or when you would want to retry the request such as a timeout.

Response Errors

Request Errors

TL;DR

Down is a great gem for downloading or streaming remote files. It does one thing and does it well. The gem has a simple, yet powerful, interface that can be used with a variety of HTTP libraries. The exceptions make debugging a breeze as they are semantic and intuitive. If you find yourself needing to download or stream remote files I encourage you to reach for Down.

Until next week!