Client Setup
Installation
npm install ohttp-ts hpke
Basic Setup
import { OHTTPClient, KeyConfig } from 'ohttp-ts';
import {
CipherSuite,
KEM_DHKEM_X25519_HKDF_SHA256,
KDF_HKDF_SHA256,
AEAD_AES_128_GCM
} from 'hpke';
// Create the cipher suite
const suite = new CipherSuite(
KEM_DHKEM_X25519_HKDF_SHA256,
KDF_HKDF_SHA256,
AEAD_AES_128_GCM
);
// Fetch gateway's public key
const keyBytes = await fetch(
'https://gateway.ohttp.info/.well-known/ohttp-gateway'
).then(r => r.arrayBuffer());
const keyConfig = KeyConfig.parse(new Uint8Array(keyBytes));
// Create the OHTTP client
const client = new OHTTPClient(suite, keyConfig);
Making Requests
Simple GET Request
const { request, context } = await client.encapsulateRequest(
new Request('https://api.example.com/data'),
'https://relay.ohttp.info/ohttp'
);
const encResponse = await fetch(request);
const response = await context.decapsulateResponse(encResponse);
console.log(await response.json());
POST with JSON Body
const { request, context } = await client.encapsulateRequest(
new Request('https://api.example.com/submit', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name: 'Lilo', action: 'test' })
}),
'https://relay.ohttp.info/ohttp'
);
const encResponse = await fetch(request);
const response = await context.decapsulateResponse(encResponse);
Using Custom Relay/Gateway
You can use any OHTTP-compatible relay and gateway:
const RELAY_URL = 'https://my-relay.example.com/ohttp';
const GATEWAY_KEY_URL = 'https://my-gateway.example.com/.well-known/ohttp-gateway';
// Fetch custom gateway key
const keyBytes = await fetch(GATEWAY_KEY_URL)
.then(r => r.arrayBuffer());
const keyConfig = KeyConfig.parse(new Uint8Array(keyBytes));
// Send through custom relay
const { request, context } = await client.encapsulateRequest(
innerRequest,
RELAY_URL
);
Error Handling
try {
const { request, context } = await client.encapsulateRequest(
innerRequest,
relayUrl
);
const encResponse = await fetch(request);
if (!encResponse.ok) {
throw new Error(`Relay error: ${encResponse.status}`);
}
const response = await context.decapsulateResponse(encResponse);
return response;
} catch (error) {
if (error.message.includes('decapsulation')) {
// Decryption failed - response may be corrupted or from wrong key
}
throw error;
}
Key Caching
For performance, cache the gateway’s key configuration:
let cachedKeyConfig: KeyConfig | null = null;
let cacheExpiry = 0;
async function getKeyConfig(): Promise<KeyConfig> {
const now = Date.now();
if (cachedKeyConfig && now < cacheExpiry) {
return cachedKeyConfig;
}
const keyBytes = await fetch(
'https://gateway.ohttp.info/.well-known/ohttp-gateway'
).then(r => r.arrayBuffer());
cachedKeyConfig = KeyConfig.parse(new Uint8Array(keyBytes));
cacheExpiry = now + 3600_000; // 1 hour
return cachedKeyConfig;
}
Browser Usage
ohttp-ts works in browsers with WebCrypto support:
<script type="module">
import { OHTTPClient, KeyConfig } from 'https://esm.sh/ohttp-ts';
import { CipherSuite, ... } from 'https://esm.sh/hpke';
// Same usage as Node.js
</script>
Cloudflare Workers
ohttp-ts is designed to work in Cloudflare Workers:
export default {
async fetch(request: Request): Promise<Response> {
const suite = new CipherSuite(...);
const keyConfig = await getKeyConfig();
const client = new OHTTPClient(suite, keyConfig);
const { request: ohttpReq, context } = await client.encapsulateRequest(
new Request('https://api.example.com/data'),
'https://relay.ohttp.info/ohttp'
);
const encResponse = await fetch(ohttpReq);
return context.decapsulateResponse(encResponse);
}
};