🙆‍♀️

pg-cloudflareでソケット接続

2024/04/07に公開

pg-cloudflareはnode-postgres内部のmodule。Cloudflare Workersでpgを動作させるために追加された。

pgがWorkerdランタイムをサポートするとそれを使っている各種ORMも動かることができる

https://github.com/brianc/node-postgres/pull/2971

これをnode-mysql2からも利用するように開発が進めらているので、Cloudflare Workersでmysql(をサポートするORMも)に接続できるようになると思われる

https://github.com/sidorares/node-mysql2/pull/2289

今後Workerdでソケット接続するプログラムで活用されるようになりそうだなと思ったので使い方を覚えた

npm create cloudflare@latest
npm i pg-cloudflare

/?url=http://amazon.comでURLを渡すとHTTP 1.1でGETするプログラムを作ってみる

curl "http://localhost:8787/?url=http://amazon.com"
HTTP/1.1 301 Moved Permanently
Server: Server
Date: Sun, 07 Apr 2024 07:44:34 GMT
Content-Type: text/html
Content-Length: 163
Connection: keep-alive
Location: https://amazon.com/

<html>
<head><title>301 Moved Permanently</title></head>
<body>
<center><h1>301 Moved Permanently</h1></center>
<hr><center>Server</center>
</body>
</html>
src/index.ts
import { CloudflareSocket as Socket } from 'pg-cloudflare';

type Env = Record<string, string>;

export default {
	async fetch(request: Request, env: Env, ctx: ExecutionContext) {
		const p = new URLSearchParams(request.url.split("?")[1]);
		const url = new URL(p.get("url") ?? 'http://example.com');

		const isSecure = url.protocol === 'https:';
		const socket = new Socket(isSecure);

		const { readable, writable } = new TransformStream();

		await socket.connect(isSecure ? 443 : 80, url.hostname, () => {
			socket.write('GET / HTTP/1.1\r\n');
			socket.write(`Host: ${url.hostname}\r\n`);
			socket.write('Connection: close\r\n');
			socket.write('\r\n');
		});

		socket.on('data', async (data: Buffer) => {
			const writer = writable.getWriter();
			const encoder = new TextEncoder();
			await writer.write(encoder.encode(data.toString()));
			writer.close();
		});

		return new Response(readable);
	},
};
  • CloudflareSocketのコンストラクタではssl=true/falseを渡す
  • このクラスはEventEmitterを継承している
  • pg-cloudflareはworkerdで動く時だけこの実装に差し替えられる

https://github.com/brianc/node-postgres/blob/3cde785e3806ee8dc999cb145e3e91ff7bd9b8aa/packages/pg/lib/stream.js#L5-L13

Discussion