Skip to content

Commit

Permalink
feat: add postBody Functionality
Browse files Browse the repository at this point in the history
You now have the ability to add pass a postBody function to the parser which will get called once the body stream has completed
  • Loading branch information
cdloh committed Aug 6, 2024
1 parent 7d3113e commit 0c9d7dc
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 7 deletions.
14 changes: 10 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ Library supports all instructions that the Ledge parser supports. Also supports
- [varsCookieBlacklist](#varscookieblacklist)
- [Custom ESI Vars Function](#custom-esi-vars-function)
- [Custom Fetch Function](#custom-fetch-function)
- [Optional Post Body Function](#optional-post-body-function)
- [Caching and upstream requests](#caching-and-upstream-requests)
- [Edge Side Includes](#edge-side-includes)
- [Regular expressions in conditions](#regular-expressions-in-conditions)
Expand All @@ -43,10 +44,10 @@ Using within your worker is as easy as including it and passing your request to
import esi from "cloudflare-esi"

export default {
async fetch(request: Request, env: any, ctx: any) {
const parser = new esi()
return parser.parse(request)
}
async fetch(request: Request, env: any, ctx: any) {
const parser = new esi()
return parser.parse(request)
}
}

```
Expand All @@ -58,6 +59,7 @@ new esi(
options?: // Config
customESIFunction?: // Custom ESI Vars Function
fetcher?: // Custom Fetch Function
postBodyFunction?: // Optional function that will be called once the body has been completed
)
```

Expand Down Expand Up @@ -245,6 +247,10 @@ new esi(undefined, undefined, customFetcher)
```


### Optional Post Body Function

If you need to do extra work once the body has completed streaming, eg you record how many fetches your custom fetcher handles. Or need to fire off some context.waitUntil functions at the end you can fire them after this function has been called.


## Caching and upstream requests

Expand Down
15 changes: 12 additions & 3 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ export type customESIVarsFunction = (
request: Request,
) => Promise<customESIVars>;
export type fetchFunction = (request: string | Request) => Promise<Response>;
export type postBodyFunction = () => void | Promise<void>;

const processorToken = "ESI";
const processorVersion = 1.0;
Expand All @@ -111,19 +112,22 @@ export class esi {
options: ESIConfig;
esiFunction?: customESIVarsFunction;
fetcher: fetchFunction;
postBodyFunction?: postBodyFunction;

constructor(
options?: ESIConfig,
customESIFunction?: customESIVarsFunction,
fetcher = fetch as fetchFunction,
postBodyFunction?: postBodyFunction,
) {
const defaultConfig = {
recursionLimit: 10,
contentTypes: ["text/html", "text/plain"],
};
this.options = { ...defaultConfig, ...options };
this.fetcher = fetcher;
if (customESIFunction) this.esiFunction = customESIFunction;
this.esiFunction = customESIFunction;
this.postBodyFunction = postBodyFunction;
}

async parse(origRequest: Request, recursion = 0): Promise<Response> {
Expand Down Expand Up @@ -252,7 +256,7 @@ export class esi {
/**
* Flushes output to the Writeable Stream
*/
async function flush_output() {
const flush_output = async () => {
// Can't call this if we're waiting for an sync option to complete
if (pending) {
return;
Expand Down Expand Up @@ -287,8 +291,13 @@ export class esi {
if (ended && output.length === 0) {
const writer = writable.getWriter();
await writer.close();

// we're completely done now notify the post body function
if (this.postBodyFunction) {
this.postBodyFunction();
}
}
}
};

const writer = (text: string, esi: boolean) => {
if (esi) {
Expand Down
83 changes: 83 additions & 0 deletions test/postBody.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import { checkSurrogate, testResponse, urlHandler } from "./helpers";
import { esi, ESIConfig } from "../src";
import { AddressInfo } from "net";
import http from "http";

const esiHead = {
"Content-Type": "text/html",
"Surrogate-Control": `content="ESI/1.0"`,
};

let parser: esi;
let config: ESIConfig;
const makeRequest = async function (request: string, details?: RequestInit) {
const reqUrl = new URL(request, `http://localhost:${port}`).toString();
const req = new Request(reqUrl, details);
return parser.parse(req);
};

const routeHandler = new urlHandler();
// @ts-ignore
const server = http.createServer(routeHandler.route);
let port = 0;
const testingDetails = {
port: 0,
hostname: "localhost",
proto: "http:",
url: `http://localhost:0`,
};

beforeAll(() => {
// Setup a basic HTTP server to handle traffic
server.listen(0);
const address = server.address() as AddressInfo;
port = address.port;
testingDetails.port = address.port;
testingDetails.url = `http://localhost:${port}`;
});

afterAll((done) => {
server.close(() => {
done();
});
});

test("TEST 1: postBody Function", async () => {
const url = `/post-body/test-1`;
let count = 0;
const postBody = function () {
expect(count).toEqual(3);
return;
};
parser = new esi(config, undefined, undefined, postBody);

const printFragment = function (
req: http.IncomingMessage,
res: testResponse,
) {
count++;
const url = new URL(req.url as string, `http://localhost:${port}`);
const query = url.searchParams.get("a") ? url.searchParams.get("a") : "";
res.end(`FRAGMENT: ${query}\n`);
};
routeHandler.add(url, function (req, res) {
res.writeHead(200, esiHead);
res.say("1");
res.write(`<esi:include src="${url}/fragment_1" />`);
res.say("2");
res.write(`<esi:include src="${url}/fragment_1?a=2" />`);
res.write("3");
res.end(
`<esi:include src="http://localhost:${port}${url}/fragment_1?a=3" />`,
);
});
routeHandler.add(`${url}/fragment_1`, printFragment);
routeHandler.add(`${url}/fragment_1?a=2`, printFragment);
routeHandler.add(`${url}/fragment_1?a=3`, printFragment);
const res = await makeRequest(url);
expect(res.ok).toBeTruthy();
expect(checkSurrogate(res)).toBeTruthy();
expect(await res.text()).toEqual(
`1\nFRAGMENT: \n2\nFRAGMENT: 2\n3FRAGMENT: 3\n`,
);
});

0 comments on commit 0c9d7dc

Please sign in to comment.