//! An example that supports automatic selection of plaintext h1/h2c connections. //! //! Notably, both the following commands will work. //! ```console //! $ curl --http1.1 'http://localhost:8080/' //! $ curl --http2-prior-knowledge 'http://localhost:8080/' //! ``` use std::{convert::Infallible, io}; use actix_http::{error::DispatchError, HttpService, Protocol, Request, Response, StatusCode}; use actix_rt::net::TcpStream; use actix_server::Server; use actix_service::{fn_service, ServiceFactoryExt}; const H2_PREFACE: &[u8] = b"PRI * HTTP/2"; #[actix_rt::main] async fn main() -> io::Result<()> { env_logger::init_from_env(env_logger::Env::new().default_filter_or("info")); Server::build() .bind("h2c-detect", ("127.0.0.1", 8080), || { fn_service(move |io: TcpStream| async move { let mut buf = [0; 12]; io.peek(&mut buf).await.map_err(DispatchError::Io)?; let proto = if buf == H2_PREFACE { tracing::info!("selecting h2c"); Protocol::Http2 } else { tracing::info!("selecting h1"); Protocol::Http1 }; let peer_addr = io.peer_addr().ok(); Ok((io, proto, peer_addr)) }) .and_then(HttpService::build().finish(|_req: Request| async move { Ok::<_, Infallible>(Response::build(StatusCode::OK).body("Hello!")) })) })? .workers(2) .run() .await }