Skip to content

Commit 9a242fc

Browse files
authored
Merge pull request #283 from cdloh/fix/customesi-doesnt-have-to-be-a-promise
fix: Cleanup useless async and awaits & custom ESI Vars function doesn't have to be async
2 parents 3c303fc + 6ee4f6b commit 9a242fc

10 files changed

Lines changed: 54 additions & 64 deletions

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -151,22 +151,22 @@ This is useful if your client is sending a sensitive cookie that you don't ever
151151
### Custom ESI Vars Function
152152

153153
```
154-
export type customESIVarsFunction = (request: Request) => Promise<customESIVars>;
154+
export type customESIVarsFunction = (request: Request) => Promise<customESIVars> | customESIVars;
155155
export type customESIVars = {
156156
[key: string]: string | { [key: string]: string };
157157
};
158158
```
159159

160160
If you want to inject custom ESI vars into the parser per request you can pass the class a custom async function that will be evaluated each request.
161161

162-
The async function accepts a request object and returns an object.
162+
The function accepts a request object, returns an object and can be async.
163163

164164
The object values can either be strings or objects. If the value is an object it the ESIVar must be refrenced with a key in the ESI variable or the default variable will be returned.
165165

166166
eg that pulls GEOIP data out of the Request and injects it as `GEOIP_X` ESI Vars
167167

