Add example for multiple listen addrs (#1179)

This commit is contained in:
Kartavya Vashishtha 2022-07-21 00:03:12 +05:30 committed by GitHub
parent a3cf025d54
commit cf09f62a1a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 70 additions and 0 deletions

View file

@ -0,0 +1,10 @@
[package]
name = "listen-multiple-addrs"
version = "0.1.0"
edition = "2021"
publish = false
[dependencies]
axum = { path = "../../axum" }
hyper = { version = "0.14", features = ["full"] }
tokio = { version = "1", features = ["full"] }

View file

@ -0,0 +1,60 @@
//! Showcases how listening on multiple addrs is possible by
//! implementing Accept for a custom struct.
//!
//! This may be useful in cases where the platform does not
//! listen on both IPv4 and IPv6 when the IPv6 catch-all listener is used (`::`),
//! [like older versions of Windows.](https://docs.microsoft.com/en-us/windows/win32/winsock/dual-stack-sockets)
use axum::{routing::get, Router};
use hyper::server::{accept::Accept, conn::AddrIncoming};
use std::{
net::{Ipv4Addr, Ipv6Addr, SocketAddr},
pin::Pin,
task::{Context, Poll},
};
#[tokio::main]
async fn main() {
let app = Router::new().route("/", get(|| async { "Hello, World!" }));
let localhost_v4 = SocketAddr::new(Ipv4Addr::LOCALHOST.into(), 8080);
let incoming_v4 = AddrIncoming::bind(&localhost_v4).unwrap();
let localhost_v6 = SocketAddr::new(Ipv6Addr::LOCALHOST.into(), 8080);
let incoming_v6 = AddrIncoming::bind(&localhost_v6).unwrap();
let combined = CombinedIncoming {
a: incoming_v4,
b: incoming_v6,
};
axum::Server::builder(combined)
.serve(app.into_make_service())
.await
.unwrap();
}
struct CombinedIncoming {
a: AddrIncoming,
b: AddrIncoming,
}
impl Accept for CombinedIncoming {
type Conn = <AddrIncoming as Accept>::Conn;
type Error = <AddrIncoming as Accept>::Error;
fn poll_accept(
mut self: Pin<&mut Self>,
cx: &mut Context<'_>,
) -> Poll<Option<Result<Self::Conn, Self::Error>>> {
if let Poll::Ready(Some(value)) = Pin::new(&mut self.a).poll_accept(cx) {
return Poll::Ready(Some(value));
}
if let Poll::Ready(Some(value)) = Pin::new(&mut self.b).poll_accept(cx) {
return Poll::Ready(Some(value));
}
Poll::Pending
}
}