diff --git a/.changeset/yummy-bananas-worry.md b/.changeset/yummy-bananas-worry.md new file mode 100644 index 00000000..13724274 --- /dev/null +++ b/.changeset/yummy-bananas-worry.md @@ -0,0 +1,5 @@ +--- +'@fingerprint/aws-cloudfront-proxy': minor +--- + +Skip creation of V3-related routes if related variables are empty diff --git a/.github/workflows/terraform-e2e-tests-on-dev.yml b/.github/workflows/terraform-e2e-tests-on-dev.yml index fd2b9918..ad6f7979 100644 --- a/.github/workflows/terraform-e2e-tests-on-dev.yml +++ b/.github/workflows/terraform-e2e-tests-on-dev.yml @@ -15,7 +15,7 @@ jobs: steps: - name: Checkout code uses: actions/checkout@v4 - + - name: Configure AWS credentials from dev account uses: aws-actions/configure-aws-credentials@v4 with: @@ -33,19 +33,19 @@ jobs: version: 9 - run: pnpm install - + - run: pnpm exec playwright install working-directory: e2e/tests - + - run: pnpm build && bash scripts/preparePackage.sh - + - run: pnpm build working-directory: e2e/website - env: + env: VITE_API_KEY: ${{ secrets.PUBLIC_API_KEY }} VITE_SCRIPT_URL_PATTERN: /fpjs/agent?apiKey=&version=&loaderVersion= VITE_ENDPOINT: /fpjs/result?region=us - + - uses: hashicorp/setup-terraform@v3 with: terraform_version: "1.11.0" @@ -62,7 +62,7 @@ jobs: run: gmake ENV=${{ env.ENV }} TIER=${{ env.TIER }} REGION=${{ env.REGION }} apply-auto-approve env: TF_VAR_fpjs_shared_secret: ${{ secrets.PROXY_SECRET }} - + mock-warden-e2e-tests: runs-on: ubuntu-latest needs: e2e-tests @@ -86,7 +86,7 @@ jobs: with: version: 9 - - run: pnpm install && npm install ts-node -g + - run: pnpm install - run: pnpm build:release env: diff --git a/README.md b/README.md index 8275f3a4..45ce1fe5 100644 --- a/README.md +++ b/README.md @@ -7,34 +7,34 @@

-Current version -coverage +Current version +coverage MIT license Discord server

