A blueprint for creating an imgix library in any language.
This document is meant to serve as a resource for implementing native libraries for use with the imgix URL API. Almost all libraries in their individual languages have a set of similar concerns: the library must be able to build imgix URLs, secure imgix URLs, and handle the corner cases that result.
This document will not cover framework-level integrations in different languages. This document is primarily concerned with building imgix API URLs reliably.
imgix cares very much about providing first-class, idiomatic support for as many languages as possible. If you create a library for a language that is not supported, please get in touch if you would like it to be supported officially.
Official libraries exist in the following languages:
Unofficial libraries are available in the following languages:
If you have an imgix library that you would like included here, please open a Pull Request.
There is a complete list of libraries (including framework-specific libraries) in the imgix documentation.
If it is idiomatic for the language, we recommend naming each library "imgix-" + language_name
, e.g. imgix-rb
or imgix-php
.
All imgix libraries must follow Semantic Versioning.
The simplest transformation for a library should be able map a path to an imgix source.
Given the origin path:
/users/1.png
A given imgix library should be able to turn that into:
https://my-social-network.imgix.net/users/1.png
imgix recommends using the HTTP over TLS (https:) in all cases. All imgix sources are HTTPS-enabled.
Given recommendations by Paul Irish and Ilya Grigorik, please do not use HTTP or protocol-relative URLs.
See:
- The Protocol-relative URL, Paul Irish
- Is TLS Fast Yet?, Ilya Grigorik
Web Proxy Sources are very powerful parts of the imgix URL API. While Amazon S3 and Web Folder sources all assume the same origin, Web Proxy Sources are able to proxy any publicly-accessible URL. Because of this, imgix requires that all Web Proxy URLs be signed.
This is also a point that can trip many library authors up. The URL-to-be-proxied is the path component of an imgix URL. While
https://my-social-network.imgix.net/http://avatars.com/john-smith.png # Don't do this
will work with imgix, imgix recommends that you do not merely append the origin URL like this. This method will begin causing issues if and when the origin URL has query parameters of its own.
Thus, imgix recommends URI-encoding the URL-to-be-proxied like so:
https://my-social-network.imgix.net/http%3A%2F%2Favatars.com%2Fjohn-smith.png
Note: Web Proxy URLs will also need to be signed. Please see the Securing URLs section below.
The imgix URL API is a powerful way to manipulate images. The primary method of doing this is the extensive set of URL parameters. These URL parameters are able to change the size, crop, file format, and much more.
These URL parameters should be appended to valid imgix URLs. For example, let's say we wanted to resize an image to be 400 pixels wide and 300 pixels tall, given this URL:
https://my-social-network.imgix.net/users/1.png
The library should then generate:
https://my-social-network.imgix.net/users/1.png?w=400&h=300
All parameters and their values should be URI encoded before generating the output URL. This helps avoid encoding errors, as well as potential XSS vulnerabilities when dealing with user-generated content. If the library is passed an image URL of users/1.png
and a parameter of hello world
with a value of this/seems… pretty sketchy! 😁
, it should generate the following url:
https://my-social-network.imgix.net/users/1.png?hello%20world=this%2Fseems%E2%80%A6%20pretty%20sketchy!%20%F0%9F%98%81
If the library is passed any parameter ending in 64
, it should automatically encode that parameter's value as an RFC4648 "base64url" string as described in the base64url encode problematic parameters section of this document. For example, the same user image as above with the txt64
parameter and value this/seems… pretty sketchy! 😁
should result in the following URL:
https://my-social-network.imgix.net/users/1.png?txt64=dGhpcy9zZWVtc-KApiBwcmV0dHkgc2tldGNoeSEg8J-YgQ
If working in JavaScript, it's important to note that the built-in atob
and btoa
methods are not URL safe, and only support Latin-1 characters. Because of these limitations, it may be useful to use a third-party tool for encoding and decoding Base64 in JavaScript, such as js-base64's Base64.encodeURI
method.
All parameters and values passed to the library must be unencoded.
imgix recommends securing all URLs, although it is not required for Amazon S3 and Web Folder Sources. Securing URLs prevents others from using one of your Sources maliciously, say to use your imgix Source as a CDN for a separate site.
imgix URL signatures are represented by the special s
parameter. The value is an MD5 hash of the data pertaining to the URL itself and the imgix Source.
- The hash value must be in lowercase hex.
- MD5 hashes represented in hex must be exactly 32 characters ... no more and no less.
- In a secured imgix URL, the
s
parameter must be the last parameter.
This parameter is generated as follows in Ruby:
signature_base = token + path
signature_base += query if !query.nil?
Digest::MD5.hexdigest(signature_base)
Here are the following definitions of each variable in the above example:
token
: The alphanumeric Secure URL Token pertaining to the specific Source. It can be found in the imgix web dashboard.path
: The path of component of the final imgix URL including the leading slash, e.g./users/1.png
or/http%3A%2F%2Favatars.com%2Fjohn-smith.png
. Special characters in the path (for example UTF-8 encoded codepoints) must remain percent encoded.query
: The query string of the imgix URL parameters, leading with the?
, e.g.?w=400&h=300
. If there are no query parameters, this should be left out of the signature base.
When dealing with complex inputs, encoding can be difficult to properly implement. To help with this, almost every parameter in imgix has a Base64 alias, which allows the values to be encoded using the "base64url" encoding with a URL and filename safe alphabet (RFC 4648). These parameters are keyed by appending 64
to the end of the parameter name. Thus txt
becomes txt64
.
Please note that, per RFC 4648, "base64" and "base64url" encodings are not interchangeable. Many libraries only implement "base64" encoding. Encoding parameter values using "base64" encoding WILL cause your requests to fail ... be sure you check for and know the difference!
When writing libraries, the output of any value passed to a parameter ending in 64
must be "base64url" encoded, with any padding characters (equals signs and newlines [=
, \n
]) removed.
Here’s an example:
?txt=Hello,+World!
is the same as
?txt64=SGVsbG8sIFdvcmxkIQ
Both of these will overlay "Hello, World!" onto an image using the imgix txt
parameter.
Let's see how that works in Ruby:
client = Imgix::Client.new(host: 'static.imgix.net')
client.path('base.png').to_url(mark64: 'https://assets.imgix.net/logo.png')
# => "https://static.imgix.net/base.png?mark64=aHR0cHM6Ly9hc3NldHMuaW1naXgubmV0L2xvZ28ucG5n"
This pattern helps ensure that the users of your libraries never encounter encoding issues while generating imgix URLs.
When consuming a library, imgix recommends always using the Base64 variant of the following parameters:
The following are a few examples for securing URLs, which library authors should use as a spot check:
Given:
- Path:
/users/1.png
- Secure URL Token:
FOO123bar
- No imgix parameters
The resulting signature should be:
6797c24146142d5b40bde3141fd3600c
This makes the final URL:
https://my-social-network.imgix.net/users/1.png?s=6797c24146142d5b40bde3141fd3600c
Given:
- Origin URL:
http://avatars.com/john-smith.png
- Path:
/http%3A%2F%2Favatars.com%2Fjohn-smith.png
- Secure URL Token:
FOO123bar
- No imgix parameters
The resulting signature should be:
493a52f008c91416351f8b33d4883135
This makes the final URL:
https://my-social-network.imgix.net/http%3A%2F%2Favatars.com%2Fjohn-smith.png?s=493a52f008c91416351f8b33d4883135
Given:
- Path:
/users/1.png
- Secure URL Token:
FOO123bar
- The following imgix parameters:
w=400
andh=300
The resulting signature should be:
c7b86f666a832434dd38577e38cf86d1
This makes the final URL:
https://my-social-network.imgix.net/users/1.png?w=400&h=300&s=c7b86f666a832434dd38577e38cf86d1
Or if your language likes to alphabetize the params:
https://my-social-network.imgix.net/users/1.png?h=300&w=400&s=1a4e48641614d1109c6a7af51be23d18
Given:
- Path:
/http%3A%2F%2Favatars.com%2Fjohn-smith.png
- Secure URL Token:
FOO123bar
- The following imgix parameters:
w=400
andh=300
The resulting signature should be:
61ea1cc7add87653bb0695fe25f2b534
This makes the final URL:
https://my-social-network.imgix.net/http%3A%2F%2Favatars.com%2Fjohn-smith.png?w=400&h=300&s=61ea1cc7add87653bb0695fe25f2b534
Or if your language likes to alphabetize parameters:
https://my-social-network.imgix.net/http%3A%2F%2Favatars.com%2Fjohn-smith.png?h=300&w=400&s=a201fe1a3caef4944dcb40f6ce99e746