Skip to content

Commit

Permalink
Merge pull request #165 from fingerprintjs/rc
Browse files Browse the repository at this point in the history
Release v1.3.3-rc.1
  • Loading branch information
ilfa authored Dec 13, 2023
2 parents ed58e59 + 7d127f6 commit 49d9bb8
Show file tree
Hide file tree
Showing 15 changed files with 168 additions and 78 deletions.
45 changes: 7 additions & 38 deletions .github/workflows/coverage-report.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,41 +6,10 @@ on:
- main

jobs:
build-and-run-tests:
runs-on: ubuntu-20.04
name: Build & run tests & publish coverage
steps:
- uses: actions/checkout@v3

- name: Install node
uses: actions/setup-node@v3
with:
node-version-file: '.node-version'
- name: Get yarn cache directory path
id: yarn-cache-dir-path
run: echo "dir=$(yarn cache dir)" >> $GITHUB_OUTPUT
- uses: actions/cache@v3
id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`)
with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-
- name: Install Dependencies and prepare packages
run: yarn install
env:
CI: true
- name: Run test
run: yarn test:coverage

- name: Create Coverage Badges
uses: jaywcjlove/coverage-badges-cli@e07f25709cd25486855c1ba1b26da53576ff3620
with:
source: coverage/coverage-summary.json
output: coverage/lcov-report/badges.svg

- name: Deploy
uses: JamesIves/github-pages-deploy-action@8817a56e5bfec6e2b08345c81f4d422db53a2cdc
with:
branch: gh-pages
folder: ./coverage/lcov-report/
generate-docs-and-coverage:
name: Generate docs and coverage report
uses: fingerprintjs/dx-team-toolkit/.github/workflows/docs-and-coverage.yml@v1
with:
skip-docs-step: true
prepare-gh-pages-commands: |
mv coverage/lcov-report/* ./gh-pages/
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
## [1.3.3-rc.1](https://github.com/fingerprintjs/fingerprint-pro-cloudfront-integration/compare/v1.3.2...v1.3.3-rc.1) (2023-12-13)


### Bug Fixes

* add types for parameter extraction functions ([d84aaeb](https://github.com/fingerprintjs/fingerprint-pro-cloudfront-integration/commit/d84aaeb50bb61b44116b359a46f4227727e728c7))
* improve endpoint creation ([006c91b](https://github.com/fingerprintjs/fingerprint-pro-cloudfront-integration/commit/006c91b594c41fe4fb85a143496d4738aaf06793))

## [1.3.2](https://github.com/fingerprintjs/fingerprint-pro-cloudfront-integration/compare/v1.3.1...v1.3.2) (2023-12-04)


Expand Down
17 changes: 5 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,11 @@
</picture>
</a>
<p align="center">
<a href="https://github.com/fingerprintjs/fingerprint-pro-cloudfront-integration">
<img src="https://img.shields.io/github/v/release/fingerprintjs/fingerprint-pro-cloudfront-integration" alt="Current version">
</a>
<a href="https://fingerprintjs.github.io/fingerprint-pro-cloudfront-integration">
<img src="https://fingerprintjs.github.io/fingerprint-pro-cloudfront-integration/badges.svg" alt="coverage">
</a>
<a href="https://opensource.org/licenses/MIT">
<img src="https://img.shields.io/:license-mit-blue.svg" alt="MIT license">
</a>
<a href="https://discord.gg/39EpE2neBg">
<img src="https://img.shields.io/discord/852099967190433792?style=logo&label=Discord&logo=Discord&logoColor=white" alt="Discord server">
</a>
<a href="https://github.com/fingerprintjs/fingerprint-pro-cloudfront-integration"><img src="https://img.shields.io/github/v/release/fingerprintjs/fingerprint-pro-cloudfront-integration" alt="Current version"></a>
<a href="https://fingerprintjs.github.io/fingerprint-pro-cloudfront-integration"><img src="https://fingerprintjs.github.io/fingerprint-pro-cloudfront-integration/badges.svg" alt="coverage"></a>
<a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/:license-mit-blue.svg" alt="MIT license"></a>
<a href="https://discord.gg/39EpE2neBg"><img src="https://img.shields.io/discord/852099967190433792?style=logo&label=Discord&logo=Discord&logoColor=white" alt="Discord server"></a>
</p>

# Fingerprint Pro CloudFront Integration

Expand Down
2 changes: 1 addition & 1 deletion jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ module.exports = {
testEnvironment: 'node',
testRegex: '/test/.+test.tsx?$',
passWithNoTests: true,
collectCoverageFrom: ['./src/**/**.ts', '!**/handlers/**.ts', '!**/model/**.ts', '!./src/app.ts', '!**/index.ts'],
collectCoverageFrom: ['./proxy/**/**.ts', '!**/handlers/**.ts', '!**/model/**.ts', '!./proxy/app.ts', '!**/index.ts'],
coverageReporters: ['lcov', 'json-summary', ['text', { file: 'coverage.txt', path: './' }]],
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@fingerprintjs/fingerprint-pro-cloudfront-lambda-function",
"version": "1.3.2",
"version": "1.3.3-rc.1",
"description": "Fingerprint Pro CloudFront lambda@edge function",
"author": "FingerprintJS, Inc (https://fingerprint.com)",
"license": "MIT",
Expand Down
3 changes: 3 additions & 0 deletions proxy/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ export const handler = async (event: CloudFrontRequestEvent): Promise<CloudFront
if (resultPathMatches && resultPathMatches.length >= 1) {
suffix = resultPathMatches[1] ?? ''
}
if (suffix.length > 0 && !suffix.startsWith('/')) {
suffix = '/' + suffix
}
const eTLDPlusOneDomain = getEffectiveTLDPlusOne(getHost(request))
return handleResult({
region: getRegion(request, logger),
Expand Down
9 changes: 7 additions & 2 deletions proxy/handlers/handleResult.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { ResultOptions } from '../model'
import { CloudFrontResultResponse } from 'aws-lambda'
import https from 'https'
import { Region } from '../model'

import { updateResponseHeaders, addTrafficMonitoringSearchParamsForVisitorIdRequest } from '../utils'

Expand All @@ -13,8 +14,12 @@ export function handleResult(options: ResultOptions): Promise<CloudFrontResultRe
const url = new URL(getIngressAPIHost(options.region) + options.suffix)
decodeURIComponent(options.querystring)
.split('&')
.filter((it) => it.includes('='))
.forEach((it) => {
const kv = it.split('=')
if (kv[0] === 'region') {
kv[1] = options.region
}
url.searchParams.append(kv[0], kv[1])
})
addTrafficMonitoringSearchParamsForVisitorIdRequest(url)
Expand Down Expand Up @@ -98,7 +103,7 @@ function generateRequestUniqueId(): string {
return generateRandomString(2)
}

function getIngressAPIHost(region: string): string {
const prefix = region === 'us' ? '' : `${region}.`
function getIngressAPIHost(region: Region): string {
const prefix = region === Region.us ? '' : `${region}.`
return `https://${prefix}__INGRESS_API__`
}
5 changes: 5 additions & 0 deletions proxy/model/Region.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export enum Region {
us = 'us',
eu = 'eu',
ap = 'ap',
}
3 changes: 2 additions & 1 deletion proxy/model/ResultOptions.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { OutgoingHttpHeaders } from 'http'
import { Logger } from '../logger'
import { Region } from './'

