samvera/serverless-iiif

View on GitHub
sam/template.yml

Summary

Maintainability
Test Coverage
Transform: "AWS::Serverless-2016-10-31"
Metadata:
  AWS::ServerlessRepo::Application:
    Name: serverless-iiif
    Description: IIIF Image API 2.1 and 3.0 Service Lambda Function
    Author: Samvera
    SpdxLicenseId: Apache-2.0
    LicenseUrl: ../LICENSE.txt
    ReadmeUrl: ../README.md
    Labels: ["iiif", "image-processing"]
    HomePageUrl: https://samvera.github.io/serverless-iiif
    SemanticVersion: 5.0.6
    SourceCodeUrl: https://github.com/samvera/serverless-iiif
  AWS::CloudFormation::Interface:
    ParameterGroups:
      - Label:
          default: "General Configuration"
        Parameters:
          - SourceBucket
          - IiifLambdaMemory
          - IiifLambdaTimeout
          - PixelDensity
          - PyramidLimit
          - ResolverTemplate
      - Label:
          default: "CORS Configuration"
        Parameters:
          - CorsAllowCredentials
          - CorsAllowHeaders
          - CorsAllowOrigin
          - CorsExposeHeaders
          - CorsMaxAge
      - Label:
          default: "Advanced Options"
        Parameters:
          - ForceHost
          - Preflight
Parameters:
  CorsAllowCredentials:
    Type: String
    Description: >
      Value of the CORS `Access-Control-Allow-Credentials` response header.
      Must be `true` to allow requests with `Authorization` and/or
      `Cookie` headers.
    AllowedValues:
      - false
      - true
    Default: false
  CorsAllowHeaders:
    Type: String
    Description: Value of the CORS `Access-Control-Allow-Headers` response header
    Default: "*"
  CorsAllowOrigin:
    Type: String
    Description: >
      Value of the CORS `Access-Control-Allow-Origin` response header.
      Use the special value `REFLECT_ORIGIN` to copy the value from the
      `Origin` request header (required to emulate `*` for XHR requests
      using `Authorization` and/or `Cookie` headers).
    Default: "*"
  CorsExposeHeaders:
    Type: String
    Description: Value of the CORS `Access-Control-Expose-Headers` response header
    Default: cache-control,content-language,content-length,content-type,date,expires,last-modified,pragma
  CorsMaxAge:
    Type: Number
    Description: Value of the CORS `Access-Control-MaxAge` response header
    Default: 3600
  ForceHost:
    Type: String
    Description: Forced hostname to use in responses
    Default: ""
  IiifLambdaMemory:
    Type: Number
    Description: The memory provisioned for the lambda.
    MinValue: 128
    MaxValue: 10240
    Default: 3008
  IiifLambdaTimeout:
    Type: Number
    Description: The timeout for the lambda.
    Default: 10
  PixelDensity:
    Type: Number
    Description: Hardcoded DPI/Pixel Density/Resolution to encode in output images
    Default: 0
    MinValue: 0
  Preflight:
    Type: String
    Description: Indicates whether the function should expect preflight headers
    AllowedValues:
      - false
      - true
    Default: false
  PyramidLimit:
    Type: Number
    Description: Smallest pyramid image dimension. Set to `0` to prevent server from auto-calculating pyramid page sizes.
    MinValue: 0
    Default: 256
  ResolverTemplate:
    Type: String
    Description: A printf-style format string that determines the location of source image within the bucket given the image ID
    Default: "%s.tif"
  SharpLayer:
    Type: String
    Description: >
      ARN of a custom AWS Lambda Layer containing the sharp and libvips dependencies. Use the special value `JP2` 
      to use the managed JPEG2000-compatible layer, or `INTERNAL` to use the built-in dependencies (without JPEG2000
      support).
    AllowedPattern: "^INTERNAL$|^JP2$|^arn:aws:lambda:.*:.*:layer:.+:\\d+$"
    Default: "JP2"
  SourceBucket:
    Type: String
    Description: Name of bucket containing source images
