A BHTTP (RFC 9292: Binary Representation of HTTP Messages) encoder and decoder for the Request/Response interface of Fetch API.
This module works on Node.js, Cloudflare Workers, and other JavaScript runtimes supporting the Fetch API.
Note: This is a fork of dajiaji/bhttp-js, converted from Deno to a standard npm package.
npm install bhttp-tsimport { BHttpDecoder, BHttpEncoder } from "bhttp-ts";
const req = new Request("https://www.example.com/hello.txt", {
method: "GET",
headers: {
"User-Agent": "curl/7.16.3 libcurl/7.16.3 OpenSSL/0.9.7l zlib/1.2.3",
"Accept-Language": "en, mi",
},
});
// Encode a Request object to a BHTTP binary
const encoder = new BHttpEncoder();
const binReq = await encoder.encodeRequest(req);
// Decode the BHTTP binary to a Request object
const decoder = new BHttpDecoder();
const decodedReq = decoder.decodeRequest(binReq);import { BHttpDecoder, BHttpEncoder } from "bhttp-ts";
const res = new Response("Hello World!", {
status: 200,
headers: { "Content-Type": "text/plain" },
});
// Encode a Response object to a BHTTP binary
const encoder = new BHttpEncoder();
const binRes = await encoder.encodeResponse(res);
// Decode the BHTTP binary to a Response object
const decoder = new BHttpDecoder();
const decodedRes = decoder.decodeResponse(binRes);For indeterminate-length messages, use the streaming encoders and decoder:
import {
BHttpRequestStreamEncoder,
BHttpResponseStreamEncoder,
BHttpStreamDecoder,
} from "bhttp-ts";
// Streaming request encoding
const reqEncoder = new BHttpRequestStreamEncoder();
yield reqEncoder.encodePreamble("POST", "https", "example.com", "/api", headers);
yield reqEncoder.encodeContentChunk(chunk1);
yield reqEncoder.encodeContentChunk(chunk2);
yield reqEncoder.encodeEnd();
// Streaming response encoding
const resEncoder = new BHttpResponseStreamEncoder();
yield resEncoder.encodePreamble(200, headers);
yield resEncoder.encodeContentChunk(chunk1);
yield resEncoder.encodeEnd(trailers);
// Streaming decode
const decoder = new BHttpStreamDecoder();
for (const chunk of incomingData) {
for (const event of decoder.push(chunk)) {
switch (event.type) {
case "request-preamble":
// event.method, event.scheme, event.authority, event.path, event.headers
break;
case "response-preamble":
// event.status, event.headers
break;
case "content":
// event.data
break;
case "trailers":
// event.headers
break;
}
}
}
for (const event of decoder.end()) {
// handle final events
}When working with Fetch Request and Response objects, the high-level
streaming methods preserve backpressure and cancellation automatically:
const encoder = new BHttpEncoder();
const decoder = new BHttpDecoder();
const encoded = encoder.encodeRequestStream(request);
const decoded = await decoder.decodeRequestStream(encoded);Response equivalents are encodeResponseStream and decodeResponseStream.
The existing BHttpRequestStreamEncoder, BHttpResponseStreamEncoder, and
BHttpStreamDecoder remain available when manual framing is required.
-
encodeRequest(request: Request, options?: { maxMessageSize?: number }): Promise<Uint8Array>- Encode a Request to known-length BHTTP -
encodeResponse(response: Response, options?: { maxMessageSize?: number }): Promise<Uint8Array>- Encode a Response to known-length BHTTP -
encodeRequestStream(request: Request): ReadableStream<Uint8Array>- Encode a streaming Request to indeterminate-length BHTTP -
encodeResponseStream(response: Response): ReadableStream<Uint8Array>- Encode a streaming Response to indeterminate-length BHTTP
-
decodeRequest(data: ArrayBuffer | Uint8Array): Request- Decode BHTTP to a Request -
decodeResponse(data: ArrayBuffer | Uint8Array): Response- Decode BHTTP to a Response -
decodeRequestStream(stream: ReadableStream<Uint8Array>): Promise<Request>- Decode a streaming BHTTP request -
decodeResponseStream(stream: ReadableStream<Uint8Array>): Promise<Response>- Decode a streaming BHTTP response
For encoding indeterminate-length messages incrementally.
For decoding BHTTP messages incrementally, emitting events as data arrives.
MIT - See LICENSE for details.