mirror of
https://github.com/oven-sh/bun
synced 2026-02-02 15:08:46 +00:00
Support socketPath in node:http request (#9284)
* Support `socketPath` in node:http request * fix dashes --------- Co-authored-by: Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com> Co-authored-by: dave caruso <me@paperdave.net>
This commit is contained in:
33
docs/guides/http/fetch-unix.md
Normal file
33
docs/guides/http/fetch-unix.md
Normal file
@@ -0,0 +1,33 @@
|
||||
---
|
||||
name: Send an HTTP request over a unix domain socket with fetch
|
||||
---
|
||||
|
||||
In Bun, the `unix` option in `fetch()` lets you send HTTP requests over a [unix domain socket](https://en.wikipedia.org/wiki/Unix_domain_socket).
|
||||
|
||||
```ts
|
||||
const unix = "/var/run/docker.sock";
|
||||
|
||||
const response = await fetch("http://localhost/info", { unix });
|
||||
|
||||
const body = await response.json();
|
||||
console.log(body); // { ... }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
The `unix` option is a string that specifies the local file path to a unix domain socket. The `fetch()` function will use the socket to send the request to the server instead of using a TCP network connection. `https` is also supported by using the `https://` protocol in the URL instead of `http://`.
|
||||
|
||||
To send a `POST` request to an API endpoint over a unix domain socket:
|
||||
|
||||
```ts
|
||||
const response = await fetch("https://hostname/a/path", {
|
||||
unix: "/var/run/path/to/unix.sock",
|
||||
method: "POST",
|
||||
body: JSON.stringify({ message: "Hello from Bun!" }),
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
|
||||
const body = await response.json();
|
||||
```
|
||||
@@ -1440,21 +1440,35 @@ class ClientRequest extends OutgoingMessage {
|
||||
url = `${this.#protocol}//${this.#host}${this.#useDefaultPort ? "" : ":" + this.#port}${this.#path}`;
|
||||
}
|
||||
try {
|
||||
//@ts-ignore
|
||||
this.#fetchRequest = fetch(url, {
|
||||
const fetchOptions: any = {
|
||||
method,
|
||||
headers: this.getHeaders(),
|
||||
body: body && method !== "GET" && method !== "HEAD" && method !== "OPTIONS" ? body : undefined,
|
||||
redirect: "manual",
|
||||
verbose: !!$debug,
|
||||
signal: this[kAbortController].signal,
|
||||
proxy: proxy,
|
||||
|
||||
// Timeouts are handled via this.setTimeout.
|
||||
timeout: false,
|
||||
// Disable auto gzip/deflate
|
||||
decompress: false,
|
||||
})
|
||||
};
|
||||
|
||||
if (!!$debug) {
|
||||
fetchOptions.verbose = true;
|
||||
}
|
||||
|
||||
if (proxy) {
|
||||
fetchOptions.proxy = proxy;
|
||||
}
|
||||
|
||||
const socketPath = this.#socketPath;
|
||||
|
||||
if (socketPath) {
|
||||
fetchOptions.unix = socketPath;
|
||||
}
|
||||
|
||||
//@ts-ignore
|
||||
this.#fetchRequest = fetch(url, fetchOptions)
|
||||
.then(response => {
|
||||
const prevIsHTTPS = isNextIncomingMessageHTTPS;
|
||||
isNextIncomingMessageHTTPS = response.url.startsWith("https:");
|
||||
|
||||
@@ -3,7 +3,7 @@ import { afterAll, afterEach, expect, it } from "bun:test";
|
||||
import { mkdtempSync, realpathSync, rmSync } from "fs";
|
||||
import { tmpdir } from "os";
|
||||
import { join } from "path";
|
||||
|
||||
import { request } from "http";
|
||||
const tmp_dir = mkdtempSync(join(realpathSync(tmpdir()), "fetch.unix.test"));
|
||||
|
||||
let server_unix: Server;
|
||||
@@ -49,6 +49,41 @@ it("provide body", async () => {
|
||||
}
|
||||
});
|
||||
|
||||
it("works with node:http", async () => {
|
||||
const path = startServerUnix({
|
||||
fetch(req) {
|
||||
return new Response(req.body);
|
||||
},
|
||||
});
|
||||
|
||||
const promises = [];
|
||||
for (let i = 0; i < 20; i++) {
|
||||
const { promise, resolve } = Promise.withResolvers<string>();
|
||||
const req = request(
|
||||
{
|
||||
path: "/hello",
|
||||
method: "POST",
|
||||
socketPath: path,
|
||||
},
|
||||
res => {
|
||||
let data = "";
|
||||
res.on("data", chunk => {
|
||||
data += chunk;
|
||||
});
|
||||
res.on("end", () => {
|
||||
resolve(data);
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
req.write(String(i));
|
||||
req.end();
|
||||
promises.push(promise.then(data => expect(data).toBe(String(i))));
|
||||
}
|
||||
|
||||
await Promise.all(promises);
|
||||
});
|
||||
|
||||
it("handle redirect to non-unix", async () => {
|
||||
startServer({
|
||||
async fetch(req) {
|
||||
@@ -69,6 +104,7 @@ it("handle redirect to non-unix", async () => {
|
||||
return new Response(null, { status: 404 });
|
||||
},
|
||||
});
|
||||
|
||||
// POST with body
|
||||
for (let i = 0; i < 20; i++) {
|
||||
const response = await fetch("http://localhost/hello", { unix: path });
|
||||
|
||||
Reference in New Issue
Block a user