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-requestfunction 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-requestfunction 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-responseandviewer-responsefunctions 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, pages: 3 })}];
return request;
}The x-preflight-dimensions header should be a JSON object including some or all of the following properties:
- Basic properties (required):
width: the width in pixels of the largest representation of the entire imageheight: the height in pixels of the largest representation of the entire image
- Multi-resolution properties (at least one is required):
sizes: an array of[{width, height}]listing the size in pixels of each resolution included in the pyramidal imagepages: the number of resolutions contained in the pyramidal image (or1if the image isn't pyramidal)
- Optional properties:
tileWidth: the tile width used when generating the tiled pyramidal imagetileHeight: the tile height used when generating the tiled pyramidal image
For example, the following dimension values would all describe the same pyramidal image:
{ width: 1024, height: 768, sizes: [{ width: 1024, height: 768 }, { width: 512, height: 384 }, { width: 256, height: 192 }] }{ width: 1024, height: 768, pages: 3 }
When responding to an Image Information Document (info.json) document request, if tileWidth is not present, the image will be
probed to determine the correct values for tileWidth and tileHeight. If tileWidth is present but null, the tiles property
will not be included in the output.
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.