New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Outbound TCP Sockets #324
Outbound TCP Sockets #324
Conversation
@zebp do you know what is going on with the build here? |
I suspect it's because of the target that I see historic issues (2017) that Mio doesn't support being compiled to WASM, unsure if it has changed since then. |
I couldn't really find any reasons why Mio would be compiled with all of the features disabled, and it turns out that since this project is using Adding [workspace]
members = [
"worker",
"worker-build",
"worker-macros",
"worker-sandbox",
"worker-sys",
]
+ resolver = "2" |
Thanks, I'll try to dig into what is happening here, I've built a worker with this change, so somehow targeting Wasm in that context is not an issue. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Really cool! Left a few comments. Thank you for picking this up.
Some notes from testing:
Thoughts on the third one @zebp? Have you run into this before? |
Just wanted to |
We run into this quite a bit. Because the runtime only ever has one thread of execution for the Worker and we don't use |
I do have this working with Cargo.toml hyper = { version="0.14", features=['http1', 'client'], default-fetaures=false }
tokio = {version = "1.0", default-features=false, features=['io-util', 'macros']} main.rs async fn make_request(
mut sender: hyper::client::conn::SendRequest<hyper::Body>,
request: hyper::Request<hyper::Body>,
) -> Response {
let hyper_response = sender.send_request(request).await.expect("send_request");
let buf = hyper::body::to_bytes(hyper_response)
.await
.expect("collect body");
let text = std::str::from_utf8(&buf).expect("utf-8");
let mut response = Response::ok(text).unwrap();
response
.headers_mut()
.append("Content-Type", "text/html")
.ok();
response
}
#[event(fetch)]
async fn main(_req: Request, _env: Env, _ctx: Context) -> Result<Response> {
set_panic_hook();
console_log!("Connecting...");
let socket = Socket::builder().connect("example.com", 80)?;
console_log!("Got socket!");
let (request_sender, connection) = hyper::client::conn::handshake(socket)
.await
.expect("handshake");
let request = hyper::Request::builder()
// We need to manually add the host header because SendRequest does not
.header("Host", "example.com")
.method("GET")
.body(hyper::Body::from(""))
.expect("build request");
tokio::select!(
res = connection => {
console_error!("Connection exited: {:?}", res);
Err(worker::Error::RustError("Connection exited".to_string()))
},
response = make_request(request_sender, request) => {
Ok(response)
}
)
} |
Full |
I think I'm pretty close to having https://github.com/kflansburg/hyper-on-workers/blob/client/src/lib.rs |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mostly looks good, some nits in terms of style but we also need to add some testing via worker-sandbox
. This will probably include a test that just spawns a tcp listener that'll expect a connection from the worker, which should be simple but it might involve us upgrading to miniflare 3 for the janky test suite.
Manual test for now located here: https://github.com/kflansburg/workers-rs-sockets-test |
Still need to do another review pass but I played around with this to see if I could get tokio-postgres working and I was able to! The changes necessary to tokio-postgres are here if interested. This is really cool use futures_util::FutureExt;
use tokio_postgres::{Config, NoTls};
use worker::*;
#[event(start)]
fn init() {
console_error_panic_hook::set_once();
}
#[event(fetch)]
async fn main(req: Request, env: Env, _ctx: Context) -> Result<Response> {
let router = Router::new().get_async("/", |_, ctx| async move {
let socket = Socket::builder()
.secure_transport(SecureTransport::Off)
.connect("0.0.0.0", 5432)?;
let (client, connection) = Config::new()
.user("postgres")
.password("postgres")
.dbname("postgres")
.connect_raw(socket, NoTls)
.await
.unwrap();
let conn = connection.map(|r| r.unwrap());
wasm_bindgen_futures::spawn_local(conn);
let rows = client.query("select 10;", &[]).await.unwrap();
let value: i32 = rows[0].get(0);
Response::ok(format!("Hello from Rust! {}", value))
});
router.run(req, env).await
} |
Awesome, I’m really excited about this! |
read
andwrite