public async setup()

in source/image-handler/image-request.ts [29:95]


  public async setup(event: ImageHandlerEvent): Promise<ImageRequestInfo> {
    try {
      await this.validateRequestSignature(event);

      let imageRequestInfo: ImageRequestInfo = <ImageRequestInfo>{};

      imageRequestInfo.requestType = this.parseRequestType(event);
      imageRequestInfo.bucket = this.parseImageBucket(event, imageRequestInfo.requestType);
      imageRequestInfo.key = this.parseImageKey(event, imageRequestInfo.requestType);
      imageRequestInfo.edits = this.parseImageEdits(event, imageRequestInfo.requestType);

      const originalImage = await this.getOriginalImage(imageRequestInfo.bucket, imageRequestInfo.key);
      imageRequestInfo = { ...imageRequestInfo, ...originalImage };

      imageRequestInfo.headers = this.parseImageHeaders(event, imageRequestInfo.requestType);

      // If the original image is SVG file and it has any edits but no output format, change the format to WebP.
      if (imageRequestInfo.contentType === 'image/svg+xml' && imageRequestInfo.edits && Object.keys(imageRequestInfo.edits).length > 0 && !imageRequestInfo.edits.toFormat) {
        imageRequestInfo.outputFormat = ImageFormatTypes.PNG;
      }

      /* Decide the output format of the image.
       * 1) If the format is provided, the output format is the provided format.
       * 2) If headers contain "Accept: image/webp", the output format is webp.
       * 3) Use the default image format for the rest of cases.
       */
      if (imageRequestInfo.contentType !== 'image/svg+xml' || imageRequestInfo.edits.toFormat || imageRequestInfo.outputFormat) {
        const outputFormat = this.getOutputFormat(event, imageRequestInfo.requestType);
        // if webp check reduction effort, if invalid value, use 4 (default in sharp)
        if (outputFormat === ImageFormatTypes.WEBP && imageRequestInfo.requestType === RequestTypes.DEFAULT) {
          const decoded = this.decodeRequest(event);
          if (typeof decoded.reductionEffort !== 'undefined') {
            const reductionEffort = Math.trunc(decoded.reductionEffort);
            const isValid = !isNaN(reductionEffort) && reductionEffort >= 0 && reductionEffort <= 6;
            imageRequestInfo.reductionEffort = isValid ? reductionEffort : ImageRequest.DEFAULT_REDUCTION_EFFORT;
          }
        }
        if (imageRequestInfo.edits && imageRequestInfo.edits.toFormat) {
          imageRequestInfo.outputFormat = imageRequestInfo.edits.toFormat;
        } else if (outputFormat) {
          imageRequestInfo.outputFormat = outputFormat;
        }
      }

      // Fix quality for Thumbor and Custom request type if outputFormat is different from quality type.
      if (imageRequestInfo.outputFormat) {
        const requestType = [RequestTypes.CUSTOM, RequestTypes.THUMBOR];
        const acceptedValues = [ImageFormatTypes.JPEG, ImageFormatTypes.PNG, ImageFormatTypes.WEBP, ImageFormatTypes.TIFF, ImageFormatTypes.HEIF];

        imageRequestInfo.contentType = `image/${imageRequestInfo.outputFormat}`;
        if (requestType.includes(imageRequestInfo.requestType) && acceptedValues.includes(imageRequestInfo.outputFormat)) {
          const qualityKey = Object.keys(imageRequestInfo.edits).filter(key => acceptedValues.includes(key as ImageFormatTypes))[0];

          if (qualityKey && qualityKey !== imageRequestInfo.outputFormat) {
            imageRequestInfo.edits[imageRequestInfo.outputFormat] = imageRequestInfo.edits[qualityKey];
            delete imageRequestInfo.edits[qualityKey];
          }
        }
      }

      return imageRequestInfo;
    } catch (error) {
      console.error(error);

      throw error;
    }
  }