Skip to content

Commit 6be415a

Browse files
authored
feat: add function name to context and event headers (#624)
1 parent 0b92623 commit 6be415a

File tree

7 files changed

+55
-7
lines changed

7 files changed

+55
-7
lines changed

.nvmrc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
16.14.2
1+
lts/gallium

README.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,3 +107,25 @@ custom:
107107
interval: 500,
108108
debounce: 750
109109
```
110+
111+
### Options
112+
113+
#### `--headersFile`
114+
115+
Default: _undefined_
116+
117+
CloudFront [injects some headers](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/using-cloudfront-headers.html) into the request. You can set these by creating a JSON file and passing its path as an option.
118+
119+
Example:
120+
121+
```json
122+
// .cf-headers.json
123+
{
124+
"CloudFront-Viewer-Country": "us",
125+
"CloudFront-Viewer-Country-Region": "tx"
126+
}
127+
```
128+
129+
```bash
130+
npx serverless offline start --headersFile .cf-headers.json
131+
```

src/behavior-router.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ export class BehaviorRouter {
3535

3636
private cacheDir: string;
3737
private fileDir: string;
38+
private injectedHeadersFile?: string;
3839
private path: string;
3940

4041
private started: boolean = false;
@@ -56,6 +57,7 @@ export class BehaviorRouter {
5657
this.cfResources = serverless.service?.resources?.Resources || {};
5758
this.cacheDir = path.resolve(options.cacheDir || path.join(os.tmpdir(), 'edge-lambda'));
5859
this.fileDir = path.resolve(options.fileDir || path.join(os.tmpdir(), 'edge-lambda'));
60+
this.injectedHeadersFile = options.headersFile ? path.resolve(options.headersFile) : undefined;
5961
this.path = this.serverless.service.custom.offlineEdgeLambda.path || '';
6062

6163
fs.mkdirpSync(this.cacheDir);
@@ -176,11 +178,15 @@ export class BehaviorRouter {
176178
getOriginFromCfDistribution(handler.pattern, this.cfResources[handler.distribution]) :
177179
null;
178180

179-
const cfEvent = convertToCloudFrontEvent(req, this.builder('viewer-request'));
181+
const cfEvent = convertToCloudFrontEvent(req, this.builder('viewer-request'), this.injectedHeadersFile);
180182

181183
try {
184+
const context = {
185+
...this.context,
186+
functionName: handler.name,
187+
};
182188
const lifecycle = new CloudFrontLifecycle(this.serverless, this.options, cfEvent,
183-
this.context, this.cacheService, handler, customOrigin);
189+
context, this.cacheService, handler, customOrigin);
184190
const response = await lifecycle.run(req.url as string);
185191

186192
if (!response) {
@@ -268,7 +274,7 @@ export class BehaviorRouter {
268274

269275
if (!behaviors.has(pattern)) {
270276
const origin = this.origins.get(pattern);
271-
behaviors.set(pattern, new FunctionSet(pattern, distribution, this.log, origin));
277+
behaviors.set(pattern, new FunctionSet(pattern, distribution, this.log, origin, def.name));
272278
}
273279

274280
const fnSet = behaviors.get(pattern) as FunctionSet;

src/function-set.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ export class FunctionSet {
2828
public readonly pattern: string,
2929
public readonly distribution: string,
3030
private readonly log: (message: string) => void,
31-
public readonly origin: Origin = new Origin()
31+
public readonly origin: Origin = new Origin(),
32+
public readonly name: string = ''
3233
) {
3334
this.regex = globToRegExp(pattern);
3435
}

src/index.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,11 @@ class OfflineEdgeLambdaPlugin {
5656
usage: 'Specify the directory where origin requests will draw from',
5757
required: false,
5858
type: 'string'
59+
},
60+
headersFile: {
61+
usage: 'Specify the file (JSON) where injected CloudFront headers will be taken from',
62+
required: false,
63+
type: 'string'
5964
}
6065
}
6166
}

src/types/serverless.types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ export interface ServerlessOptions {
7676
disableCache: boolean;
7777
fileDir: string;
7878
port: number;
79+
headersFile: string;
7980
}
8081

8182
export interface EdgeLambdaOptions {
@@ -85,6 +86,7 @@ export interface EdgeLambdaOptions {
8586
}
8687

8788
export interface ServerlessFunction {
89+
name: string;
8890
handler: string;
8991
package: ServerlessPackage;
9092
lambdaAtEdge: EdgeLambdaOptions;

src/utils/convert-to-cf-event.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,34 @@
11
import { CloudFrontRequestEvent } from 'aws-lambda';
22
import { IncomingMessage } from 'http';
3+
import fs from 'fs';
34
import { parse, UrlWithStringQuery } from 'url';
45

56
import { CloudFrontConfig } from '../types';
67
import { toCloudFrontHeaders } from './convert-headers';
78

9+
function readInjectedHeadersFile(injectedHeadersFile: string): Record<string, string> {
10+
const headers = fs.readFileSync(injectedHeadersFile, 'utf8');
11+
return JSON.parse(headers);
12+
}
813

914
export type IncomingMessageWithBodyAndCookies = IncomingMessage & {
1015
body: any;
1116
cookies: Record<string, string>;
1217
};
1318

14-
export function convertToCloudFrontEvent(req: IncomingMessageWithBodyAndCookies, config: CloudFrontConfig): CloudFrontRequestEvent {
19+
export function convertToCloudFrontEvent(
20+
req: IncomingMessageWithBodyAndCookies,
21+
config: CloudFrontConfig,
22+
injectedHeadersFile?: string
23+
): CloudFrontRequestEvent {
1524
const url = parse(req.url as string, false) as UrlWithStringQuery;
25+
26+
const injectedHeaders = injectedHeadersFile ? readInjectedHeadersFile(injectedHeadersFile) : {};
27+
1628
const request = {
1729
clientIp: req.socket.remoteAddress as string,
1830
method: req.method as string,
19-
headers: toCloudFrontHeaders(req.headers),
31+
headers: toCloudFrontHeaders({...req.headers, ...injectedHeaders}),
2032
uri: url.pathname as string,
2133
querystring: url.query || '',
2234
body: req.body,

0 commit comments

Comments
 (0)