for the Request/Response interface of Fetch API.
This module works on web browsers, Node.js, Deno and various other JavaScript runtimes.
bhttp-js
can be used in all JavaScript runtimes which support
Request/Response
interface of
Fetch API:
- Deno: 1.x
- Node.js: 18.x, 19.x, 20.x, 21.x, 22.x
- Bun: 0.x, 1.x
- Cloudflare Workers
- @fastly/js-compute
- Web browsers: Chrome, Edge, Firefox, Safari and so on.
Starting from version 0.3.4, bhttp-js
is available from the
JSR registry. From this version onwards, please use JSR import
instead of HTTPS import in Deno.
JSR imoprt (recommended on >=0.3.4
):
Add bhttp-js
package using the commands below:
deno add @dajiaji/bhttp
After adding the package, you will have an import map entry in deno.json
that
looks something like this:
{
"imports": {
"@dajiaji/bhttp": "jsr:@dajiaji/bhttp@^<SEMVER>"
}
}
Then, you can use the module from code like this:
import { BHttpDecoder, BHttpEncoder } from "@dajiaji/bhttp";
HTTPS import (deprecated):
import {
BHttpDecoder,
BHttpEncoder,
} from "https://deno.land/x/bhttp@<SEMVER>/mod.ts";
Using npm, yarn or pnpm:
npm add bhttp-js
yarn add bhttp-js
pnpm add bhttp-js
After adding the package, you will have a dependency entry in package.json
that looks something like this:
{
"dependencies": {
"bhttp-js": "^<SEMVER>"
}
}
Then, you can use the module from code like this:
import { BHttpDecoder, BHttpEncoder } from "bhttp-js";
// or as a CommonJS module
// const { BHttpEncoder, BHttpDecoder } = require("bhttp-js");
// ...
Using jsr:
npx jsr add @dajiaji/bhttp
yarn dlx jsr add @dajiaji/bhttp
pnpm dlx jsr add @dajiaji/bhttp
After adding the package, you will have a dependency entry in package.json
that looks something like this:
{
"dependencies": {
"@dajiaji/bhttp": "npm:@jsr/dajiaji__bhttp@^<SEMVER>"
}
}
Then, you can use the module from code like this:
import { BHttpDecoder, BHttpEncoder } from "@dajiaji/bhttp";
// ...
Using jsr:
npx jsr add @dajiaji/bhttp
yarn dlx jsr add @dajiaji/bhttp
pnpm dlx jsr add @dajiaji/bhttp
After adding the package, you will have a dependency entry in package.json
that looks something like this:
{
"dependencies": {
"@dajiaji/bhttp": "npm:@jsr/dajiaji__bhttp@^<SEMVER>"
}
}
Then, you can use the module from code like this:
import { BHttpDecoder, BHttpEncoder } from "@dajiaji/bhttp";
// ...
Using jsr:
bunx jsr add @dajiaji/bhttp
After adding the package, you will have a dependency entry in package.json
that looks something like this:
{
"dependencies": {
"@dajiaji/bhttp": "npm:@jsr/dajiaji__bhttp"
}
}
Then, you can use the module from code like this:
import { BHttpDecoder, BHttpEncoder } from "@dajiaji/bhttp";
// ...
Followings are how to use with typical CDNs. Other CDNs can be used as well.
Using esm.sh:
<!-- use a specific version -->
<script type="module">
import { BHttpDecoder, BhttpEncoder } from "https://esm.sh/[email protected]";
// ...
</script>
<!-- use the latest stable version -->
<script type="module">
import { BHttpDecoder, BhttpEncoder } from "https://esm.sh/bhttp-js";
// ...
</script>
Using unpkg:
<!-- use a specific version -->
<script type="module">
import { BHttpDecoder, BhttpEncoder } from "https://unpkg.com/[email protected]/esm/mod.js";
// ...
</script>
This section shows some typical usage examples.
See samples/deno.
import { BHttpDecoder, BHttpEncoder } from "@dajiaji/bhttp";
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 string.
const encoder = new BHttpEncoder();
const binReq = await encoder.encodeRequest(req);
// Decode the BHTTP binary string to a Request object.
const decoder = new BHttpDecoder();
const decodedReq = decoder.decodeRequest(binReq);
See samples/node.
// via `npm add bhttp-js`
import { BHttpDecoder, BHttpEncoder } from "bhttp-js";
// or as a CommonJS module
// const { BHttpEncoder, BHttpDecoder } = require("bhttp-js");
// via `npx jsr add @dajiaji/bhttp`
// import { BHttpDecoder, BHttpEncoder } from "@dajiaji/bhttp";
async function doBHttp() {
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 string.
const encoder = new BHttpEncoder();
const binReq = await encoder.encodeRequest(req);
// Decode the BHTTP binary string to a Request object.
const decoder = new BHttpDecoder();
const decodedReq = decoder.decodeRequest(binReq);
}
doBHttp();
See samples/bun.
import { BHttpDecoder, BHttpEncoder } from "@dajiaji/bhttp";
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 string.
const encoder = new BHttpEncoder();
const binReq = await encoder.encodeRequest(req);
// Decode the BHTTP binary string to a Request object.
const decoder = new BHttpDecoder();
const decodedReq = decoder.decodeRequest(binReq);
See samples/cloudflare.
BHTTP server on Cloutflare Workers:
import { BHttpDecoder, BHttpEncoder } from "@dajiaji/bhttp";
export default {
async fetch(request) {
const decoder = new BHttpDecoder();
const encoder = new BHttpEncoder();
const url = new URL(request.url);
if (url.pathname === "/to_target") {
try {
if (request.headers.get("content-type") !== "message/bhttp") {
throw new Error("Invalid content-type.");
}
const reqBody = await request.arrayBuffer();
const decodedReq = decoder.decodeRequest(reqBody);
const res = new Response("baz", {
headers: { "Content-Type": "text/plain" },
});
const bRes = await encoder.encodeResponse(res);
return new Response(bRes, {
headers: { "Content-Type": "message/bhttp" },
});
} catch (err) {
return new Response(
await encoder.encodeResponse(
new Response(err.message, { status: 400 }),
),
{ status: 400, headers: { "Content-Type": "message/bhttp" } },
);
}
}
return new Response(
await encoder.encodeResponse(new Response("", { status: 404 })),
{ status: 404, headers: { "Content-Type": "message/bhttp" } },
);
},
};
BHTTP client on Web Browser:
<html>
<head></head>
<body>
<script type="module">
import { BHttpEncoder, BHttpDecoder } from "https://esm.sh/[email protected]";
globalThis.doBHttp = async () => {
try {
const encoder = new BHttpEncoder();
const req = new Request("https://target.example/query?foo=bar");
const bReq = await encoder.encodeRequest(req);
const res = await fetch("https://bin.example/to_target", {
method: "POST",
headers: {
"Content-Type": "message/bhttp",
},
body: bReq,
});
const decoder = new BHttpDecoder();
const decodedRes = decoder.decodeResponse(await res.arrayBuffer());
// decodedRes.status === 200;
const body = await decodedRes.text();
// body === "baz"
} catch (err) {
alert(err.message);
}
}
</script>
<button type="button" onclick="doBHttp()">do BHTTP</button>
</body>
</html>
We welcome all kind of contributions, filing issues, suggesting new features or sending PRs.