feat: add custom socket transport support for Postgres and MySQL#4187
feat: add custom socket transport support for Postgres and MySQL#4187jowparks wants to merge 1 commit intolaunchbadge:mainfrom
Conversation
cbedb56 to
9655878
Compare
Add `connect_socket()` methods to `PgConnection` and `MySqlConnection` that accept any pre-connected socket implementing the `Socket` trait. This enables using custom transport layers (e.g., vsock for AWS Nitro Enclaves, QUIC, or other non-TCP/UDS transports) without forking sqlx. Re-export `Socket` and `ReadBuf` traits from `sqlx::net` so users can implement custom socket types.
9655878 to
f7dcf2d
Compare
| /// Networking traits for custom transport implementations. | ||
| pub mod net { | ||
| pub use sqlx_core::io::ReadBuf; | ||
| pub use sqlx_core::net::Socket; |
There was a problem hiding this comment.
The Socket trait was never meant for public use, so I'm really uncomfortable just exporting it without a proper design pass. I don't think it's the right interface to expose anyway because it inherently requires a bespoke implementation.
Instead, I think we should accept a type that implements the AsyncRead + AsyncWrite traits from either tokio or futures-io. I sort of did this with PgCopyIn::read_from() but I'm not really happy with how I did it, since enabling the runtime-tokio feature would break code that's passing an impl from futures-io.
We could either get around this by just having two different methods that use each set of traits, or a single method using a sealed trait that's implemented for adapter types.
I'm thinking I'm leaning towards the two different methods, though.
| Ok(Self::establish_with_stream(stream, options)) | ||
| } | ||
|
|
||
| fn establish_with_stream(stream: MySqlStream, options: &MySqlConnectOptions) -> Self { |
There was a problem hiding this comment.
This should just be called with_stream() since establish implies some sort of action taking place.
| pub async fn connect_socket<S: Socket, Ws: WithSocket>( | ||
| socket: S, | ||
| with_socket: Ws, | ||
| ) -> crate::Result<Ws::Output> { | ||
| Ok(with_socket.with_socket(socket).await) | ||
| } | ||
|
|
There was a problem hiding this comment.
This function doesn't add anything.
Summary
Add
connect_socket()methods toPgConnectionandMySqlConnectionthat accept any pre-connected socket implementing theSockettrait. This enables using custom transport layers without forking sqlx.Motivation: In environments like AWS Nitro Enclaves, vsock is the only available networking transport. Currently, sqlx hardcodes its connection establishment to TCP and Unix domain sockets, making it impossible to use with non-standard transports without forking. This PR makes the
Sockettrait usable as a public extension point.Before / After
Before
There is no way to provide a custom socket to sqlx. The only connection paths are TCP and Unix domain sockets, hardcoded in
PgStream::connect()andMySqlConnection::establish():After
Users can connect over any transport by providing a pre-connected socket:
Changes
New public API
PgConnection::connect_socket(socket, &options)— connect to PostgreSQL over anySocketimplMySqlConnection::connect_socket(socket, &options)— connect to MySQL over anySocketimplsqlx::net::Socket— re-exported trait for implementing custom transportssqlx::net::ReadBuf— re-exported trait needed bySocketimplementationsFiles changed
sqlx-core/src/net/socket/mod.rs: Addconnect_socket()helper functionsqlx-core/src/net/mod.rs: Re-exportconnect_socketsqlx-postgres/src/connection/stream.rs: AddPgStream::connect_socket()sqlx-postgres/src/connection/establish.rs: Refactorestablish()to extractestablish_with_stream(), addestablish_with_socket()sqlx-postgres/src/connection/mod.rs: Add publicPgConnection::connect_socket()sqlx-mysql/src/connection/establish.rs: Refactor to extractestablish_with_stream(), addestablish_with_socket()sqlx-mysql/src/connection/mod.rs: Add publicMySqlConnection::connect_socket()sqlx-mysql/src/options/connect.rs: Extractconfigure_session()fromConnectOptions::connect()for reuse byconnect_socketsrc/lib.rs: Addsqlx::netmodule re-exportingSocketandReadBufDesign decisions
PgConnectOptions/MySqlConnectOptionsderiveClone + Debug, which prevents storingBox<dyn Socket>. A separateconnect_socket()method is cleaner and more ergonomic.MaybeUpgradeTls/DoHandshakeflow, so TLS upgrade negotiation works out of the box.establish_with_stream()to share code between the TCP/UDS path and the custom socket path. No behavioral changes to existing code.Sockettrait.Use cases
tokio-vsock)Checklist
cargo check --all-featurespasses