-
Notifications
You must be signed in to change notification settings - Fork 4
feat: add http-gateway library and cloudflare gateway example project #42
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
3d463e2
fa50e58
51a88db
2776675
4fcd03f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,6 +5,7 @@ dist/ | |
pocket-ic | ||
.env | ||
Cargo.lock | ||
.wrangler | ||
|
||
.DS_Store | ||
.idea |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
# Cloudflare Worker based ICP HTTP Gateway | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: it seems to me "based" should be preceded with a hyphen, but am not sure whether it should be "Cloudflare-Worker-based" or "Cloudflare Worker-based" (and obviously I'm not a native speaker 😢 ). Maybe the best solution would be to reformulate to "An ICP HTTP Gateway based on a Cloudflare Worker"? |
||
|
||
## Environment variables | ||
|
||
Set the `API_GATEWAY` and `CANISTER_ID` variables in the `wrangler.json` file. Run `pnpm run -F http-gateway-cloudflare-example cf-typegen` to regenerate the `worker-configuration.d.ts` file. | ||
|
||
## Notes | ||
|
||
- Do not alter the response body, status codes or headers in any way. Local HTTP Gateways on an end user's computer may re-validate the response and reject it if it has been altered. | ||
|
||
## Possible optimizations | ||
|
||
- Early hints: | ||
- https://developers.cloudflare.com/workers/examples/103-early-hints/. | ||
- https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Link. | ||
- Link headers should be set on the canister side and certified. The implementation of this will depend on the frontend framework and bundler that is used. | ||
- Cache control: | ||
- Cloudflare reads the `Cache-Control` header and caches the response based on the value of the header. | ||
- This header should be completely controlled by the canister. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
{ | ||
"name": "http-gateway-cloudflare-example", | ||
"version": "0.0.0", | ||
"private": true, | ||
"scripts": { | ||
"start": "wrangler dev", | ||
"deploy": "wrangler deploy", | ||
"cf-typegen": "wrangler types" | ||
}, | ||
"dependencies": { | ||
"@dfinity/http-gateway": "workspace:*" | ||
}, | ||
"devDependencies": { | ||
"wrangler": "^4.14.3" | ||
} | ||
} |
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is the main logic for the Cloudlfare worker. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import { HttpGatewayClient } from '@dfinity/http-gateway'; | ||
import { HttpAgent } from '@dfinity/agent'; | ||
import RESPONSE_VERIFICATION_WASM from '@dfinity/response-verification/dist/web/web_bg.wasm'; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I had issues with loading the WASM when the HTTP Gateway library did it internally. This should work fine in other environments, but Cloudflare doesn't like it for some reason. Loading it explicitly inside the worker and passing it as a parameter works well, although I really don't like it. |
||
|
||
export default { | ||
async fetch(request, env): Promise<Response> { | ||
const cachedResponse = await caches.default.match(request); | ||
if (cachedResponse) { | ||
return mapResponse(cachedResponse); | ||
} | ||
|
||
const agent = HttpAgent.createSync({ host: env['API_GATEWAY'] }); | ||
const client = new HttpGatewayClient({ | ||
agent, | ||
responseVerificationWasm: RESPONSE_VERIFICATION_WASM, | ||
canisterId: env['CANISTER_ID'], | ||
}); | ||
|
||
const response = await client.request({ | ||
request, | ||
}); | ||
|
||
await caches.default.put(request, mapResponse(response.clone())); | ||
|
||
return mapResponse(response); | ||
}, | ||
} satisfies ExportedHandler<Env>; | ||
|
||
function mapResponse(res: Response): Response { | ||
return new Response(res.body, { | ||
headers: res.headers, | ||
status: res.status, | ||
// This prevents Cloudflare from automatically encoding the response body | ||
// according to the response's Content-Encoding header. Otherwise, the | ||
// response body would be double-encoded. | ||
// | ||
// See: https://developers.cloudflare.com/workers/runtime-apis/response/#parameters | ||
encodeBody: 'manual', | ||
}); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
{ | ||
"extends": "../../../tsconfig.json", | ||
"compilerOptions": { | ||
"target": "es2021", | ||
"lib": ["es2021"], | ||
"module": "es2022", | ||
"moduleResolution": "Bundler", | ||
"resolveJsonModule": true, | ||
"allowJs": true, | ||
"checkJs": false, | ||
"noEmit": true, | ||
"isolatedModules": true, | ||
"allowSyntheticDefaultImports": true | ||
}, | ||
"exclude": ["test"], | ||
"include": ["worker-configuration.d.ts", "typings.d.ts", "src/**/*.ts"] | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
declare module '@dfinity/response-verification/dist/web/web_bg.wasm' { | ||
const value: Uint8Array; | ||
export default value; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This folder is generated by Cloudflare's wrangler CLI