メインコンテンツへスキップ
paste
bin
.ca
type · paste · share
⌘
K
ドキュメント
サインイン
?
← ペーストに戻る
›
編集 / フォーク
無題のペースト
#5hU5jZccLe
public / public
新しいバージョン
作成者 @slepp
作成日 3 days ago
失効なし
3.6 KB
構文:
hew
変更により、このペーストにリンクされた新しいペーストが作成されます — 元のペーストは変更されません。
新しいバージョン
変更により、このペーストにリンクされた新しいペーストが作成されます — 元のペーストは変更されません。
タイトル(任意)
ファイル名
構文
hew
text
bash
c
cpp
css
diff
dockerfile
go
html
ini
java
javascript
json
kotlin
lua
makefile
markdown
nginx
php
python
ruby
rust
shellscript
sql
swift
toml
typescript
xml
yaml
可視性
パブリックフィード
アクセス
public
失効
7日
10分
1時間
1日
7日
30日
90日
カスタム…
カスタム失効
変更メモ
(任意)
このペーストはパブリックフィードに表示されます。リンクを知っている人だけに見せたい場合は可視性を変更してください。
新しいバージョンを作成
キャンセル
貼り付けるか入力…
// Multi-actor TCP -> HTTP transform proxy (Hew, v0.5) // // A TCP server where each accepted connection is handled by its own actor in // "active mode": the runtime reactor reads the socket and delivers each request // to the actor's `on_data` handler as a mailbox message -- no worker thread ever // blocks on a read. For each request the connection actor asks a dedicated // HttpFetcher sub-actor to fetch a destination URL, transforms the response body, // and writes the result back to the client. Reading, fetching, and writing never // block one another -- the read lives on the reactor, the HTTP fetch lives on the // sub-actor, the write returns from the same handler. // // Verified end-to-end: a TCP client sent "http://127.0.0.1:8000/index.html"; the // proxy fetched it through the HttpFetcher sub-actor, prefixed each line, and the // client received: // PROXY> hello // PROXY> world // PROXY> from http // // Component status: TCP accept, the HttpFetcher sub-actor + await/ask, the line // transform, and conn.send_string all run on the v0.5 trunk today; the active-mode // `conn.attach(handler)` registration rides one in-flight gate refinement. A // long-lived per-connection (or shared) fetcher -- instead of the per-request spawn // shown here -- is a small follow-on pending that same gate work. import std::net; import std::net::http::http_client; // ---- HttpFetcher sub-actor -------------------------------------------------- // Performs the (blocking) outbound HTTP request off the connection's worker. // Replies to a `fetch(url)` ask with the body, or an error string. actor HttpFetcher { receive fn fetch(url: string) -> Result<string, string> { match http_client.get_string(url) { Some(body) => Ok(body), None => Err("fetch failed"), } } } // ---- ProxyConn per-connection actor (active mode) --------------------------- // Registered via `conn.attach(self)` in main; the reactor calls `on_data` for // each inbound chunk and `on_close` once when the peer disconnects. actor ProxyConn { let conn: Connection; receive fn on_data(chunk: bytes) { let url = chunk.to_string().trim(); if url.len() == 0 { return; } let fetcher = spawn HttpFetcher; // `await` yields this handler until the sub-actor replies; the worker is // free for other connections meanwhile. let reply = await fetcher.fetch(url); match reply { Ok(inner) => match inner { Ok(body) => conn.send_string(transform_body(body)), Err(e) => conn.send_string("ERROR: " + e + "\n"), }, Err(_) => conn.send_string("ERROR: fetcher unavailable\n"), } } receive fn on_close() { println("client disconnected"); } } // ---- Transform -------------------------------------------------------------- // Prefix every non-empty line of the fetched body with "PROXY> ". fn transform_body(body: string) -> string { let lines = body.split("\n"); var out = ""; var i = 0; let n = lines.len(); while i < n { let line = lines.get(i); if line.len() > 0 { out = out + "PROXY> " + line + "\n"; } i = i + 1; } out } // ---- Entry point ------------------------------------------------------------ fn main() { let listener = net.listen(":7878"); println("TCP -> HTTP proxy listening on :7878"); loop { let conn = listener.accept(); let handler = spawn ProxyConn(conn: conn); conn.attach(handler); // reactor now drives on_data/on_close for this connection } }