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
Note: Cloudflare has moved to more prominently display their new module-based workers. The Service Worker API will still be supported, though.
Using our library is simple. We require only a single function call if we are the only library you are using.
// 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.
You can use Cloudflare 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. Below is an example of how to integrate the KV store with your Spec Proxy Cloudflare worker after you have created it.
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);
};