This version of the manual refers to an earlier version of the software.

Delegate Script

The delegate script mechanism enables the use of custom Ruby methods as "hooks" to provide dynamic information back to the image server. A truly customized image server can be created with minimal code.

Delegate methods are implemented in Ruby, and invoked by a JRuby interpreter bundled into the image server. There is no need to install an external Ruby environment and no need to know Java; just type some code into a file, and go.

The delegate script mechanism is disabled by default. To enable it, copy the sample delegate script, delegates.rb.sample, included in the distribution, to delegates.rb; reference it from the delegate_script.pathname configuration option; and set delegate_script.enabled to true.


Rules

While the arguments and return types of each method will vary, all delegate methods must be contained within a Cantaloupe module. Inside a method, anything goes, and you can use any (non-platform-native) gems that you have installed with gem install.

Because delegate methods will be called frequently, though, they should be written with efficiency in mind.

The delegate script will be reloaded on each request, so it can be edited without restarting. But, code that has been loaded into the JRuby runtime cannot be unloaded. For example, when a method is changed, it will overwrite the old version; but a constant cannot be redefined.

Note: typically, neither method arguments nor return values are sanitized or validated. Be very careful to write defensive, injection-aware code.

Example

Here is an example of a script used by FilesystemResolver that performs a Solr query to return a pathname based on an identifier. The documentation in that section describes the contract that this method must abide by: its name, arguments, and return value.

require 'cgi'
require 'net/http'

module Cantaloupe

  module FilesystemResolver
    ##
    # Used by FilesystemResolver's ScriptLookupStrategy.
    #
    # @param identifier [String] Image identifier
    # @return [String,nil] Absolute pathname of the image corresponding to the
    #                      given identifier, or nil if not found.
    #
    def self.get_pathname(identifier)
      uri = 'http://localhost:8983/solr/collection1/select?q=' +
          CGI.escape('id:"' + identifier + '"') +
          '&fl=pathname_si&wt=ruby'
      uri = URI.parse(uri)

      http = Net::HTTP.new(uri.host, uri.port)
      request = Net::HTTP::Get.new(uri.request_uri)
      response = http.request(request)
      return nil if response.code.to_i >= 400

      results = eval(response.body)['response']['docs']
      results.any? ? results.first['pathname_si'] : nil
    end
  end

end

Testing Script Methods

Using the example above, get_pathname() could be tested by adding the following line to the end of the script:

puts Cantaloupe::FilesystemResolver::get_pathname('identifier-to-test')
And running it on the command line with a command like: ruby delegates.rb. The method output will appear in the console.

The delegate script is standard Ruby code that will work in any Ruby interpreter. The only thing to be aware of is that gems with platform-native extensions will not work in JRuby. For that reason, it would be best to install a standalone JRuby interpreter and test with that. (Something like RVM can make it easier to switch between different versions of the Ruby interpreter.)