Skip to content

Conversation

@SabrinaJewson
Copy link
Contributor

This example bridges TlsListener with axum::serve.

One can also bypass axum::serve and use the Router with Hyper's serve_connection API directly. The main advantages of using axum::serve are that

  • graceful shutdown is made easy with axum's .with_graceful_shutdown API, and
  • the Hyper server is configured by axum itself, allowing options specific to axum to be set (for example, axum currently enables the CONNECT protocol in order to support HTTP/2 websockets).

There are a couple slight papercuts I encountered when writing this example. In particular:

  • TlsListener provides no way to access the underlying listener, meaning .local_addr() has to be implemented by caching the address instead of calling a hypothetical .inner.listener().local_addr(). This seems fairly easy to fix.
  • Because tls_listener::AsyncAccept is poll-based while axum’s Listener trait is async-based, it is not possible to easily bridge axum's existing error-handling logic with this crate; hence, I opted to simply copy-paste the code. Maybe it would be nice if axum exposed handle_connection_error in its public API.

@SabrinaJewson SabrinaJewson changed the title Axum Add axum example Mar 7, 2025
@tmccombs tmccombs merged commit fd3793a into tmccombs:main Mar 12, 2025
13 checks passed
@tmccombs
Copy link
Owner

Thanks for adding this!

TlsListener provides no way to access the underlying listener, meaning .local_addr() has to be implemented by caching the address instead of calling a hypothetical .inner.listener().local_addr(). This seems fairly easy to fix.

Yep. Done in #55

Because tls_listener::AsyncAccept is poll-based while axum’s Listener trait is async-based, it is not possible to easily bridge axum's existing error-handling logic with this crate

Well, that's a little annoying.

I don't think it would be too difficult to make an adapter from something that returns Futures (like axum's Listener trait) to AsyncAccept, that just stores and polls the next future.

@SabrinaJewson
Copy link
Contributor Author

SabrinaJewson commented Mar 12, 2025

I don't think it would be too difficult to make an adapter from something that returns Futures (like axum's Listener trait) to AsyncAccept, that just stores and polls the next future.

The probem is that such a type would have to be self-referential, since the future returned by axum’s accept borrows from self. Your best bet would be using a boxed stream with async_stream, or spawning the Listener in a task and receiving the results via an mpsc::channel. I started on the latter solution, but I thought it probably wasn’t worth the effort over copying and pasting.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants