Resolvers locate and provide access to source images. A resolver translates an identifier in a request URL to an image locator, such as a pathname, in the particular type of underlying storage it is written to interface with. It can then check whether the underlying object exists and is accessible, and if so, provide access to it to other image server components. The rest of the image server does not need to know where an image resides, be it on the filesystem, in a database, on a remote web server, or in cloud storage—it can simply ask the current resolver, whatever it may be, to provide a generic interface from which an image can be read.
The interface in question may be a stream or a file. All resolvers can provide stream access, but only FilesystemResolver can provide file access. This distinction is important because not all processors can read from streams.
In a typical configuration, one resolver will handle all requests. It is also possible to configure the image server to select a resolver dynamically upon each request depending on the image identifier.
When the resolver.static
configuration key is set to the name of a resolver, that resolver will be used for all requests.
When a static resolver is not flexible enough, it is also possible to serve images from different sources simultaneously. For example, you may have some images stored on a filesystem, and others stored on Amazon S3. If you can differentiate their sources based on their identifier in code—either by analyzing the identifier string, or performing some kind of service request—you can use the delegate script mechanism to write a simple Ruby method to tell the image server which resolver to use for a given request.
To enable dynamic resolver selection, set the resolver.delegate
configuration key to true
. Then, implement the get_resolver(identifier)
method in the delegate script, which takes in an identifier and returns a resolver name (like FilesystemResolver, HttpResolver, etc.) For example:
See the Delegate Script section for general information about the delegate script.
On a filesystem… | …and the identifiers I use in URLs will correspond predictably to filesystem paths | FilesystemResolver with BasicLookupStrategy |
…and filesystem paths will need to be looked up (in a SQL database, search server, index file, etc.) based on their identifier | FilesystemResolver with ScriptLookupStrategy | |
On a local or remote web server… | …and the identifiers I use in URLs will correspond predictably to URL paths | HttpResolver with BasicLookupStrategy |
…and URL paths will need to be looked up (in a SQL database, search server, index file, etc.) based on their identifier | HttpResolver with ScriptLookupStrategy | |
As binaries or BLOBs in a SQL database | JdbcResolver | |
In the cloud | AmazonS3Resolver or AzureStorageResolver |
FilesystemResolver maps a URL identifier to a filesystem path, for retrieving images on a local or attached filesystem. In addition to being the most compatible resolver, this is also the most efficient resolver and may or may not be the only option for serving very large source images.
For images with extensions that are missing or unrecognized, this resolver will check the "magic number" to determine type, which will add some overhead. It is therefore slightly more efficient to serve images with extensions.
FilesystemResolver supports two distinct lookup strategies, defined by the FilesystemResolver.lookup_strategy
configuration option.
BasicLookupStrategy locates images by concatenating a pre-defined path prefix and/or suffix. For example, with the following configuration options set:
An identifier of image.jpg
in the URL will resolve to
/usr/local/images/image.jpg.
It's also possible to include a partial path in the identifier using URL-encoded slashes (%2F
) as path separators. subdirectory%2Fimage.jpg
in the URL would then resolve to /usr/local/images/subdirectory/image.jpg.
slash_substitude
configuration key.To prevent arbitrary directory traversal, BasicLookupStrategy will strip out ..{path separator}
and {path separator}..
from identifiers before resolving the path.
path_prefix
. The shallower the path, the more of the filesystem that will be exposed.Sometimes, BasicLookupStrategy will not offer enough control. Perhaps you want to serve images from multiple filesystems, or perhaps your identifiers are opaque and you need to perform a database or web service request to locate the corresponding images. With this lookup strategy, you can tell FilesystemResolver to invoke a method in your delegate script and capture the pathname it returns.
The delegate script method, get_pathname(identifier)
, will take in an identifier string and should return a pathname, if available, or nil
, if not. (See the Delegate Script section for general information about the delegate script.) Examples follow:
Note that several common Ruby database libraries (like the mysql and pgsql gems) use native extensions. These won't work in JRuby. Instead, the course of action above is to use the JDBC API via the JRuby-Java bridge. For this to work, a JDBC driver for your database will need to be installed on the Java classpath, and referenced in a java_import
statement.
This very simple imaginary web service will return a pathname in the response body if an image was found, and an empty response body if not.
In this variation on the previous example, our web service is Solr, and instead of parsing a text string out of the response body, we treat the body as Ruby code.
HttpResolver maps a URL identifier to an HTTP or HTTPS resource, for retrieving images from a web server.
It is preferable to use this resolver with source images with recognizable file extensions. For images with an extension that is missing or unrecognizable, it will issue an HTTP HEAD request to the server to check the Content-Type
header. If the type cannot be inferred from that, an error response will be returned.
HttpResolver supports two distinct lookup strategies, defined by the HttpResolver.lookup_strategy
configuration option.
BasicLookupStrategy locates images by concatenating a pre-defined URL prefix and/or suffix. For example, with the following configuration options set:
An identifier of image.jpg
in the URL will resolve to
http://example.org/images/image.jpg.
It's also possible to include a partial path in the identifier using URL-encoded slashes (%2F
) as path separators. subdirectory%2Fimage.jpg
in the URL would then resolve to http://example.org/images/subdirectory/image.jpg.
slash_substitude
configuration key.Sometimes, BasicLookupStrategy will not offer enough control. Perhaps you want to serve images from multiple URLs, or perhaps your identifiers are opaque and you need to run a database or web service request to locate them. With this lookup strategy, you can tell HttpResolver to invoke a method in your delegate script and capture the URL it returns.
The delegate script method, get_url(identifier)
, will take in an identifier string and should return a URL, if available, or nil
, if not. See the Delegate Script section for general information about the delegate script, and the FilesystemResolver ScriptLookupStrategy section for examples of similar scripts.
JdbcResolver maps a URL identifier to an RDBMS BLOB field, for retrieving images from a relational database. It does not require a custom schema and can adapt to any schema. The downside of that is that some delegate script methods must be implemented in order to obtain the information needed to run the SQL queries.
Cantaloupe does not include any JDBC drivers, so a driver JAR for the desired database must be obtained separately and saved somewhere on the classpath.
The JDBC connection is initialized by the JdbcResolver.url
, JdbcResolver.user
, and JdbcResolver.password
configuration options. If the user or password are not necessary, they can be left blank. The connection string must use your driver's JDBC syntax:
jdbc:postgresql://localhost:5432/my_database
jdbc:mysql://localhost:3306/my_database
jdbc:microsoft:sqlserver://example.org:1433;DatabaseName=MY_DATABASE
Consult the driver's documentation for details.
Then, the resolver needs to be told:
This method takes in an unencoded URL identifier and returns the corresponding database value of the identifier.
This method returns a media (MIME) type corresponding to the value returned by the get_database_identifier
method. If the media type is stored in the database, this example will return an SQL statement to retrieve it.
If the URL identifier will always have a known, valid image extension, like .jpg, .tif, etc., this method can return nil
, and Cantaloupe will infer the media type from the extension.
The get_lookup_sql
method returns an SQL statement that selects the BLOB value corresponding to the value returned by the get_database_identifier
method.
AmazonS3Resolver maps a URL identifier to an Amazon Simple Storage Service (S3) object, for retrieving images from Amazon S3. It can be configured with the following options:
AmazonS3Resolver.access_key_id
AmazonS3Resolver.secret_key
AmazonS3Resolver.bucket.name
AmazonS3Resolver.bucket.region
us-east-1
. Can be commented out or left blank to use a default region. (See S3 Regions.)AmazonS3Resolver.lookup_strategy
BasicLookupStrategy locates images by passing the URL identifier as-is to S3, with no additional configuration necessary or possible.
When your URL identifiers don't match your Amazon S3 object keys, ScriptLookupStrategy is available to tell AmazonS3Resolver to capture the object key returned by a method in your delegate script.
The delegate script method, get_s3_object_key(identifier)
, will take in an identifier string and should return an S3 object key string, if available, or nil
, if not. See the Delegate Script section for general information about the delegate script, and the FilesystemResolver ScriptLookupStrategy section for an example of a similar script.
AzureStorageResolver maps a URL identifier to a Microsoft Azure Storage blob, for retrieving images from Azure Storage. It can be configured with the following options:
AzureStorageResolver.account_name
AzureStorageResolver.account_key
AzureStorageResolver.container_name
AzureStorageResolver.lookup_strategy
BasicLookupStrategy locates images by passing the URL identifier as-is to Azure Storage, with no additional configuration necessary or possible.
When your URL identifiers don't match your Azure Storage blob keys, ScriptLookupStrategy is available to tell AzureStorageResolver to capture the blob key returned by a method in your delegate script.
The delegate script method, get_azure_storage_blob_key(identifier)
, will take in an identifier string and should return a blob key string, if available, or nil
, if not. See the Delegate Script section for general information about the delegate script, and the FilesystemResolver ScriptLookupStrategy section for an example of a similar script.