@oceanum/layers / Proxy Guide
A reverse proxy lets you serve Oceanum zarr layers from a public web app without exposing your Datamesh token in client-side code and helps you avoid CORS issues.
This repo includes example proxies you can deploy quickly, and shows how to point the layers to them.
packages/layers/proxy/cloudflare/index.jspackages/layers/proxy/express/index.js@oceanum/layersAll @oceanum/layers layers accept an authHeaders prop — a plain object of HTTP headers that are sent with every zarr chunk and metadata request. Without a proxy, you’d pass your token directly:
new OceanumPcolorLayer({
authHeaders: { Authorization: `Bearer ${token}` },
// ...
});
With a proxy, the token lives server-side and the client needs no authHeaders at all.
The example Cloudflare Worker:
Authorization header using a Worker Secret.// Example Cloudflare Worker reverse proxy for @oceanum/layers
// Add your datamesh token as a secret in the Cloudflare worker environment
const LAYERS_SERVICE = "https://layers.app.oceanum.io";
export default {
async fetch(request, env) {
const url = new URL(request.url);
const TOKEN = env.DATAMESH_TOKEN;
// Handle CORS preflight
if (request.method === "OPTIONS") {
return new Response(null, {
status: 204,
headers: {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET, OPTIONS",
"Access-Control-Allow-Headers": "Content-Type, Authorization",
},
});
}
// Build the upstream request URL
const upstreamUrl = new URL(url.pathname + url.search, LAYERS_SERVICE);
// Clone request and forward headers/method
const modifiedRequest = new Request(upstreamUrl.toString(), {
method: request.method,
headers: request.headers,
});
// Inject/overwrite the authorization header
modifiedRequest.headers.set("Authorization", `Bearer ${TOKEN}`);
// Forward
const response = await fetch(modifiedRequest);
// Add CORS headers for the browser
return new Response(response.body, {
status: response.status,
statusText: response.statusText,
headers: {
...response.headers,
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET, OPTIONS",
"Access-Control-Allow-Headers": "Content-Type, Authorization",
},
});
},
};
packages/layers/proxy/cloudflare/index.js.DATAMESH_TOKEN and set it to your Datamesh token.LAYERS_SERVICE to point at a different upstream if needed.https://your-proxy.workers.dev.wrangler dev.You can also run a simple Node/Express reverse proxy locally or deploy it to your own infrastructure.
packages/layers/proxy/express/index.jsInstall dependencies in the example folder:
cd packages/layers/proxy/express
npm init -y
npm install express
Start the proxy:
DATAMESH_TOKEN=your_token_here node index.js
# Optional:
# LAYERS_SERVICE=https://layers.app.oceanum.io PORT=8787 DATAMESH_TOKEN=your_token_here node index.js
The proxy will listen on http://localhost:8787 by default and forward all requests to LAYERS_SERVICE, injecting the Authorization header and adding permissive CORS headers.
Point serviceUrl to your proxy origin and omit authHeaders — the proxy injects the token.
import { OceanumPcolorLayer } from "@oceanum/layers";
const PROXY_URL = "https://your-proxy.workers.dev"; // or your custom domain
new OceanumPcolorLayer({
id: "wave-height",
serviceUrl: PROXY_URL,
// No authHeaders needed — the proxy injects the token
datasource: "oceanum_wave_glob05",
variable: "hs",
time: "2024-01-15T00:00:00Z",
colormap: {
scale: [
"#313695", "#4575b4", "#74add1", "#abd9e9",
"#fee090", "#fdae61", "#f46d43", "#d73027",
],
domain: [0, 1, 2, 3, 4, 5, 6, 8],
},
});
Notes:
authHeaders defaults to {} when omitted — the proxy takes care of authentication./zarr/oceanum_wave_glob05/latest/.zmetadata).Authorization header to prevent client-supplied values from reaching the upstream.GET requests, so you can safely restrict the proxy to GET and OPTIONS methods only.