-# Fingerprint Pro CloudFront Integration +# Fingerprint CloudFront Proxy Integration [Fingerprint](https://fingerprint.com/) is a device intelligence platform offering industry-leading accuracy. -Fingerprint Pro CloudFront Integration is responsible for +The Fingerprint CloudFront Integration is responsible for -- Proxying download requests of the latest Fingerprint Pro JS Agent between your site and Fingerprint CDN. -- Proxying identification requests and responses between your site and Fingerprint Pro's APIs. +- Proxying download requests of the latest Fingerprint JS Agent between your site and Fingerprint CDN. +- Proxying identification requests and responses between your site and Fingerprint's APIs. -This [improves](https://dev.fingerprint.com/docs/cloudfront-proxy-integration-v2#the-benefits-of-using-the-cloudfront-integration) both accuracy and reliability of visitor identification and bot detection on your site. +This [improves](https://docs.fingerprint.com/docs/cloudfront-proxy-integration-v2#the-benefits-of-using-the-cloudfront-integration) both accuracy and reliability of visitor identification and bot detection on your site. > [!IMPORTANT] -> CloudFront integration v1 has been [deprecated](https://dev.fingerprint.com/docs/cloudfront-proxy-integration). -> This repository now contains the source code for [CloudFront Integration v2](https://dev.fingerprint.com/docs/cloudfront-proxy-integration-v2). -> If you are currently using v1, see our guide for [Migrating CloudFront proxy integration from v1 to v2](https://dev.fingerprint.com/docs/cloudfront-integration-migration-from-v1-to-v2). +> CloudFront integration v1 has been [deprecated](https://docs.fingerprint.com/docs/cloudfront-proxy-integration). +> This repository now contains the source code for [CloudFront Integration v2](https://docs.fingerprint.com/docs/cloudfront-proxy-integration-v2). +> If you are currently using v1, see our guide for [Migrating CloudFront proxy integration from v1 to v2](https://docs.fingerprint.com/docs/v3/cloudfront-integration-migration-from-v1-to-v2). ## Requirements - AWS Account > [!IMPORTANT] -> The AWS CloudFront Proxy Integration is accessible and exclusively supported for customers on the Enterprise Plan. Other customers are encouraged to use [Custom subdomain setup](https://dev.fingerprint.com/docs/custom-subdomain-setup) or [Cloudflare Proxy Integration](https://dev.fingerprint.com/docs/cloudflare-integration). +> The AWS CloudFront Proxy Integration is accessible and exclusively supported for customers on the Enterprise Plan. Other customers are encouraged to use [Custom subdomain setup](https://docs.fingerprint.com/docs/custom-subdomain-setup) or [Cloudflare Proxy Integration](https://docs.fingerprint.com/docs/cloudflare-integration). > [!WARNING] > The underlying data contract in the identification logic can change to keep up with browser updates. Using the AWS CloudFront Proxy Integration might require occasional manual updates on your side. Ignoring these updates will lead to lower accuracy or service disruption. @@ -44,14 +44,14 @@ This [improves](https://dev.fingerprint.com/docs/cloudfront-proxy-integration-v2 To set up CloudFront integration, you need to: 1. Create the required resources in your AWS infrastructure — a CloudFormation stack and a CloudFront distribution. -2. Configure the Fingerprint Pro JS Agent on your site to communicate with your created Lambda@Edge function using the [scriptUrlPattern](https://dev.fingerprint.com/reference/load-function#scripturlpattern) and [endpoint](https://dev.fingerprint.com/reference/load-function#endpoint) parameters. +2. Configure the Fingerprint JS Agent on your site to communicate with your created Lambda@Edge function using the [endpoints](https://docs.fingerprint.com/reference/js-agent-v4-start-function#endpoints) parameter. -See [CloudFront Proxy Integration guide](https://dev.fingerprint.com/docs/cloudfront-proxy-integration-v2) in our documentation for step-by-step instructions. If you have any questions, reach out to our [support team](https://fingerprint.com/support/). +See [CloudFront Proxy Integration guide](https://docs.fingerprint.com/docs/cloudfront-proxy-integration-v2) in our documentation for step-by-step instructions. If you have any questions, reach out to our [support team](https://fingerprint.com/support/). ### Deployment using Terraform -If you prefer to deploy the integration using Terraform, see the [Terraform module repository](https://github.com/fingerprintjs/terraform-aws-fingerprint-cloudfront-proxy-integration) and the related [Terraform guide](https://dev.fingerprint.com/docs/aws-cloudfront-integration-via-terraform). +If you prefer to deploy the integration using Terraform, see the [Terraform module repository](https://github.com/fingerprintjs/terraform-aws-fingerprint-cloudfront-proxy-integration) and the related [Terraform guide](https://docs.fingerprint.com/docs/aws-cloudfront-integration-via-terraform). ## License -This project is licensed under the MIT license. See the [LICENSE](https://github.com/fingerprintjs/fingerprint-pro-cloudfront-integration/blob/main/LICENSE) file for more info. +This project is licensed under the MIT license. See the [LICENSE](https://github.com/fingerprintjs/aws-cloudfront-proxy/blob/main/LICENSE) file for more info. diff --git a/cloudformation/template.yml b/cloudformation/template.yml index b5c6fda7..9f72d4df 100644 --- a/cloudformation/template.yml +++ b/cloudformation/template.yml @@ -8,14 +8,14 @@ Parameters: Default: "" Type: String FpjsGetResultPath: - AllowedPattern: ^([a-zA-Z0-9\-])+$ - Description: request path used to send identification requests (aka FPJS_GET_RESULT_PATH) - Default: "result" + AllowedPattern: ^$|^([a-zA-Z0-9\-])+$ + Description: (Optional) request path used to send V3 identification requests (aka FPJS_GET_RESULT_PATH) + Default: "" Type: String FpjsAgentDownloadPath: - AllowedPattern: ^([a-zA-Z0-9\-])+$ - Description: request path used to send ProCDN requests (aka FPJS_AGENT_DOWNLOAD_PATH) - Default: "agent" + AllowedPattern: ^$|^([a-zA-Z0-9\-])+$ + Description: (Optional) request path used to send V3 ProCDN requests (aka FPJS_AGENT_DOWNLOAD_PATH) + Default: "" Type: String FpjsPreSharedSecret: AllowedPattern: ^([a-zA-Z0-9\-])+$ diff --git a/e2e/infra/terraform/cloudfront_invalidate.tf b/e2e/infra/terraform/cloudfront_invalidate.tf index 04bee6ca..2cf3c03e 100644 --- a/e2e/infra/terraform/cloudfront_invalidate.tf +++ b/e2e/infra/terraform/cloudfront_invalidate.tf @@ -1,3 +1,13 @@ +resource "null_resource" "invalidate_with_secret_cache_v4_only" { + triggers = { + run_id = timestamp() + } + + provisioner "local-exec" { + command = "aws cloudfront create-invalidation --distribution-id ${aws_cloudfront_distribution.with_secret_v4_only.id} --paths '/*'" + } +} + resource "null_resource" "invalidate_with_secret_cache" { triggers = { run_id = timestamp() diff --git a/e2e/infra/terraform/cloudfront_v4.tf b/e2e/infra/terraform/cloudfront_v4.tf new file mode 100644 index 00000000..787efd12 --- /dev/null +++ b/e2e/infra/terraform/cloudfront_v4.tf @@ -0,0 +1,80 @@ +resource "aws_cloudfront_distribution" "with_secret_v4_only" { + enabled = true + is_ipv6_enabled = true + comment = "CloudFront distribution for E2E Tests using Secrets Manager with V4 only" + default_root_object = "index.html" + + default_cache_behavior { + allowed_methods = ["GET", "HEAD", "OPTIONS"] + cached_methods = ["GET", "HEAD"] + target_origin_id = aws_s3_bucket.website_bucket.bucket_domain_name + viewer_protocol_policy = "redirect-to-https" + + forwarded_values { + query_string = false + cookies { + forward = "none" + } + } + } + + depends_on = [ + aws_s3_bucket_policy.website_bucket_policy + ] + + origin { + domain_name = aws_s3_bucket.website_bucket.bucket_domain_name + origin_id = aws_s3_bucket.website_bucket.bucket_domain_name + } + + restrictions { + geo_restriction { + restriction_type = "none" + } + } + + origin { + domain_name = var.fpjs_origin_name + origin_id = var.fpjs_origin_id + custom_origin_config { + origin_protocol_policy = "https-only" + http_port = 80 + https_port = 443 + origin_ssl_protocols = ["TLSv1.2"] + } + custom_header { + name = "FPJS_SECRET_NAME" + value = module.fingerprint_cloudfront_integration_v4_only.fpjs_secret_manager_arn + } + custom_header { + name = "fpjs_debug" + value = "true" + } + } + + ordered_cache_behavior { + path_pattern = "${var.fpjs_behavior_path}*" + + allowed_methods = ["GET", "HEAD", "OPTIONS", "PUT", "POST", "PATCH", "DELETE"] + cached_methods = ["GET", "HEAD"] + cache_policy_id = module.fingerprint_cloudfront_integration_v4_only.fpjs_cache_policy_id + origin_request_policy_id = module.fingerprint_cloudfront_integration_v4_only.fpjs_origin_request_policy_id + target_origin_id = module.fingerprint_cloudfront_integration_v4_only.fpjs_origin_id + viewer_protocol_policy = "https-only" + compress = true + + lambda_function_association { + event_type = "origin-request" + lambda_arn = module.fingerprint_cloudfront_integration_v4_only.fpjs_proxy_lambda_arn + include_body = true + } + } + + viewer_certificate { + cloudfront_default_certificate = true + } +} + +output "cloudfront_with_secret_url_v4_only" { + value = aws_cloudfront_distribution.with_secret_v4_only.domain_name +} \ No newline at end of file diff --git a/e2e/infra/terraform/fingerprint.tf b/e2e/infra/terraform/fingerprint.tf index b6d1ae59..b71ce3e5 100644 --- a/e2e/infra/terraform/fingerprint.tf +++ b/e2e/infra/terraform/fingerprint.tf @@ -3,6 +3,15 @@ module "fingerprint_cloudfront_integration" { fpjs_agent_download_path = var.fpjs_agent_download_path fpjs_get_result_path = var.fpjs_get_result_path + fpjs_shared_secret = var.fpjs_shared_secret + fetch_lambda_from_s3 = false + local_lambda_path = "../../../lambda_latest.zip" +} + +// TODO After release, replace with source from above +module "fingerprint_cloudfront_integration_v4_only" { + source = "git::https://github.com/fingerprintjs/terraform-aws-fingerprint-cloudfront-proxy-integration.git?ref=feature/add-v4-support" + fpjs_shared_secret = var.fpjs_shared_secret fetch_lambda_from_s3 = false local_lambda_path = "../../../lambda_latest.zip" diff --git a/e2e/infra/terraform/tests.tf b/e2e/infra/terraform/tests.tf index 18c0b332..9f8dfb0f 100644 --- a/e2e/infra/terraform/tests.tf +++ b/e2e/infra/terraform/tests.tf @@ -5,8 +5,9 @@ resource "null_resource" "tests" { command = "pnpm test" working_dir = "../../tests" environment = { - CLOUDFRONT_WITH_HEADERS_URL = aws_cloudfront_distribution.with_headers.domain_name - CLOUDFRONT_WITH_SECRETS_URL = aws_cloudfront_distribution.with_secret.domain_name + CLOUDFRONT_WITH_HEADERS_URL = aws_cloudfront_distribution.with_headers.domain_name + CLOUDFRONT_WITH_SECRETS_URL = aws_cloudfront_distribution.with_secret.domain_name + CLOUDFRONT_WITH_SECRETS_V4_URL = aws_cloudfront_distribution.with_secret_v4_only.domain_name } } triggers = { @@ -16,8 +17,13 @@ resource "null_resource" "tests" { # Make sure that we run this after cloudfront is ready depends_on = [ - aws_cloudfront_distribution.with_headers, aws_cloudfront_distribution.with_secret, - null_resource.invalidate_with_headers_cache, null_resource.invalidate_with_secret_cache + aws_cloudfront_distribution.with_headers, + aws_cloudfront_distribution.with_secret, + aws_cloudfront_distribution.with_secret_v4_only, + + null_resource.invalidate_with_headers_cache, + null_resource.invalidate_with_secret_cache, + null_resource.invalidate_with_secret_cache_v4_only ] } @@ -25,15 +31,48 @@ resource "null_resource" "mock-warden-tests" { count = var.run_mock_warden_tests ? 1 : 0 provisioner "local-exec" { - command = "ts-node e2e/scripts/mockTests.ts --project tsconfig.json" + command = "pnpm exec ts-node e2e/scripts/mockTests.ts --project tsconfig.json" + working_dir = "../../../" + environment = { + CLOUDFRONT_WITH_HEADERS_URL = aws_cloudfront_distribution.with_headers.domain_name + CLOUDFRONT_WITH_SECRETS_URL = aws_cloudfront_distribution.with_secret.domain_name + CLOUDFRONT_WITH_SECRETS_V4_URL = aws_cloudfront_distribution.with_secret_v4_only.domain_name + FPJS_BEHAVIOR_PATH = var.fpjs_behavior_path + FPJS_AGENT_DOWNLOAD_PATH = var.fpjs_agent_download_path + FPJS_GET_RESULT_PATH = var.fpjs_get_result_path + API_URL = var.mock_warden_url + } + } + + triggers = { + # We need to define this to run on every `terraform apply` + run_id = timestamp() + } + + # Make sure that we run this after cloudfront is ready + depends_on = [ + aws_cloudfront_distribution.with_headers, + aws_cloudfront_distribution.with_secret, + null_resource.invalidate_with_headers_cache, + null_resource.invalidate_with_secret_cache + ] +} + +resource "null_resource" "mock-warden-tests-v4" { + count = var.run_mock_warden_tests ? 1 : 0 + + provisioner "local-exec" { + command = "pnpm exec ts-node e2e/scripts/mockTests.ts --project tsconfig.json" working_dir = "../../../" environment = { - CLOUDFRONT_WITH_HEADERS_URL = aws_cloudfront_distribution.with_headers.domain_name - CLOUDFRONT_WITH_SECRETS_URL = aws_cloudfront_distribution.with_secret.domain_name - FPJS_BEHAVIOR_PATH = var.fpjs_behavior_path - FPJS_AGENT_DOWNLOAD_PATH = var.fpjs_agent_download_path - FPJS_GET_RESULT_PATH = var.fpjs_get_result_path - API_URL = var.mock_warden_url + CLOUDFRONT_WITH_HEADERS_URL = aws_cloudfront_distribution.with_headers.domain_name + CLOUDFRONT_WITH_SECRETS_URL = aws_cloudfront_distribution.with_secret.domain_name + CLOUDFRONT_WITH_SECRETS_V4_URL = aws_cloudfront_distribution.with_secret.domain_name + V4_ONLY = "true" + FPJS_BEHAVIOR_PATH = var.fpjs_behavior_path + FPJS_AGENT_DOWNLOAD_PATH = var.fpjs_agent_download_path + FPJS_GET_RESULT_PATH = var.fpjs_get_result_path + API_URL = var.mock_warden_url } } @@ -44,7 +83,11 @@ resource "null_resource" "mock-warden-tests" { # Make sure that we run this after cloudfront is ready depends_on = [ - aws_cloudfront_distribution.with_headers, aws_cloudfront_distribution.with_secret, - null_resource.invalidate_with_headers_cache, null_resource.invalidate_with_secret_cache + aws_cloudfront_distribution.with_headers, + aws_cloudfront_distribution.with_secret, + aws_cloudfront_distribution.with_secret_v4_only, + null_resource.invalidate_with_headers_cache, + null_resource.invalidate_with_secret_cache, + null_resource.invalidate_with_secret_cache_v4_only ] -} \ No newline at end of file +} diff --git a/e2e/scripts/mockTests.ts b/e2e/scripts/mockTests.ts index 04889bf5..90ac013e 100644 --- a/e2e/scripts/mockTests.ts +++ b/e2e/scripts/mockTests.ts @@ -1,5 +1,5 @@ import { execSync } from 'child_process' -import { getCloudfrontUrls } from '../tests/src/utils/cloudfront' +import { CloudfrontUrls, getCloudfrontUrls } from '../tests/src/utils/cloudfront' import { version } from '../../package.json' function getEnv(name: string) { @@ -12,11 +12,16 @@ function getEnv(name: string) { return value } +const v3Urls: Array = ['cloudfrontWithHeadersUrl', 'cloudfrontWithSecretsUrl'] +const v4Urls: Array = ['cloudfrontWithSecretsV4Url'] + async function main() { let hasError = false const cloudfrontUrls = getCloudfrontUrls() + const isV4Only = process.env.V4_ONLY === 'true' + const apiUrl = getEnv('API_URL') const behaviorPath = getEnv('FPJS_BEHAVIOR_PATH') const agentPath = getEnv('FPJS_AGENT_DOWNLOAD_PATH') @@ -25,7 +30,10 @@ async function main() { console.info('Agent download path:', agentPath) console.info('Get result path:', ingressPath) - for (const [name, url] of Object.entries(cloudfrontUrls)) { + const cloudfrontUrlsArray = Object.entries(cloudfrontUrls).filter(([name]) => + isV4Only ? v4Urls.includes(name as keyof CloudfrontUrls) : v3Urls.includes(name as keyof CloudfrontUrls) + ) + for (const [name, url] of cloudfrontUrlsArray) { if (name === 'cloudfrontWithoutVariables') { continue } @@ -44,10 +52,19 @@ async function main() { 'traffic-name': 'fingerprintjs-pro-cloudfront', 'integration-version': version, 'enable-new-tests': 'true', + } as Record + if (isV4Only) { + args['include'] = ['v4 agent', 'v4 browser cache', 'v4 ingress'] } const argsString = Object.entries(args) - .map(([key, value]) => `--${key}="${value}"`) + .flatMap(([key, value]) => { + if (typeof value === 'string') { + return `--${key}="${value}"` + } + + return value.map((v) => `--${key}="${v}"`) + }) .join(' ') execSync( diff --git a/e2e/tests/playwright.config.ts b/e2e/tests/playwright.config.ts index a605e7b0..45e0f0cf 100644 --- a/e2e/tests/playwright.config.ts +++ b/e2e/tests/playwright.config.ts @@ -1,7 +1,7 @@ import type { PlaywrightTestConfig } from '@playwright/test' import { devices } from '@playwright/test' import { getProjectName } from './src/project' -import { CloudfrontUrls, getCloudfrontUrls } from './src/utils/cloudfront' +import { CloudfrontUrls, getCloudfrontUrls, testMatches } from './src/utils/cloudfront' /** * Read environment variables from file. @@ -46,13 +46,19 @@ const config: PlaywrightTestConfig = { }, /* Configure projects for major browsers */ - projects: cloudfrontUrls.map(([name, url]) => ({ - name: getProjectName('chromium', name as keyof CloudfrontUrls), - use: { - ...devices['Desktop Chrome'], - baseURL: url, - }, - })), + projects: cloudfrontUrls.map(([name, url]) => { + const projectName = name as keyof CloudfrontUrls + const testMatch = testMatches[projectName] + + return { + name: getProjectName('chromium', projectName), + testMatch, + use: { + ...devices['Desktop Chrome'], + baseURL: url, + }, + } + }), /* Folder for test artifacts such as screenshots, videos, traces, etc. */ // outputDir: 'test-results/', diff --git a/e2e/tests/src/utils/cloudfront.ts b/e2e/tests/src/utils/cloudfront.ts index f4a2bf65..84fd77fb 100644 --- a/e2e/tests/src/utils/cloudfront.ts +++ b/e2e/tests/src/utils/cloudfront.ts @@ -1,14 +1,23 @@ import { wait } from './wait' import { readTerraformOutput } from './terraform' +import { PlaywrightTestConfig } from '@playwright/test' export type CloudfrontUrls = { cloudfrontWithHeadersUrl: string cloudfrontWithSecretsUrl: string + cloudfrontWithSecretsV4Url: string } +export const testMatches = { + cloudfrontWithHeadersUrl: '**/*.test.ts', + cloudfrontWithSecretsUrl: '**/*.test.ts', + cloudfrontWithSecretsV4Url: ['statusCheck.test.ts', 'v4/**/*.test.ts'], +} satisfies Record + export const urlTypeCustomerVariableSourceMap: Record = { cloudfrontWithHeadersUrl: 'HeaderCustomerVariables', cloudfrontWithSecretsUrl: 'SecretsManagerVariables', + cloudfrontWithSecretsV4Url: 'SecretsManagerVariables', } let cache: CloudfrontUrls | undefined @@ -17,16 +26,18 @@ function getCloudfrontUrlsFromEnv(): Partial { return { cloudfrontWithHeadersUrl: process.env.CLOUDFRONT_WITH_HEADERS_URL, cloudfrontWithSecretsUrl: process.env.CLOUDFRONT_WITH_SECRETS_URL, + cloudfrontWithSecretsV4Url: process.env.CLOUDFRONT_WITH_SECRETS_V4_URL, } } export function getCloudfrontUrls(): CloudfrontUrls { if (!cache) { const fromEnv = getCloudfrontUrlsFromEnv() - if (fromEnv.cloudfrontWithHeadersUrl && fromEnv.cloudfrontWithSecretsUrl) { + if (fromEnv.cloudfrontWithHeadersUrl && fromEnv.cloudfrontWithSecretsUrl && fromEnv.cloudfrontWithSecretsV4Url) { cache = { cloudfrontWithHeadersUrl: `https://${fromEnv.cloudfrontWithHeadersUrl}`, cloudfrontWithSecretsUrl: `https://${fromEnv.cloudfrontWithSecretsUrl}`, + cloudfrontWithSecretsV4Url: `https://${fromEnv.cloudfrontWithSecretsV4Url}`, } console.info('Using cloudfront urls from env', cache) } else { @@ -35,6 +46,7 @@ export function getCloudfrontUrls(): CloudfrontUrls { cache = { cloudfrontWithHeadersUrl: `https://${contents.cloudfront_with_headers_url.value}`, cloudfrontWithSecretsUrl: `https://${contents.cloudfront_with_secret_url.value}`, + cloudfrontWithSecretsV4Url: `https://${contents.cloudfront_with_secret_url_v4_only.value}`, } console.info('Using cloudfront urls from terraform output', cache) diff --git a/e2e/tests/src/utils/terraform.ts b/e2e/tests/src/utils/terraform.ts index 4ed803f3..1e7d7a56 100644 --- a/e2e/tests/src/utils/terraform.ts +++ b/e2e/tests/src/utils/terraform.ts @@ -9,6 +9,7 @@ export type TerraformOutputValue = { export type TerraformOutput = { cloudfront_with_headers_url: TerraformOutputValue cloudfront_with_secret_url: TerraformOutputValue + cloudfront_with_secret_url_v4_only: TerraformOutputValue } const FILE_NAME = 'infra.json' diff --git a/package.json b/package.json index c7646674..64bc22f4 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@fingerprint/aws-cloudfront-proxy", "version": "2.2.0-rc.1", - "description": "Fingerprint Pro CloudFront lambda@edge function", + "description": "Fingerprint CloudFront lambda@edge function", "author": "FingerprintJS, Inc (https://fingerprint.com)", "license": "MIT", "private": true, @@ -69,7 +69,8 @@ "rollup-plugin-license": "^3.6.0", "ts-jest": "^29.4.0", "tslib": "^2.8.1", - "typescript": "^5.7.3" + "typescript": "^5.7.3", + "ts-node": "^10.9.2" }, "lint-staged": { "*.ts": "pnpm run lint:fix", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3b141cd0..f3e6f72c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -95,7 +95,7 @@ importers: version: 9.1.7 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@20.19.1) + version: 29.7.0(@types/node@20.19.1)(ts-node@10.9.2(@types/node@20.19.1)(typescript@5.8.3)) jest-environment-jsdom: specifier: ^29.7.0 version: 29.7.0 @@ -119,7 +119,10 @@ importers: version: 3.6.0(picomatch@4.0.2)(rollup@4.44.0) ts-jest: specifier: ^29.4.0 - version: 29.4.0(@babel/core@7.27.4)(@jest/transform@30.0.2)(@jest/types@30.0.1)(babel-jest@30.0.2(@babel/core@7.27.4))(jest-util@30.0.2)(jest@29.7.0(@types/node@20.19.1))(typescript@5.8.3) + version: 29.4.0(@babel/core@7.27.4)(@jest/transform@30.0.2)(@jest/types@30.0.1)(babel-jest@30.0.2(@babel/core@7.27.4))(jest-util@30.0.2)(jest@29.7.0(@types/node@20.19.1)(ts-node@10.9.2(@types/node@20.19.1)(typescript@5.8.3)))(typescript@5.8.3) + ts-node: + specifier: ^10.9.2 + version: 10.9.2(@types/node@20.19.1)(typescript@5.8.3) tslib: specifier: ^2.8.1 version: 2.8.1 @@ -732,6 +735,10 @@ packages: resolution: {integrity: sha512-/yCrWGCoA1SVKOks25EGadP9Pnj0oAIHGpl2wH2M2Y46dPM2ueb8wyCVOD7O3WCTkaJ0IkKvzhl1JY7+uCT2Dw==} engines: {node: '>=v18'} + '@cspotcode/source-map-support@0.8.1': + resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} + engines: {node: '>=12'} + '@esbuild/aix-ppc64@0.25.2': resolution: {integrity: sha512-wCIboOL2yXZym2cgm6mlA742s9QeJ8DjGVaL39dLN4rRwrOgOyYSnOaFPhKZGLb2ngj4EyfAFjsNJwPXZvseag==} engines: {node: '>=18'} @@ -1083,6 +1090,9 @@ packages: '@jridgewell/trace-mapping@0.3.25': resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} + '@jridgewell/trace-mapping@0.3.9': + resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} + '@manypkg/find-root@1.1.0': resolution: {integrity: sha512-mki5uBvhHzO8kYYix/WRy2WX8S3B5wdVSc9D6KcU5lQNglP2yt58/VfLuAK49glRXChosY8ap2oJ1qgma3GUVA==} @@ -1202,56 +1212,67 @@ packages: resolution: {integrity: sha512-x+e/Z9H0RAWckn4V2OZZl6EmV0L2diuX3QB0uM1r6BvhUIv6xBPL5mrAX2E3e8N8rEHVPwFfz/ETUbV4oW9+lQ==} cpu: [arm] os: [linux] + libc: [glibc] '@rollup/rollup-linux-arm-musleabihf@4.44.0': resolution: {integrity: sha512-1exwiBFf4PU/8HvI8s80icyCcnAIB86MCBdst51fwFmH5dyeoWVPVgmQPcKrMtBQ0W5pAs7jBCWuRXgEpRzSCg==} cpu: [arm] os: [linux] + libc: [musl] '@rollup/rollup-linux-arm64-gnu@4.44.0': resolution: {integrity: sha512-ZTR2mxBHb4tK4wGf9b8SYg0Y6KQPjGpR4UWwTFdnmjB4qRtoATZ5dWn3KsDwGa5Z2ZBOE7K52L36J9LueKBdOQ==} cpu: [arm64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-arm64-musl@4.44.0': resolution: {integrity: sha512-GFWfAhVhWGd4r6UxmnKRTBwP1qmModHtd5gkraeW2G490BpFOZkFtem8yuX2NyafIP/mGpRJgTJ2PwohQkUY/Q==} cpu: [arm64] os: [linux] + libc: [musl] '@rollup/rollup-linux-loongarch64-gnu@4.44.0': resolution: {integrity: sha512-xw+FTGcov/ejdusVOqKgMGW3c4+AgqrfvzWEVXcNP6zq2ue+lsYUgJ+5Rtn/OTJf7e2CbgTFvzLW2j0YAtj0Gg==} cpu: [loong64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-powerpc64le-gnu@4.44.0': resolution: {integrity: sha512-bKGibTr9IdF0zr21kMvkZT4K6NV+jjRnBoVMt2uNMG0BYWm3qOVmYnXKzx7UhwrviKnmK46IKMByMgvpdQlyJQ==} cpu: [ppc64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-riscv64-gnu@4.44.0': resolution: {integrity: sha512-vV3cL48U5kDaKZtXrti12YRa7TyxgKAIDoYdqSIOMOFBXqFj2XbChHAtXquEn2+n78ciFgr4KIqEbydEGPxXgA==} cpu: [riscv64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-riscv64-musl@4.44.0': resolution: {integrity: sha512-TDKO8KlHJuvTEdfw5YYFBjhFts2TR0VpZsnLLSYmB7AaohJhM8ctDSdDnUGq77hUh4m/djRafw+9zQpkOanE2Q==} cpu: [riscv64] os: [linux] + libc: [musl] '@rollup/rollup-linux-s390x-gnu@4.44.0': resolution: {integrity: sha512-8541GEyktXaw4lvnGp9m84KENcxInhAt6vPWJ9RodsB/iGjHoMB2Pp5MVBCiKIRxrxzJhGCxmNzdu+oDQ7kwRA==} cpu: [s390x] os: [linux] + libc: [glibc] '@rollup/rollup-linux-x64-gnu@4.44.0': resolution: {integrity: sha512-iUVJc3c0o8l9Sa/qlDL2Z9UP92UZZW1+EmQ4xfjTc1akr0iUFZNfxrXJ/R1T90h/ILm9iXEY6+iPrmYB3pXKjw==} cpu: [x64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-x64-musl@4.44.0': resolution: {integrity: sha512-PQUobbhLTQT5yz/SPg116VJBgz+XOtXt8D1ck+sfJJhuEsMj2jSej5yTdp8CvWBSceu+WW+ibVL6dm0ptG5fcA==} cpu: [x64] os: [linux] + libc: [musl] '@rollup/rollup-win32-arm64-msvc@4.44.0': resolution: {integrity: sha512-M0CpcHf8TWn+4oTxJfh7LQuTuaYeXGbk0eageVjQCKzYLsajWS/lFC94qlRqOlyC2KvRT90ZrfXULYmukeIy7w==} @@ -1689,6 +1710,18 @@ packages: resolution: {integrity: sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==} engines: {node: '>= 10'} + '@tsconfig/node10@1.0.12': + resolution: {integrity: sha512-UCYBaeFvM11aU2y3YPZ//O5Rhj+xKyzy7mvcIoAjASbigy8mHMryP5cK7dgjlz2hWxh1g5pLw084E0a/wlUSFQ==} + + '@tsconfig/node12@1.0.11': + resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} + + '@tsconfig/node14@1.0.3': + resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==} + + '@tsconfig/node16@1.0.4': + resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==} + '@types/aws-lambda@8.10.160': resolution: {integrity: sha512-uoO4QVQNWFPJMh26pXtmtrRfGshPUSpMZGUyUQY20FhfHEElEBOPKgVmFs1z+kbpyBsRs2JnoOPT7++Z4GA9pA==} @@ -1857,11 +1890,6 @@ packages: resolution: {integrity: sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==} engines: {node: '>=0.4.0'} - acorn@8.11.3: - resolution: {integrity: sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==} - engines: {node: '>=0.4.0'} - hasBin: true - acorn@8.15.0: resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==} engines: {node: '>=0.4.0'} @@ -1924,6 +1952,9 @@ packages: resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} engines: {node: '>= 8'} + arg@4.1.3: + resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} + argparse@1.0.10: resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} @@ -2249,6 +2280,9 @@ packages: engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} hasBin: true + create-require@1.1.1: + resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} + cross-spawn@7.0.3: resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} engines: {node: '>= 8'} @@ -2341,6 +2375,10 @@ packages: resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + diff@4.0.4: + resolution: {integrity: sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ==} + engines: {node: '>=0.3.1'} + diff@5.2.0: resolution: {integrity: sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==} engines: {node: '>=0.3.1'} @@ -4031,6 +4069,20 @@ packages: jest-util: optional: true + ts-node@10.9.2: + resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==} + hasBin: true + peerDependencies: + '@swc/core': '>=1.2.50' + '@swc/wasm': '>=1.2.50' + '@types/node': '*' + typescript: '>=2.7' + peerDependenciesMeta: + '@swc/core': + optional: true + '@swc/wasm': + optional: true + tslib@2.8.1: resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} @@ -4104,6 +4156,9 @@ packages: resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==} hasBin: true + v8-compile-cache-lib@3.0.1: + resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} + v8-to-istanbul@9.3.0: resolution: {integrity: sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==} engines: {node: '>=10.12.0'} @@ -4245,6 +4300,10 @@ packages: resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} engines: {node: '>=12'} + yn@3.1.1: + resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} + engines: {node: '>=6'} + yocto-queue@0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} @@ -5653,6 +5712,10 @@ snapshots: '@types/conventional-commits-parser': 5.0.1 chalk: 5.4.1 + '@cspotcode/source-map-support@0.8.1': + dependencies: + '@jridgewell/trace-mapping': 0.3.9 + '@esbuild/aix-ppc64@0.25.2': optional: true @@ -5841,7 +5904,7 @@ snapshots: jest-util: 29.7.0 slash: 3.0.0 - '@jest/core@29.7.0': + '@jest/core@29.7.0(ts-node@10.9.2(@types/node@20.19.1)(typescript@5.8.3))': dependencies: '@jest/console': 29.7.0 '@jest/reporters': 29.7.0 @@ -5855,7 +5918,7 @@ snapshots: exit: 0.1.2 graceful-fs: 4.2.11 jest-changed-files: 29.7.0 - jest-config: 29.7.0(@types/node@20.19.1) + jest-config: 29.7.0(@types/node@20.19.1)(ts-node@10.9.2(@types/node@20.19.1)(typescript@5.8.3)) jest-haste-map: 29.7.0 jest-message-util: 29.7.0 jest-regex-util: 29.6.3 @@ -6065,6 +6128,11 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.0 + '@jridgewell/trace-mapping@0.3.9': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.0 + '@manypkg/find-root@1.1.0': dependencies: '@babel/runtime': 7.28.6 @@ -6866,6 +6934,14 @@ snapshots: '@tootallnate/once@2.0.0': {} + '@tsconfig/node10@1.0.12': {} + + '@tsconfig/node12@1.0.11': {} + + '@tsconfig/node14@1.0.3': {} + + '@tsconfig/node16@1.0.4': {} + '@types/aws-lambda@8.10.160': {} '@types/babel__core@7.20.5': @@ -7069,16 +7145,14 @@ snapshots: acorn: 8.15.0 acorn-walk: 8.3.4 - acorn-jsx@5.3.2(acorn@8.11.3): + acorn-jsx@5.3.2(acorn@8.15.0): dependencies: - acorn: 8.11.3 + acorn: 8.15.0 acorn-walk@8.3.4: dependencies: acorn: 8.15.0 - acorn@8.11.3: {} - acorn@8.15.0: {} adm-zip@0.5.16: {} @@ -7142,6 +7216,8 @@ snapshots: normalize-path: 3.0.0 picomatch: 2.3.1 + arg@4.1.3: {} + argparse@1.0.10: dependencies: sprintf-js: 1.0.3 @@ -7500,13 +7576,13 @@ snapshots: optionalDependencies: typescript: 5.8.3 - create-jest@29.7.0(@types/node@20.19.1): + create-jest@29.7.0(@types/node@20.19.1)(ts-node@10.9.2(@types/node@20.19.1)(typescript@5.8.3)): dependencies: '@jest/types': 29.6.3 chalk: 4.1.2 exit: 0.1.2 graceful-fs: 4.2.11 - jest-config: 29.7.0(@types/node@20.19.1) + jest-config: 29.7.0(@types/node@20.19.1)(ts-node@10.9.2(@types/node@20.19.1)(typescript@5.8.3)) jest-util: 29.7.0 prompts: 2.4.2 transitivePeerDependencies: @@ -7515,6 +7591,8 @@ snapshots: - supports-color - ts-node + create-require@1.1.1: {} + cross-spawn@7.0.3: dependencies: path-key: 3.1.1 @@ -7589,6 +7667,8 @@ snapshots: diff-sequences@29.6.3: {} + diff@4.0.4: {} + diff@5.2.0: {} dir-glob@3.0.1: @@ -7771,8 +7851,8 @@ snapshots: espree@9.6.1: dependencies: - acorn: 8.11.3 - acorn-jsx: 5.3.2(acorn@8.11.3) + acorn: 8.15.0 + acorn-jsx: 5.3.2(acorn@8.15.0) eslint-visitor-keys: 3.4.3 esprima@4.0.1: {} @@ -8321,16 +8401,16 @@ snapshots: - babel-plugin-macros - supports-color - jest-cli@29.7.0(@types/node@20.19.1): + jest-cli@29.7.0(@types/node@20.19.1)(ts-node@10.9.2(@types/node@20.19.1)(typescript@5.8.3)): dependencies: - '@jest/core': 29.7.0 + '@jest/core': 29.7.0(ts-node@10.9.2(@types/node@20.19.1)(typescript@5.8.3)) '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 chalk: 4.1.2 - create-jest: 29.7.0(@types/node@20.19.1) + create-jest: 29.7.0(@types/node@20.19.1)(ts-node@10.9.2(@types/node@20.19.1)(typescript@5.8.3)) exit: 0.1.2 import-local: 3.2.0 - jest-config: 29.7.0(@types/node@20.19.1) + jest-config: 29.7.0(@types/node@20.19.1)(ts-node@10.9.2(@types/node@20.19.1)(typescript@5.8.3)) jest-util: 29.7.0 jest-validate: 29.7.0 yargs: 17.7.2 @@ -8340,7 +8420,7 @@ snapshots: - supports-color - ts-node - jest-config@29.7.0(@types/node@20.19.1): + jest-config@29.7.0(@types/node@20.19.1)(ts-node@10.9.2(@types/node@20.19.1)(typescript@5.8.3)): dependencies: '@babel/core': 7.27.4 '@jest/test-sequencer': 29.7.0 @@ -8366,6 +8446,7 @@ snapshots: strip-json-comments: 3.1.1 optionalDependencies: '@types/node': 20.19.1 + ts-node: 10.9.2(@types/node@20.19.1)(typescript@5.8.3) transitivePeerDependencies: - babel-plugin-macros - supports-color @@ -8668,12 +8749,12 @@ snapshots: supports-color: 8.1.1 optional: true - jest@29.7.0(@types/node@20.19.1): + jest@29.7.0(@types/node@20.19.1)(ts-node@10.9.2(@types/node@20.19.1)(typescript@5.8.3)): dependencies: - '@jest/core': 29.7.0 + '@jest/core': 29.7.0(ts-node@10.9.2(@types/node@20.19.1)(typescript@5.8.3)) '@jest/types': 29.6.3 import-local: 3.2.0 - jest-cli: 29.7.0(@types/node@20.19.1) + jest-cli: 29.7.0(@types/node@20.19.1)(ts-node@10.9.2(@types/node@20.19.1)(typescript@5.8.3)) transitivePeerDependencies: - '@types/node' - babel-plugin-macros @@ -9504,12 +9585,12 @@ snapshots: dependencies: typescript: 5.8.3 - ts-jest@29.4.0(@babel/core@7.27.4)(@jest/transform@30.0.2)(@jest/types@30.0.1)(babel-jest@30.0.2(@babel/core@7.27.4))(jest-util@30.0.2)(jest@29.7.0(@types/node@20.19.1))(typescript@5.8.3): + ts-jest@29.4.0(@babel/core@7.27.4)(@jest/transform@30.0.2)(@jest/types@30.0.1)(babel-jest@30.0.2(@babel/core@7.27.4))(jest-util@30.0.2)(jest@29.7.0(@types/node@20.19.1)(ts-node@10.9.2(@types/node@20.19.1)(typescript@5.8.3)))(typescript@5.8.3): dependencies: bs-logger: 0.2.6 ejs: 3.1.10 fast-json-stable-stringify: 2.1.0 - jest: 29.7.0(@types/node@20.19.1) + jest: 29.7.0(@types/node@20.19.1)(ts-node@10.9.2(@types/node@20.19.1)(typescript@5.8.3)) json5: 2.2.3 lodash.memoize: 4.1.2 make-error: 1.3.6 @@ -9524,6 +9605,24 @@ snapshots: babel-jest: 30.0.2(@babel/core@7.27.4) jest-util: 30.0.2 + ts-node@10.9.2(@types/node@20.19.1)(typescript@5.8.3): + dependencies: + '@cspotcode/source-map-support': 0.8.1 + '@tsconfig/node10': 1.0.12 + '@tsconfig/node12': 1.0.11 + '@tsconfig/node14': 1.0.3 + '@tsconfig/node16': 1.0.4 + '@types/node': 20.19.1 + acorn: 8.15.0 + acorn-walk: 8.3.4 + arg: 4.1.3 + create-require: 1.1.1 + diff: 4.0.4 + make-error: 1.3.6 + typescript: 5.8.3 + v8-compile-cache-lib: 3.0.1 + yn: 3.1.1 + tslib@2.8.1: {} type-check@0.4.0: @@ -9574,6 +9673,8 @@ snapshots: uuid@9.0.1: {} + v8-compile-cache-lib@3.0.1: {} + v8-to-istanbul@9.3.0: dependencies: '@jridgewell/trace-mapping': 0.3.25 @@ -9675,6 +9776,8 @@ snapshots: y18n: 5.0.8 yargs-parser: 21.1.1 + yn@3.1.1: {} + yocto-queue@0.1.0: {} yocto-queue@1.2.1: {} diff --git a/proxy/app.ts b/proxy/app.ts index 568a69a0..380e873a 100644 --- a/proxy/app.ts +++ b/proxy/app.ts @@ -21,21 +21,28 @@ export type Route = { async function createRoutes(customerVariables: CustomerVariables): Promise { const routes: Route[] = [] - const downloadScriptRoute: Route = { - pathPattern: createRoute(await getAgentUri(customerVariables)), - handler: createIngressHandler('agentV3'), + + const agentUri = await getAgentUri(customerVariables) + if (agentUri) { + routes.push({ + pathPattern: createRoute(agentUri), + handler: createIngressHandler('agentV3'), + }) } - const ingressAPIRoute: Route = { - pathPattern: createRoute(await getResultUri(customerVariables)), - handler: createIngressHandler('ingressV3'), + + const resultUri = await getResultUri(customerVariables) + if (resultUri) { + routes.push({ + pathPattern: createRoute(resultUri), + handler: createIngressHandler('ingressV3'), + }) } + const statusRoute: Route = { pathPattern: createRoute(getStatusUri()), handler: (request, env) => handleStatusPage(request, env), } - routes.push(downloadScriptRoute) - routes.push(ingressAPIRoute) routes.push(statusRoute) // For V4, proxy all remaining routes through Warden (CDN + Ingress) routes.push({ diff --git a/proxy/test/handlers/__snapshots__/handleStatus.test.ts.snap b/proxy/test/handlers/__snapshots__/handleStatus.test.ts.snap index 79ef3a93..23c75a00 100644 --- a/proxy/test/handlers/__snapshots__/handleStatus.test.ts.snap +++ b/proxy/test/handlers/__snapshots__/handleStatus.test.ts.snap @@ -505,9 +505,9 @@ exports[`Handle status returns correct status info in html if some variables are
  • fpjs_pre_shared_secret - ⚠️ Value is not defined
  • - fpjs_get_result_path V3 only - ⚠️ Value is not defined and uses default value: resultId + fpjs_get_result_path V3 only - ⚠️ Value is not defined
  • - fpjs_agent_download_path V3 only - ⚠️ Value is not defined and uses default value: agent + fpjs_agent_download_path V3 only - ⚠️ Value is not defined
  • diff --git a/proxy/test/utils/customer-variables/selectors.test.ts b/proxy/test/utils/customer-variables/selectors.test.ts index 73ff7e45..5ba67979 100644 --- a/proxy/test/utils/customer-variables/selectors.test.ts +++ b/proxy/test/utils/customer-variables/selectors.test.ts @@ -129,8 +129,8 @@ describe('customer variables selectors', () => { const customerVariables = getHeaderCustomerVariables(req) - expect(await getAgentUri(customerVariables)).toBe('/agent') - expect(await getResultUri(customerVariables)).toBe('/resultId(/.*)?') + expect(await getAgentUri(customerVariables)).toBeNull() + expect(await getResultUri(customerVariables)).toBeNull() expect(getStatusUri()).toBe('/status') }) }) diff --git a/proxy/utils/customer-variables/defaults.ts b/proxy/utils/customer-variables/defaults.ts index 0a17d504..aab230fa 100644 --- a/proxy/utils/customer-variables/defaults.ts +++ b/proxy/utils/customer-variables/defaults.ts @@ -1,9 +1,9 @@ import { CustomerVariableName, CustomerVariablesRecord, CustomerVariableType } from './types' const defaultCustomerVariables = { - [CustomerVariableName.GetResultPath]: 'resultId', + [CustomerVariableName.GetResultPath]: null, [CustomerVariableName.PreSharedSecret]: null, - [CustomerVariableName.AgentDownloadPath]: 'agent', + [CustomerVariableName.AgentDownloadPath]: null, [CustomerVariableName.FpCdnUrl]: '__FPCDN__', [CustomerVariableName.FpIngressBaseHost]: '__INGRESS_API__', [CustomerVariableName.BehaviorPathNestLevel]: 1, diff --git a/proxy/utils/customer-variables/selectors.ts b/proxy/utils/customer-variables/selectors.ts index f0e6e26e..9667bc57 100644 --- a/proxy/utils/customer-variables/selectors.ts +++ b/proxy/utils/customer-variables/selectors.ts @@ -3,9 +3,17 @@ import { CustomerVariableName } from './types' const extractVariable = (result: GetVariableResult) => result.value -export const getAgentUri = async (variables: CustomerVariables) => `/${await getAgentDownloadPath(variables)}` +export const getAgentUri = async (variables: CustomerVariables) => { + const agentDownloadPath = await getAgentDownloadPath(variables) -export const getResultUri = async (variables: CustomerVariables) => `/${await getResultPath(variables)}(/.*)?` + return agentDownloadPath ? `/${agentDownloadPath}` : null +} + +export const getResultUri = async (variables: CustomerVariables) => { + const resultPath = await getResultPath(variables) + + return resultPath ? `/${resultPath}(/.*)?` : null +} export const getStatusUri = () => `/status`