168168
```javascript
169-
const geoIPVarsFromRequest = async function (request) {
169+
const geoIPVarsFromRequest = function (request) {
170170
let customVariables = {};
171171
let cfData = request.cf;
172172
let geoipVars = [

package.json

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@
5656
"license": "BSD-2-Clause",
5757
"eslintConfig": {
5858
"root": true,
59+
"parserOptions": {
60+
"project": "./tsconfig.json"
61+
},
5962
"extends": [
6063
"typescript",
6164
"prettier",
@@ -73,15 +76,11 @@
7376
"startLines": 1
7477
}
7578
],
76-
"no-new-func": [
77-
"error"
78-
],
79-
"no-eval": [
80-
"error"
81-
],
82-
"no-return-await": [
83-
"error"
84-
]
79+
"no-new-func": "error",
80+
"no-eval": "error",
81+
"no-return-await": "error",
82+
"@typescript-eslint/await-thenable": "error",
83+
"require-await": "error"
8584
}
8685
},
8786
"devDependencies": {

src/handleChunk.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { tagParser } from "./tagParser";
88
* @returns {void}
99
*/
1010
type writerFunction = (text: string, esi: boolean) => void;
11-
type handleFunction = (value: string, done: boolean) => Promise<void>;
11+
type handleFunction = (value: string, done: boolean) => void;
1212

1313
/**
1414
* Creates a chunk handler and returns a
@@ -26,13 +26,13 @@ export function create(writer: writerFunction): handleFunction {
2626
}
2727
};
2828

29-
return async function (value: string, done: boolean): Promise<void> {
29+
return function (value: string, done: boolean): void {
3030
value = prev_chunk + value;
3131
prev_chunk = "";
3232

3333
const parser = new tagParser(value);
3434
do {
35-
const [tag, before, after] = await parser.next();
35+
const [tag, before, after] = parser.next();
3636

3737
// Always write before if we have it
3838
writeString(before);
@@ -64,8 +64,8 @@ export function create(writer: writerFunction): handleFunction {
6464
// eslint-disable-next-line no-constant-condition
6565
} while (true);
6666

67-
// Check if we had something left over
68-
// But we didnt write it
67+
// ensure we write anything left over
68+
// when we are done
6969
if (done) {
7070
writeString(prev_chunk);
7171
}

src/index.ts

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,10 @@ import { getheaderToken } from "./headerUtils";
2121
* @property {string[]} contentTypes - Array of strings of content types that the parser should parse for ESI Tags
2222
* Note: That these are case sensitive. See - https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Type
2323
* @property {boolean} disableThirdPartyIncludes - Whether or not to enable third party includes (includes from other domains)
24-
* @property {number} [recursionLimit] - Levels of recusion the parser is allowed to go do
25-
* think includes that include themselves causing recusion
24+
* @property {number} [recursionLimit] - Levels of recursion the parser is allowed to include before bailing out
25+
* think includes that include themselves causing recursion
2626
* @default 10
27-
* @property {string[]} thirdPatyIncludesDomainWhitelist - If third party includes are disabled you can white list them by including domains here
27+
* @property {string[]} thirdPartyIncludesDomainWhitelist - If third party includes are disabled you can white list them by including domains here
2828
* @property {string[]} varsCookieBlacklist - Array of strings of cookies that will be blacklisted from being expanded in esi VARs.
2929
*/
3030
export type ESIConfig = {
@@ -47,14 +47,14 @@ export type ESIVars = {
4747
* ESI Event Data for the Current Request
4848
*
4949
* @property {ESIConfig} config - ESIConfig when class was created
50-
* @property {object} headers - All headers of the request uppercased
50+
* @property {object} headers - All headers of the request in uppercase
5151
* @property {string} method - Method of the request
5252
* @property {URLSearchParams} esiArgs - Any ESI Arguments extracted from the URL Search params of the original request
5353
* Will be a URLSearchParam encoded object
5454
* @property {customESIVars} customVars - If a custom ESI Vars function is supplied this will be the result of that function
5555
* @property {URL} url - URL Object of the Request with ESI Args removed
5656
* @property {Request} request - Request object after ESI Args have been removed
57-
* @property {number} recursion - Recusion level we're currently at
57+
* @property {number} recursion - Recursion level we're currently at
5858
*/
5959
export type ESIEventData = {
6060
/**
@@ -63,7 +63,7 @@ export type ESIEventData = {
6363
config: ESIConfig;
6464
/**
6565
* All headers of the current Request in {Object}
66-
* All headers are uppercassed with - being converted to _
66+
* All headers are in uppercase and - is converted to _
6767
*/
6868
headers: { [key: string]: string };
6969
/**
@@ -101,7 +101,7 @@ export type customESIVars = {
101101
};
102102
export type customESIVarsFunction = (
103103
request: Request,
104-
) => Promise<customESIVars>;
104+
) => Promise<customESIVars> | customESIVars;
105105
export type fetchFunction = (
106106
request: RequestInfo,
107107
ctx: Request[],
@@ -150,7 +150,7 @@ export class esi {
150150
// Remove ESI Vars if they're in the request
151151
// Return a brand new request
152152
// eslint-disable-next-line
153-
let [request, esiVars] = await getVars(origRequest);
153+
let [request, esiVars] = getVars(origRequest);
154154

155155
// Load custom values if we can
156156
let customESIVariables;
@@ -159,7 +159,7 @@ export class esi {
159159
}
160160

161161
// Add SurrogateControl header or append to it
162-
request = await advertiseSurrogateControl(request);
162+
request = advertiseSurrogateControl(request);
163163

164164
// pack our nice stuff in
165165
const eventData: ESIEventData = {
@@ -189,7 +189,7 @@ export class esi {
189189
!response.body ||
190190
!this.validContentType(response) ||
191191
!this.validSurrogateControl(response) ||
192-
(await canDelegateToSurrogate(origRequest, this.options))
192+
canDelegateToSurrogate(origRequest, this.options)
193193
) {
194194
const resp = new Response(response.body, response);
195195
// We set the URL manually here as it doesn't come across from the copy˛
@@ -230,10 +230,10 @@ export class esi {
230230
}
231231

232232
async handleESI(eventData: ESIEventData, text: string): Promise<string> {
233-
text = await processEscaping(text);
233+
text = processEscaping(text);
234234
text = processComments(text);
235235
text = processRemove(text);
236-
text = await processESIVars(eventData, text);
236+
text = processESIVars(eventData, text);
237237
let vars = false;
238238
[text, vars] = await processConditionals(eventData, text);
239239

@@ -249,15 +249,16 @@ export class esi {
249249

250250
return text;
251251
}
252+
// eslint-disable-next-line require-await
252253
async handleTEXT(eventData: ESIEventData, text: string): Promise<string> {
253254
return text;
254255
}
255256

256-
async streamBody(
257+
streamBody(
257258
eventData: ESIEventData,
258259
readable: ReadableStream,
259260
writable: WritableStream,
260-
): Promise<void> {
261+
) {
261262
const reader = readable.getReader();
262263
const encoder = new TextEncoder();
263264
const decoder = new TextDecoder();
@@ -328,12 +329,12 @@ export class esi {
328329

329330
const handler = createHandleChunk(writerBound);
330331

331-
reader.read().then(async function processBlob(blob): Promise<void> {
332+
reader.read().then(function processBlob(blob): Promise<void> | undefined {
332333
const chunk: ArrayBuffer = blob.value;
333334
const done: boolean = blob.done;
334335
// decode it
335336
const decodedChunk: string = decoder.decode(chunk, { stream: true });
336-
await handler(decodedChunk, done);
337+
handler(decodedChunk, done);
337338

338339
// we're done bail out
339340
if (done) {
@@ -390,9 +391,9 @@ const esiArgsRegex = /^esi_(\S+)/;
390391
* Return a brand new mutatable Request along with an ESIVars object
391392
*
392393
* @param {Request} request - Original Request
393-
* @returns {Promise<[Request, ESIVars]>} - Mutatable Request and ESIVars
394+
* @returns {[Request, ESIVars]} - Mutatable Request and ESIVars
394395
*/
395-
async function getVars(request: Request): Promise<[Request, ESIVars]> {
396+
function getVars(request: Request): [Request, ESIVars] {
396397
const vars: ESIVars = {
397398
headers: {},
398399
method: request.method,
@@ -466,7 +467,7 @@ export function getProcessorVersionString(): string {
466467
* @param {Request[]} ctx request ctx (parent requests)
467468
* @returns {Promise<Response>} - processor supported version
468469
*/
469-
async function defaultFetch(
470+
function defaultFetch(
470471
req: RequestInfo,
471472
// eslint-disable-next-line @typescript-eslint/no-unused-vars
472473
ctx: Request[],

src/processConditionals.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ export async function process(
2323
let hasConditionals = false;
2424

2525
do {
26-
const [choose, ch_before, ch_after] = await parser.next("esi:choose");
26+
const [choose, ch_before, ch_after] = parser.next("esi:choose");
2727

2828
if (choose && choose.closing) {
2929
hasConditionals = true;
@@ -43,7 +43,7 @@ export async function process(
4343
let otherwise = null;
4444

4545
do {
46-
const [tag, ,] = await innerParser.next("esi:when|esi:otherwise");
46+
const [tag, ,] = innerParser.next("esi:when|esi:otherwise");
4747

4848
if (tag && tag.closing && tag.whole && tag.contents) {
4949
if (tag.tagname == "esi:when" && !whenMatched) {

src/processESIVars.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,9 @@ const esiLessArrow = />/g;
1313
*
1414
* @param {ESIEventData} eventData event data for the current request
1515
* @param {string} chunk string to process
16-
* @returns {Promise<string>} processed string
16+
* @returns {string} processed string
1717
*/
18-
export async function process(
19-
eventData: ESIEventData,
20-
chunk: string,
21-
): Promise<string> {
18+
export function process(eventData: ESIEventData, chunk: string): string {
2219
if (chunk.indexOf("esi:vars") == -1) {
2320
return chunk;
2421
}

src/processEscaping.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,14 @@ import { tagParser } from "./tagParser";
55
*
66
* @param {string} chunk Chunk of text to process
77
* @param {string[]} [res] Array of chunks of text already processed (used internally within function)
8-
* @returns {Promise<string>} processed string
8+
* @returns {string} processed string
99
*/
10-
export async function process(
11-
chunk: string,
12-
res: Array<string> = [],
13-
): Promise<string> {
10+
export function process(chunk: string, res: Array<string> = []): string {
1411
const parser = new tagParser(chunk);
1512
let hasEscaping = false;
1613

1714
do {
18-
const [tag, before, after] = await parser.next("!--esi");
15+
const [tag, before, after] = parser.next("!--esi");
1916

2017
if (tag && tag.closing && tag.contents) {
2118
hasEscaping = true;

src/surrogate.ts

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,9 @@ import { getheaderToken } from "./headerUtils";
1212
* If we have Colo data in the Request object we add that to our identifier
1313
*
1414
* @param {Request} request Request to modify
15-
* @returns {Promise<Request>} Request with SurrogateControl header added
15+
* @returns {Request} Request with SurrogateControl header added
1616
*/
17-
export async function advertiseSurrogateControl(
18-
request: Request,
19-
): Promise<Request> {
17+
export function advertiseSurrogateControl(request: Request): Request {
2018
let coloName = "";
2119
if (request.cf && request.cf.colo) {
2220
coloName = `-${request.cf.colo}`;
@@ -33,12 +31,12 @@ export async function advertiseSurrogateControl(
3331
*
3432
* @param {Request} request Request to confirm against
3533
* @param {ESIConfig} config Config for the current request
36-
* @returns {Promise<boolean>} result
34+
* @returns {boolean} result
3735
*/
38-
export async function canDelegateToSurrogate(
36+
export function canDelegateToSurrogate(
3937
request: Request,
4038
config: ESIConfig,
41-
): Promise<boolean> {
39+
): boolean {
4240
const surrogates = config.allowSurrogateDelegation;
4341
if (surrogates === undefined || surrogates === false) return false;
4442

src/tagParser.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,7 @@ export class tagParser {
2323
this.next = this.next.bind(this);
2424
}
2525

26-
async next(
27-
tagname?: string,
28-
): Promise<[tag | null, string | undefined, string | undefined]> {
26+
next(tagname?: string): [tag | null, string | undefined, string | undefined] {
2927
const tag = this.findWholeTag(tagname);
3028
let before, after;
3129

test/esi.spec.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -416,7 +416,7 @@ test("TEST 7h: Compile instructions if ESI delegation is enabled by IP but no Ca
416416
expect(await res.text()).toEqual(`a=1`);
417417
});
418418

419-
test("TEST 8: Response downstrean cacheability is zeroed when ESI processing", async () => {
419+
test("TEST 8: Response downstream cacheability is zeroed when ESI processing", async () => {
420420
const url = `/esi/test-8`;
421421
routeHandler.add(url, function (req, res) {
422422
res.writeHead(200, {
@@ -1862,7 +1862,7 @@ test("TEST 48: POST With body", async () => {
18621862
expect(await res.text()).toEqual(postBody);
18631863
});
18641864

1865-
test("TEST 48: Mutliple ESI Includes next to each other", async () => {
1865+
test("TEST 48: Multiple ESI Includes next to each other", async () => {
18661866
const url = `/esi/test-48`;
18671867
routeHandler.add(url, function (req, res) {
18681868
res.writeHead(200, esiHead);
@@ -1885,7 +1885,7 @@ test("TEST 48: Mutliple ESI Includes next to each other", async () => {
18851885
expect(await res.text()).toEqual(`START:\nFRAGMENT\nFRAGMENT\n:END`);
18861886
});
18871887

1888-
test("TEST 49: Mutliple ESI Includes next to each other in choose", async () => {
1888+
test("TEST 49: Multiple ESI Includes next to each other in choose", async () => {
18891889
const url = `/esi/test-49`;
18901890
routeHandler.add(url, function (req, res) {
18911891
res.writeHead(200, esiHead);
@@ -1930,7 +1930,7 @@ describe("TEST 51: ESI Args that lead with ints shouldn't convert to ints", () =
19301930
{ arg: "1719,1732", result: "second-lineage" },
19311931
{ arg: "1719,1918", result: "third-lineage" },
19321932
{ arg: "1719,1922", result: "forth-lineage" },
1933-
{ arg: "1719,1926", result: "fith-lineage" },
1933+
{ arg: "1719,1926", result: "fifth-lineage" },
19341934
{ arg: "1719,2000", result: "sixth-lineage" },
19351935
{ arg: "2000", result: "seventh-lineage" },
19361936
{ arg: "2001", result: "eighth-lineage" },
@@ -1946,7 +1946,7 @@ describe("TEST 51: ESI Args that lead with ints shouldn't convert to ints", () =
19461946
<esi:when test="$(ESI_ARGS{lineage}) =~ '/(?:^|,)(1732)(?:,|$)/'">second-lineage</esi:when>
19471947
<esi:when test="$(ESI_ARGS{lineage}) =~ '/(?:^|,)(1918)(?:,|$)/'">third-lineage</esi:when>
19481948
<esi:when test="$(ESI_ARGS{lineage}) =~ '/(?:^|,)(1922)(?:,|$)/'">forth-lineage</esi:when>
1949-
<esi:when test="$(ESI_ARGS{lineage}) =~ '/(?:^|,)(1926)(?:,|$)/'">fith-lineage</esi:when>
1949+
<esi:when test="$(ESI_ARGS{lineage}) =~ '/(?:^|,)(1926)(?:,|$)/'">fifth-lineage</esi:when>
19501950
<esi:when test="$(ESI_ARGS{lineage}) == '1719,2000'">sixth-lineage</esi:when>
19511951
<esi:when test="$(ESI_ARGS{lineage}) == '2000'">seventh-lineage</esi:when>
19521952
<esi:when test="$(ESI_ARGS{lineage}) >= '800'">eighth-lineage</esi:when>

0 commit comments

Comments
 (0)