Documentation
Advanced Usage
Request Response Functions

Request/Response Functions

The IIIF service can be heavily customized through the use of CloudFront Functions (opens in a new tab) or Lambda@Edge Functions (opens in a new tab) attached to a CloudFront distribution in front of the service. It's important to understand the four stages of CloudFront processing in order to know where a given type of customization belongs.

  • A viewer-request function will be called on every request, cached or not. This is the appropriate place to attach a function that performs authorization, authentication, or anything else whose result should not be cached.
  • An origin-request function will only be called when CloudFront refreshes the content from the origin (e.g., the IIIF server). It's the appropriate place to attach a function that should be cached, such as S3 file resolution or the retrieval of image dimensions.
  • Similarly, the origin-response and viewer-response functions are called after the IIIF server returns its response and before CloudFront passes it on to the viewer, respectively. They can be used to alter the response in a way that is either cached or ephemeral.

Examples

These examples use CloudFront Functions. Lambda@Edge functions are slightly more complicated in terms of the event structure but the basic idea is the same.

Simple Authorization
function handler(event) {
    if (notAuthorized) { // based on something in the event.request
       return {
         statusCode: 403,
         statusDescription: 'Unauthorized'
       };
    };
    return event.request;
}
Custom File Location / Image Dimensions
function handler(event) {
  var request = event.request;
  request.headers['x-preflight-location'] = [{value: 's3://image-bucket/path/to/correct/image.tif'}];
  request.headers['x-preflight-dimensions'] = [{value: JSON.stringify({ width: 640, height: 480 })}];
  return request;
}

The x-preflight-dimensions header can take several shapes:

  • { width, height } (or [{ width, height }]) - a straightforward, single-resolution image
  • [{ width, height }, { width, height }, ...] - a multi-resolution image with pages of the specified sizes
  • { width, height, pages } - a multi-resolution image with the specified number of pages, each half the size of the one before
  • { width, height, limit } - a multi-resolution image in which the smallest width and height are both less than the specified limit

For example, the following dimension values would all describe the same pyramidal image:

  • [{ width: 2048, height: 1536 }, { width: 1024, height: 768 }, { width: 512, height: 384 }]
  • { width: 2048, height: 1536, pages: 3 }
  • { width: 2048, height: 1536, limit: 480 }

The limit calculator will keep going until both dimensions are less than the limit, not less than or equal to. So a limit: 512 on the third example above would generate a fourth page at { width: 256, height: 192 }.

💡

If you plan to use CloudFront functions to add either of the above x-preflight- headers to incoming requests, you must set the value of the Preflight parameter to true when deploying serverless-iiif. The function will only look for the preflight headers if this environment variable is true. This prevents requests from including those headers directly if no preflight function is present. If you do use a preflight function, make sure it strips out any x-preflight-location and x-preflight-dimensions headers that it doesn't set itself.