export interface ResultOptions {
region: string
region: Region
querystring: string
method: string
headers: OutgoingHttpHeaders
Expand Down
3 changes: 2 additions & 1 deletion proxy/model/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { AgentOptions } from './AgentOptions'
import { ResultOptions } from './ResultOptions'
import { Region } from './Region'

export { AgentOptions, ResultOptions }
export { AgentOptions, ResultOptions, Region }
8 changes: 6 additions & 2 deletions proxy/test/aws.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,14 @@ export function getMockSecretsManager() {
}
}

export const mockRequest = (uri: string, querystring = 'apiKey=ujKG34hUYKLJKJ1F&version=3&loaderVersion=3.6.2') => {
export const mockRequest = (
uri: string,
querystring = 'apiKey=ujKG34hUYKLJKJ1F&version=3&loaderVersion=3.6.2',
method = 'POST',
) => {
return {
clientIp: '1.1.1.1',
method: 'GET',
method: method,
uri,
querystring,
headers: {
Expand Down
84 changes: 84 additions & 0 deletions proxy/test/handlers/handleResult.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,90 @@ describe('Result Endpoint', function () {
)
})

test('Call with wrong region', async () => {
const queryString = 'apiKey=ujKG34hUYKLJKJ1F&version=3&loaderVersion=3.6.2'
const request = mockRequest('/behavior/result', queryString)
request.querystring = `${request.querystring}&region=bar.baz/foo`
const event = mockEvent(request)

await handler(event)

expect(handleResult).toHaveBeenCalledTimes(1)
expect(https.request).toHaveBeenCalledWith(
new URL(`https://${origin}/${queryStringWithRegion('us')}`),
expect.anything(),
expect.anything(),
)
})

test('Invalid query parameters', async () => {
const queryString = 'apiKey=foo.bar/baz&version=bar.foo/baz&loaderVersion=baz.bar/foo'
const queryStringWithUSRegion =
'?apiKey=foo.bar%2Fbaz&version=bar.foo%2Fbaz&loaderVersion=baz.bar%2Ffoo&ii=fingerprintjs-pro-cloudfront%2F__lambda_func_version__%2Fingress'
const request = mockRequest('/behavior/result', queryString)
request.querystring = `${request.querystring}`
const event = mockEvent(request)

await handler(event)

expect(handleResult).toHaveBeenCalledTimes(1)
expect(https.request).toHaveBeenCalledWith(
new URL(`https://${origin}/${queryStringWithUSRegion}`),
expect.anything(),
expect.anything(),
)
})

test('Suffix with dot', async () => {
const suffix = '.suffix/more/path'
const iiParam = 'ii=fingerprintjs-pro-cloudfront%2F__lambda_func_version__%2Fingress'
const request = mockRequest(`/behavior/result/${suffix}`, '')
const event = mockEvent(request)

await handler(event)

expect(handleResult).toHaveBeenCalledTimes(1)
expect(https.request).toHaveBeenCalledWith(
new URL(`https://${origin}/${suffix}?${iiParam}`),
expect.anything(),
expect.anything(),
)
})

test('Invalid query parameters, GET request', async () => {
const queryString = 'apiKey=foo.bar/baz&version=bar.foo/baz&loaderVersion=baz.bar/foo'
const queryStringWithUSRegion =
'?apiKey=foo.bar%2Fbaz&version=bar.foo%2Fbaz&loaderVersion=baz.bar%2Ffoo&ii=fingerprintjs-pro-cloudfront%2F__lambda_func_version__%2Fingress'
const request = mockRequest('/behavior/result', queryString, 'GET')
request.querystring = `${request.querystring}`
const event = mockEvent(request)

await handler(event)

expect(handleResult).toHaveBeenCalledTimes(1)
expect(https.request).toHaveBeenCalledWith(
new URL(`https://${origin}/${queryStringWithUSRegion}`),
expect.anything(),
expect.anything(),
)
})

test('Suffix with dot, GET request', async () => {
const suffix = '.suffix/more/path'
const iiParam = 'ii=fingerprintjs-pro-cloudfront%2F__lambda_func_version__%2Fingress'
const request = mockRequest(`/behavior/result/${suffix}`, '', 'GET')
const event = mockEvent(request)

await handler(event)

expect(handleResult).toHaveBeenCalledTimes(1)
expect(https.request).toHaveBeenCalledWith(
new URL(`https://${origin}/${suffix}?${iiParam}`),
expect.anything(),
expect.anything(),
)
})

test('Call without suffix', async () => {
const event = mockEvent(mockRequest('/behavior/result'))
await handler(event)
Expand Down
11 changes: 11 additions & 0 deletions proxy/test/utils/request.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,4 +74,15 @@ describe('region', () => {
}
expect(getRegion(req, logger)).toBe('eu')
})

test('wrong region', () => {
const req: CloudFrontRequest = {
clientIp: '1.1.1.1',
method: 'GET',
uri: 'fpjs/agent',
querystring: 'apiKey=ujKG34hUYKLJKJ1F&version=3&loaderVersion=3.6.2&region=bar.baz/foo',
headers: {},
}
expect(getRegion(req, logger)).toBe('us')
})
})
16 changes: 11 additions & 5 deletions proxy/utils/request.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,25 @@
import { CloudFrontRequest } from 'aws-lambda'
import { Logger } from '../logger'
import { Region } from '../model'

export const getApiKey = (request: CloudFrontRequest, logger: Logger) => getQueryParameter(request, 'apiKey', logger)
export const getApiKey = (request: CloudFrontRequest, logger: Logger): string | undefined =>
getQueryParameter(request, 'apiKey', logger)

export const getVersion = (request: CloudFrontRequest, logger: Logger) => {
export const getVersion = (request: CloudFrontRequest, logger: Logger): string => {
const version = getQueryParameter(request, 'version', logger)
return version === undefined ? '3' : version
}

export const getLoaderVersion = (request: CloudFrontRequest, logger: Logger) =>
export const getLoaderVersion = (request: CloudFrontRequest, logger: Logger): string | undefined =>
getQueryParameter(request, 'loaderVersion', logger)

export const getRegion = (request: CloudFrontRequest, logger: Logger) => {
export const getRegion = (request: CloudFrontRequest, logger: Logger): Region => {
const value = getQueryParameter(request, 'region', logger)
return value === undefined ? 'us' : value
if (!value || !(value in Region)) {
return Region.us
}

return value as Region
}

function getQueryParameter(request: CloudFrontRequest, key: string, logger: Logger): string | undefined {
Expand Down
Loading

0 comments on commit 49d9bb8

Please sign in to comment.