Workers ランタイムは、Workers からアウトバウンドの TCP 接続 ↗ を作成するための connect() API を提供します。
多くのアプリケーション層プロトコルは、Transmission Control Protocol(TCP)の上に構築されています。SSH、MQTT、SMTP、FTP、IRC、および MySQL、PostgreSQL、MongoDB を含むほとんどのデータベース用ワイヤプロトコルは、動作するために基盤となる TCP ソケット API が必要です。
connect() 関数は、データの 読み取り可能 ストリームと 書き込み可能 ストリームの両方を持つ TCP ソケットを返します。接続が開いている限り、継続的にデータの読み書きができます。
connect() は Runtime API として提供され、cloudflare:sockets から connect 関数をインポートして使います。手順は、Node.js で組み込みモジュールをインポートする場合と似ています。次のコードブロックは、TCP ソケットを作成し、書き込み、ソケットの読み取り側をレスポンスとして返す例です。
import { connect } from 'cloudflare:sockets';
export default {
async fetch(req): Promise<Response> {
const gopherAddr = { hostname: "gopher.floodgap.com", port: 70 };
const url = new URL(req.url);
try {
const socket = connect(gopherAddr);
const writer = socket.writable.getWriter()
const encoder = new TextEncoder();
const encoded = encoder.encode(url.pathname + "\r\n");
await writer.write(encoded);
await writer.close();
return new Response(socket.readable, { headers: { "Content-Type": "text/plain" } });
} catch (error) {
return new Response("Socket connection failed: " + error, { status: 500 });
}
}
} satisfies ExportedHandler;connect(address: SocketAddress | string, options?: optional SocketOptions):Socketconnect()は、接続先のホスト名とポート番号を指定する URL 文字列またはSocketAddressと、省略可能な設定オブジェクトSocketOptionsを受け取ります。戻り値はSocketのインスタンスです。
-
hostnamestring- 接続先のホスト名です。例:
cloudflare.com。
- 接続先のホスト名です。例:
-
portnumber- 接続先のポート番号です。例:
5432。
- 接続先のポート番号です。例:
-
secureTransport"off" | "on" | "starttls" — 既定値はoff- TCP ソケット作成時に TLS ↗ を使うかどうかを指定します。
off— TLS を使いません。on— TLS を使います。starttls— 最初は TLS を使わず、startTls()を呼んで TLS へアップグレードできます。
-
allowHalfOpenboolean — 既定値はfalse- EOF(end-of-file)時に、TCP ソケットの書き込み側を自動で閉じるかどうかを決めます。
falseの場合、EOF 時に書き込み側は自動で閉じます。trueの場合、EOF 時も書き込み側は開いたままです。 - Node.js の
netモジュール ↗ が提供するオプションと似ており、それを使うコードとの相互運用に役立ちます。
- EOF(end-of-file)時に、TCP ソケットの書き込み側を自動で閉じるかどうかを決めます。
-
remoteAddressstring | null- ソケットが接続しているリモートピアのアドレスです。常に設定されるとは限りません。
-
localAddressstring | null- このソケットのローカルネットワークエンドポイントのアドレスです。常に設定されるとは限りません。
-
readable: ReadableStream- TCP ソケットの読み取り側を返します。
-
writable: WritableStream- TCP ソケットの書き込み側を返します。
- 返される
WritableStreamが受け付けるチャンクは、Uint8Arrayまたはそのビューだけです。
-
openedPromise<SocketInfo>- ソケット接続が確立すると解決し、ソケットでエラーが起きると拒否される Promise です。
-
closedPromise<void>- ソケットが閉じると解決し、ソケットでエラーが起きると拒否される Promise です。
-
close()Promise<void>- TCP ソケットを閉じます。読み取りストリームと書き込みストリームの両方を強制的に閉じます。
-
startTls(): Socket- 非セキュアなソケットを、TLS を使うセキュアなソケットへアップグレードし、新しい Socket を返します。
startTls()を呼ぶには、最初にconnect()でソケットを作成するときにsecureTransportをstarttlsに設定する必要があります。
- 非セキュアなソケットを、TLS を使うセキュアなソケットへアップグレードし、新しい Socket を返します。
データベースやメールサーバーを含む多くの TCP ベースのシステムでは、接続時に便宜的 TLS(StartTLS ↗ とも呼ばれます)を使う必要があります。このパターンでは、クライアントは最初に TLS なしの非セキュアな TCP ソケットを作り、その後 TLS を使うセキュアな TCP ソケットへアップグレードします。connect() API では、TLS を使う新しい Socket インスタンスを返す startTls() メソッドで、この手順を簡単にできます。
import { connect } from "cloudflare:sockets"
const address = {
hostname: "example-postgres-db.com",
port: 5432
};
const socket = connect(address, { secureTransport: "starttls" });
const secureSocket = socket.startTls();startTls()は、最初の TCP ソケット作成時にsecureTransportをstarttlsに設定した場合にだけ呼べます。startTls()を呼ぶと、最初のソケットは閉じられ、以降は読み書きできません。上の例では、startTls()の呼び出し後は、新しく作ったsecureSocketを使います。元のソケットから作った既存のリーダーとライターは使えなくなります。新しく作ったsecureSocketからリーダーとライターを作り直す必要があります。- 既存のソケットに対する
startTls()の呼び出しは、1 回だけにしてください。
新しい TCP ソケットの作成、ソケットからの読み取り、ソケットへの書き込みでエラーを処理するには、これらの呼び出しを try...catch ↗ 文で囲みます。次の例は、Google.com へ接続を開き、HTTP リクエストを開始してレスポンスを返します。失敗して例外が投げられた場合は、500 レスポンスを返します。
import { connect } from 'cloudflare:sockets';
const connectionUrl = { hostname: "google.com", port: 80 };
export interface Env { }
export default {
async fetch(req, env, ctx): Promise<Response> {
try {
const socket = connect(connectionUrl);
const writer = socket.writable.getWriter();
const encoder = new TextEncoder();
const encoded = encoder.encode("GET / HTTP/1.0\r\n\r\n");
await writer.write(encoded);
await writer.close();
return new Response(socket.readable, { headers: { "Content-Type": "text/plain" } });
} catch (error) {
return new Response(`Socket connection failed: ${error}`, { status: 500 });
}
}
} satisfies ExportedHandler<Env>;ソケットの close() を呼ぶと、TCP 接続を閉じられます。読み取り側と書き込み側の両方が閉じます。
import { connect } from "cloudflare:sockets"
const socket = connect({ hostname: "my-url.com", port: 70 });
const reader = socket.readable.getReader();
socket.close();
// After close() is called, you can no longer read from the readable side of the socket
const reader = socket.readable.getReader(); // This fails- Cloudflare の IP レンジ ↗ へのアウトバウンド TCP ソケットはブロックされます。
- TCP ソケットをグローバルスコープで作成してリクエスト間で共有することはできません。常にハンドラー(例:
fetch()、scheduled()、queue())またはalarm()の中で作成してください。 - 開いている TCP ソケットは、同時に開ける 接続数の上限 にカウントされます。
- Durable Object 内で作成した開いている TCP ソケットは、Durable Object をメモリ上に保ち、接続あたり最大 15 分間の duration 課金が発生します。15 分後、ソケットは Durable Object を生存させなくなり(ソケット自体は動作を続けます)、標準の退避ルール が再開されます。
- 既定では、Workers はポート
25へのアウトバウンド TCP 接続を作成して SMTP メールサーバーへメールを送れません。Cloudflare Email Workers が、メールの処理と転送の API を提供します。 - インバウンド TCP 接続の処理は 近日対応予定 ↗ です。現時点では、
CONNECTHTTP メソッドなどを使って Worker へインバウンド TCP 接続を行うことはできません。
TCP ソケットを使うときに表示されることがある一般的なエラーメッセージ、その意味、対処方法を確認します。
ソケットが、許可されていないアドレスへ接続しようとしています。許可されないアドレスの例は、Cloudflare IP、localhost、プライベートネットワーク IP です。
ポート 80 または 443 のアドレスへ接続して HTTP リクエストを送る必要がある場合は、fetch を使ってください。
ソケットが、アウトバウンド接続を開始した Worker 自身へ戻っています。つまり、Worker が自分自身へ接続しています。現時点ではサポートされていません。
ソケットがポート 25 のアドレスへ接続しようとしています。このポートは通常、SMTP メールサーバーで使われます。Workers はポート 25 へのアウトバウンド接続を作成できません。代わりに Cloudflare Email Workers の利用を検討してください。