I'm very new to the Axum / Tower / Hyper frameworks and want to build a simple hello world example with the caveat that it should listen on two different ports at the same time.
These listeners should each have their own routes associated with them. I would like to do this as the program I'm building will listen on a public IP(HTTPS) for client requests, while listening on a different port on an internal IP for microservice communications (obviously with an extra layer of authentication on top of it).
However all the tutorials immediately jump to Axum::Serve() with a single listener and none of the multi listener examples seem to work.
This isn't what you asked for, but it's very common to run things behind a reverse proxy, that handles stuff like TLS, logging, some security checks, whatever. So you could just have that proxy filter for the public routes.
Good suggestion, but Serve<tokio::net::TcpListener, Router, Router> isn't a future and as such can't be spawned by tokio::spawn(). Am I missing something obvious here?
Valid remark, but I believe that externalising these security measures to the reverse proxy adds maintenance overhead and could easily result in errors (forget to block a new API call, make a typo, ...).
Plus I would like to perform TLS client side authentication for the microservices communications, but not for the public API.
// axum = "0.8.1"
// tokio = { version = "1.43.0", features = ["full"] }
use axum::{Router, routing::get};
#[tokio::main]
async fn main() {
let t0 = tokio::task::spawn(async move { serve(3000).await });
let t1 = tokio::task::spawn(async move { serve(3001).await });
let _ = tokio::join!(t0, t1);
}
async fn serve(port: u16) {
let router = Router::new().route("/", get(|| async { "Hello, World!" }));
let listener = tokio::net::TcpListener::bind(&format!("0.0.0.0:{port}"))
.await
.unwrap();
axum::serve(listener, router).await.unwrap();
}
This isn't exactly what you want, because you said that the second service would have different layers (like authentication). So I guess you'd have serve1() and serve2() that create the two different services you need.