Conditions:
  UseBuiltInDependencies:
    Fn::Equals: [!Ref SharpLayer, "INTERNAL"]
  UseJP2SharpLayer:
    Fn::Equals: [!Ref SharpLayer, "JP2"]
  UseForceHost:
    Fn::Not:
      - Fn::Equals: [!Ref ForceHost, ""]
  UsePixelDensity:
    Fn::Not:
      - Fn::Equals: [!Ref PixelDensity, 0]
  UsePyramidLimit:
    Fn::Not:
      - Fn::Equals: [!Ref PyramidLimit, 0]
Resources:
  Dependencies:
    Type: "AWS::Serverless::LayerVersion"
    Properties:
      LayerName:
        Fn::Sub: "${AWS::StackName}-dependencies"
      Description: Dependencies for IIIF app
      ContentUri: ../dependencies
      CompatibleRuntimes:
        - nodejs18.x
      LicenseInfo: "Apache-2.0"
    Metadata:
      BuildMethod: nodejs18.x
  IiifFunction:
    Type: "AWS::Serverless::Function"
    Properties:
      Runtime: nodejs18.x
      Handler: index.handler
      MemorySize:
        Ref: IiifLambdaMemory
      FunctionUrlConfig:
        AuthType: NONE
        InvokeMode: RESPONSE_STREAM
      Timeout:
        Ref: IiifLambdaTimeout
      CodeUri: ../src
      Layers:
        - Ref: Dependencies
        - Fn::If:
          - UseBuiltInDependencies
          - !Ref AWS::NoValue
          - Fn::If:
            - UseJP2SharpLayer
            - !Sub "arn:aws:lambda:${AWS::Region}:625046682746:layer:libvips-sharp-jp2:4"
            - Ref: SharpLayer
      Policies:
        - AWSLambdaExecute
        - Version: "2012-10-17"
          Statement:
            - Effect: Allow
              Action:
                - s3:ListAllMyBuckets
              Resource: "*"
            - Effect: Allow
              Action:
                - s3:GetObject
                - s3:GetObjectACL
              Resource:
                Fn::Sub: "arn:aws:s3:::${SourceBucket}/*"
        - Version: "2012-10-17"
          Statement:
            - Effect: Allow
              Action:
                - s3:ListBucket
                - s3:GetBucketLocation
              Resource:
                Fn::Sub: "arn:aws:s3:::${SourceBucket}"
      Environment:
        Variables:
          corsAllowCredentials: !Ref CorsAllowCredentials
          corsAllowOrigin: !Ref CorsAllowOrigin
          corsAllowHeaders: !Ref CorsAllowHeaders
          corsExposeHeaders: !Ref CorsExposeHeaders
          corsMaxAge: !Ref CorsMaxAge
          density:
            Fn::If:
              - UsePixelDensity
              - !Ref PixelDensity
              - !Ref AWS::NoValue
          forceHost:
            Fn::If:
              - UseForceHost
              - !Ref ForceHost
              - !Ref AWS::NoValue
          preflight: !Ref Preflight
          pyramidLimit:
            Fn::If:
              - UsePyramidLimit
              - !Ref PyramidLimit
              - !Ref AWS::NoValue
          resolverTemplate: !Ref ResolverTemplate
          tiffBucket: !Ref SourceBucket
Outputs:
  EndpointV2:
    Description: IIIF Image API v2 Endpoint
    Value:
      Fn::Sub: "${IiifFunctionUrl.FunctionUrl}iiif/2"
  EndpointV3:
    Description: IIIF Image API v3 Endpoint
    Value:
      Fn::Sub: "${IiifFunctionUrl.FunctionUrl}iiif/3"
  FunctionDomain:
    Description: IIIF Function Domain Name
    Value:
      Fn::Select:
        - 2
        - Fn::Split:
          - "/"
          - Fn::GetAtt: IiifFunctionUrl.FunctionUrl
  FunctionUrl:
    Description: IIIF Function URL
    Value:
      Fn::GetAtt: IiifFunctionUrl.FunctionUrl