Skip to content

Commit 524a6e5

Browse files
LtadrianAdrian Gracia
andauthored
SQC-652 Implement Hyperdrive binding TLS miniflare proxy. This will (#11219)
allow for wrangler dev hyperdrive bindings to connect to external databases that require TLS. - Supports upgrading TLS connection to database by setting sslmode=prefer or sslmode=require or sslmode=disable in localConnectionString - Default sslmode is disable - Adds integration tests to miniflare test suite Co-authored-by: Adrian Gracia <agracia@cloudflare.com>
1 parent 1674958 commit 524a6e5

File tree

11 files changed

+890
-73
lines changed

11 files changed

+890
-73
lines changed

.changeset/cute-plums-relate.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
"miniflare": minor
3+
"wrangler": minor
4+
---
5+
6+
Implement Hyperdrive binding TLS miniflare proxy. This will allow for wrangler dev hyperdrive bindings to connect to external
7+
databases that require TLS.

fixtures/vitest-pool-workers-examples/hyperdrive/global-setup.ts

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,25 @@ import assert from "node:assert";
22
import events from "node:events";
33
import net from "node:net";
44
import util from "node:util";
5-
import type { GlobalSetupContext } from "vitest/node";
5+
import type { TestProject } from "vitest/node";
6+
7+
export const POSTGRES_SSL_REQUEST_PACKET = Buffer.from([
8+
0x00, 0x00, 0x00, 0x08, 0x04, 0xd2, 0x16, 0x2f,
9+
]);
610

711
// Global setup runs inside Node.js, not `workerd`
8-
export default async function ({ provide }: GlobalSetupContext) {
12+
export default async function ({ provide }: TestProject) {
913
// Start echo server on random port
10-
const server = net.createServer((socket) => socket.pipe(socket));
14+
const server = net.createServer((socket) => {
15+
socket.on("data", (chunk) => {
16+
// on postgres ssl request packet respond with 'N' to indicate no SSL support
17+
if (POSTGRES_SSL_REQUEST_PACKET.equals(chunk)) {
18+
socket.write("N");
19+
} else {
20+
socket.write(chunk);
21+
}
22+
});
23+
});
1124
const listeningPromise = events.once(server, "listening");
1225
server.listen(0, "127.0.0.1");
1326
await listeningPromise;

fixtures/vitest-pool-workers-examples/hyperdrive/src/index.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,14 @@ export default <ExportedHandler<Env>>{
44
if (request.body === null) return new Response();
55

66
const socket = env.ECHO_SERVER_HYPERDRIVE.connect();
7-
await request.body.pipeTo(socket.writable);
8-
return new Response(socket.readable);
7+
const writer = socket.writable.getWriter();
8+
9+
// parse body
10+
const value = await request.text();
11+
await writer.write(new TextEncoder().encode(value));
12+
const result = await socket.readable.getReader().read();
13+
14+
writer.close();
15+
return new Response(result.value);
916
},
1017
};

packages/miniflare/src/index.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ import {
8383
ServiceDesignatorSchema,
8484
} from "./plugins/core";
8585
import { InspectorProxyController } from "./plugins/core/inspector-proxy";
86+
import { HyperdriveProxyController } from "./plugins/hyperdrive/hyperdrive-proxy";
8687
import { imagesLocalFetcher } from "./plugins/images/fetcher";
8788
import {
8889
Config,
@@ -948,6 +949,9 @@ export class Miniflare {
948949
#maybeInspectorProxyController?: InspectorProxyController;
949950
#previousRuntimeInspectorPort?: number;
950951

952+
#hyperdriveProxyController: HyperdriveProxyController =
953+
new HyperdriveProxyController();
954+
951955
constructor(opts: MiniflareOptions) {
952956
// Split and validate options
953957
const [sharedOpts, workerOpts] = validateOptions(opts);
@@ -1720,6 +1724,7 @@ export class Miniflare {
17201724
unsafeEphemeralDurableObjects,
17211725
queueProducers,
17221726
queueConsumers,
1727+
hyperdriveProxyController: this.#hyperdriveProxyController,
17231728
};
17241729
for (const [key, plugin] of this.#mergedPluginEntries) {
17251730
const workerOptions = this.#getWorkerOptsForPlugin(key, workerOpts);
@@ -2689,6 +2694,9 @@ export class Miniflare {
26892694
// Unregister workers from dev registry and stop the file watcher
26902695
await this.#devRegistry.dispose();
26912696

2697+
// shutdown hyperdrive proxies if any exist
2698+
await this.#hyperdriveProxyController.dispose();
2699+
26922700
// Remove from instance registry as last step in `finally`, to make sure
26932701
// all dispose steps complete
26942702
maybeInstanceRegistry?.delete(this);

0 commit comments

Comments
 (0)