@specprotected/spec-proxy-cloudflare-worker
Version:
Spec Proxy implementation for Cloudflare Edge Workers
150 lines (120 loc) • 4.99 kB
Markdown
# Spec Proxy Cloudflare Worker API Integration
This document describes a method of integrating with Spec Proxy through a
Cloudflare Edge Worker.
We won't cover in detail how to use a Cloudflare Worker and will instead direct
you to follow their documentation to get a worker project setup and deployed.
Once deployed, all you need do is copy our sample code into your edge worker
function as well as communicate with the Spec team to coordinate the Spec Proxy
deployment.
[Cloudflare Worker Documentation](https://developers.cloudflare.com/workers/)
**Note:** Cloudflare has moved to more prominently display their new
module-based workers. The [Service Worker
API](https://developers.cloudflare.com/workers/learning/service-worker/) will
still be [supported](https://blog.cloudflare.com/workers-javascript-modules/),
though.
## Implementation Example
Using our library is simple. We require only a single function call if we are
the only library you are using.
```javascript
// Import the Spec Proxy library function
import { specProxyProcess } from "@specprotected/spec-proxy-cloudflare-worker";
// Option 1: Cloudflare ES Modules
export default {
async fetch(request, env, ctx) {
// If we don't catch the exception, fail open to original traffic path
ctx.passThroughOnException();
// wrap up the context methods that our library uses alongside the request
let eventWrapper = {
waitUntil: ctx.waitUntil.bind(ctx),
request,
};
return specProxyProcess(eventWrapper, {
inlineMode: true,
}));
}
}
// Option 2: Cloudflare Service Worker
addEventListener('fetch', event => {
// If we don't catch the exception, fail open to original traffic path
event.passThroughOnException();
event.respondWith(
specProxyProcess(event, {
inlineMode: true,
})
);
});
```
There's no additional configuration of our library required in order to use it.
Your Cloudflare configuration and your Spec Proxy deployment take care of all of
the inner details of routing traffic. The only additional thing you will have to
configure is how to route traffic to your worker, which is typically done
through the use of [Cloudflare
Routes](https://developers.cloudflare.com/workers/platform/triggers/routes/).
### Runtime Configuration
You can use [Cloudflare
KV](https://developers.cloudflare.com/workers/runtime-apis/kv/) to dynamically
configure how the Spec Proxy library behaves during runtime. When you create
your KV store in the Cloudflare web UI, be sure to [add it to your
worker](https://developers.cloudflare.com/workers/runtime-apis/kv/#referencing-kv-from-workers).
Below is an example of how to integrate the KV store with your Spec Proxy
Cloudflare worker after you have created it.
```javascript
import { specProxyProcess } from "@specprotected/spec-proxy-cloudflare-worker";
// Option 1: Cloudflare ES Modules
export default {
async fetch(request, env, ctx) {
// If we don't catch the exception, fail open to original traffic path
ctx.passThroughOnException();
return await handler(request, env, ctx);
},
};
async function handler(request, env, ctx) {
// Note: null is returned if the key isn't present, so the value
// of inlineMode and disableSpecProxy would default to false
let inlineMode = (await env.SPEC_PROXY.get("inline_mode")) === "true";
let disableSpecProxy =
(await env.SPEC_PROXY.get("disable_spec_proxy")) === "true";
// configure our use of the spec library
let config = {
inlineMode,
disableSpecProxy,
};
// only assign percentage of IPs if it's valid
let percentageIPs = parseInt(await env.SPEC_PROXY.get("percentage_of_ips"));
if (!isNaN(percentageIPs)) {
config.percentageOfIPs = percentageIPs;
}
// wrap up the context methods that our library uses alongside the request
let eventWrapper = {
waitUntil: ctx.waitUntil.bind(ctx),
request,
};
return await specProxyProcess(eventWrapper, config);
},
};
// Option 2: Cloudflare Service Worker
addEventListener('fetch', event => {
// If we don't catch the exception, fail open to original traffic path
event.passThroughOnException();
// respond with an async function so we can `await` the KV accesses
event.respondWith(handler(event));
});
async function handler(event) {
// Note: null is returned if the key isn't present, so the value
// of inlineMode and disableSpecProxy would default to false
let inlineMode = (await SPEC_PROXY.get("inline_mode")) === "true";
let disableSpecProxy =
(await SPEC_PROXY.get("disable_spec_proxy")) === "true";
// configure our use of the spec library
let config = {
inlineMode,
disableSpecProxy,
};
// only assign percentage of IPs if it's valid
let percentageIPs = parseInt(dictionary.get("percentage_of_ips"));
if (!isNaN(percentageIPs)) {
config.percentageOfIPs = percentageIPs;
}
return await specProxyProcess(event, config);
};
```