From 77459ec415a44ab90ed5b11ec6165f0dd0fe5e37 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Mon, 2 Jan 2023 00:14:25 +0000 Subject: [PATCH] add h2c example --- actix-http/examples/h2c-detect.rs | 54 +++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 actix-http/examples/h2c-detect.rs diff --git a/actix-http/examples/h2c-detect.rs b/actix-http/examples/h2c-detect.rs new file mode 100644 index 000000000..e1491324b --- /dev/null +++ b/actix-http/examples/h2c-detect.rs @@ -0,0 +1,54 @@ +//! 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::{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?; + + 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::Error>((io, proto, peer_addr)) + }) + .and_then( + HttpService::build() + .finish(|_req: Request| async move { + Ok::<_, Infallible>(Response::build(StatusCode::OK).body("Hello!")) + }) + .map_err(|err| { + tracing::error!("{}", err); + io::Error::new(io::ErrorKind::Other, "http service dispatch error") + }), + ) + })? + .workers(2) + .run() + .await +}