Skip to content

Commit abb1875

Browse files
committed
Add mtls support.
1 parent 6274b30 commit abb1875

File tree

7 files changed

+106
-18
lines changed

7 files changed

+106
-18
lines changed

src/__tests__/getMtlsFetch.test.js

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/*
2+
Copyright 2025 Adobe. All rights reserved.
3+
This file is licensed to you under the Apache License, Version 2.0 (the "License");
4+
you may not use this file except in compliance with the License. You may obtain a copy
5+
of the License at http://www.apache.org/licenses/LICENSE-2.0
6+
Unless required by applicable law or agreed to in writing, software distributed under
7+
the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
8+
OF ANY KIND, either express or implied. See the License for the specific language
9+
governing permissions and limitations under the License.
10+
*/
11+
12+
import { describe, it, expect, vi, beforeEach } from 'vitest';
13+
import getMtlsFetch from '../getMtlsFetch.js';
14+
import { MTLS_BINDING } from '../constants.js';
15+
16+
describe('getMtlsFetch', () => {
17+
let mockEnv;
18+
let mockFetch;
19+
20+
beforeEach(() => {
21+
mockFetch = vi.fn();
22+
mockEnv = {};
23+
});
24+
25+
it('should return the MTLS fetch function when the binding exists', () => {
26+
// Arrange
27+
mockEnv[MTLS_BINDING] = { fetch: mockFetch };
28+
29+
// Act
30+
const result = getMtlsFetch(mockEnv);
31+
32+
// Assert
33+
expect(result).toBe(mockFetch);
34+
});
35+
36+
it('should return a function that throws an error when the binding does not exist', () => {
37+
// Arrange
38+
mockEnv = {}; // Empty env without MTLS binding
39+
40+
// Act
41+
const result = getMtlsFetch(mockEnv);
42+
43+
// Assert
44+
expect(() => result()).toThrowError(
45+
'MTLS certificate not found on the worker'
46+
);
47+
});
48+
49+
it('should handle undefined env gracefully', () => {
50+
// Act
51+
const result = getMtlsFetch(undefined);
52+
53+
// Assert
54+
expect(result).toBeInstanceOf(Function);
55+
expect(() => result()).toThrowError(
56+
'MTLS certificate not found on the worker'
57+
);
58+
});
59+
});

src/__tests__/index.test.js

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,16 @@ describe('index', () => {
3333
request: { header: {}, body: { xdm: {}, data: {} } }
3434
};
3535

36-
const execute = index.initialize(containerInitFunction, {
37-
fetch: globalFetch
38-
});
36+
const execute = index.initialize(containerInitFunction);
3937

40-
return execute(callData, {
41-
headersForSubrequests: {}
42-
}).then((result) => {
38+
return execute(
39+
callData,
40+
{},
41+
{
42+
headersForSubrequests: {},
43+
fetch: globalFetch
44+
}
45+
).then((result) => {
4346
expect(result).toStrictEqual([
4447
{
4548
ruleId: 'RLbb1d94c79fee4733a510564a86ba3c59',

src/constants.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,4 @@ governing permissions and limitations under the License.
1111

1212
export const CORE = 'core';
1313
export const PROMISE_TIMEOUT = 30000;
14+
export const MTLS_BINDING = 'ADOBE_MTLS_CERTIFICATE';

src/executeRules.js

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,14 @@ import logRuleStarting from './rules/logRuleStarting.js';
1717
import logRuleEnding from './rules/logRuleEnding.js';
1818
import returnRuleResult from './rules/returnRuleResult.js';
1919
import createPromiseChain from './rules/createPromiseChain.js';
20+
import getMtlsFetch from './getMtlsFetch.js';
2021

2122
export default (
2223
moduleProvider,
2324
container,
24-
globalFetch,
2525
requestData,
2626
env,
27-
{ headersForSubrequests } = {}
27+
{ headersForSubrequests, fetch: globalFetch } = {}
2828
) => {
2929
const rulePromises = [];
3030

@@ -53,11 +53,19 @@ export default (
5353
logger
5454
);
5555

56+
const mtlsFetch = getRuleFetchFn(
57+
getMtlsFetch(env),
58+
getHeaderOverrides(env),
59+
headersForSubrequests,
60+
logger
61+
);
62+
5663
const utils = {
5764
getRule: () => ({ id, name }),
5865
getBuildInfo: () => buildInfo,
5966
logger,
60-
fetch
67+
fetch,
68+
mtlsFetch
6169
};
6270

6371
const initialContext = {

src/getMtlsFetch.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/*
2+
Copyright 2025 Adobe. All rights reserved.
3+
This file is licensed to you under the Apache License, Version 2.0 (the "License");
4+
you may not use this file except in compliance with the License. You may obtain a copy
5+
of the License at http://www.apache.org/licenses/LICENSE-2.0
6+
Unless required by applicable law or agreed to in writing, software distributed under
7+
the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
8+
OF ANY KIND, either express or implied. See the License for the specific language
9+
governing permissions and limitations under the License.
10+
*/
11+
12+
import { MTLS_BINDING } from './constants.js';
13+
14+
export default (env) => {
15+
if (env && env[MTLS_BINDING]) {
16+
return env[MTLS_BINDING].fetch;
17+
}
18+
19+
return () => {
20+
throw new Error('MTLS certificate not found on the worker');
21+
};
22+
};

src/getRuleFetchFn.js

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,7 @@ governing permissions and limitations under the License.
1212
const byteArrayToString = (buf) =>
1313
new TextDecoder('utf-8').decode(new Uint8Array(buf));
1414

15-
export default (
16-
globalFetch,
17-
headerOverrides,
18-
headersForSubrequests,
19-
logger
20-
) => {
15+
export default (fetch, headerOverrides, headersForSubrequests, logger) => {
2116
return (resource, init = {}) => {
2217
// If resource is not a string then it must be a Request object and we
2318
// need to read it's headers. Otherwise the Request headers will be
@@ -50,7 +45,7 @@ export default (
5045
}
5146
});
5247

53-
return globalFetch(resource, init).then(
48+
return fetch(resource, init).then(
5449
(r) => {
5550
// Below we will read the body of the response. The body can be read only once.
5651
// We are cloning the response and sending it down to the actions so in case

src/index.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,14 @@ const getDataElementValue = createGetDataElementValue(
2929

3030
const getDataElementValues = createGetDataElementValues(getDataElementValue);
3131

32-
const initialize = (containerInitFunction, { fetch }) => {
32+
const initialize = (containerInitFunction) => {
3333
const container = containerInitFunction(getDataElementValues);
3434
if (container.dataElements) {
3535
dataElements = container.dataElements;
3636
}
3737

3838
moduleProvider.registerModules(container.modules, container.extensions);
39-
return executeRules.bind(null, moduleProvider, container, fetch);
39+
return executeRules.bind(null, moduleProvider, container);
4040
};
4141

4242
export default {

0 commit comments

Comments
 (0)