hyper - 底层HTTP实现

hyper 是一个用Rust编写的 HTTP 实现,支持HTTP/1和HTTP/2,支持异步Rust,并且同时提供了服务端和客户端的API支持。

服务端

添加依赖

$ cargo add hyper --features full
$ cargo add tokio --features full

服务端

use hyper::service::{make_service_fn, service_fn};
use hyper::{Body, Request, Response, Server};
use hyper::{Method, StatusCode};
use std::convert::Infallible;
use std::net::SocketAddr;
use std::str::FromStr;

// service 函数,使用这个函数实现处理请求并返回响应的逻辑
async fn route(req: Request<Body>) -> Result<Response<Body>, Infallible> {
    let mut response = Response::new(Body::empty());

    match (req.method(), req.uri().path()) {
        (&Method::GET, "/") => {
            *response.body_mut() = Body::from("Try POSTing data to /echo");
        }
        (&Method::POST, "/echo") => {
            *response.body_mut() = req.into_body();
        }
        _ => {
            *response.status_mut() = StatusCode::NOT_FOUND;
        }
    };

    Ok(response)
}

#[tokio::main]
async fn main() {
    // 监听 8080 端口
    let addr = SocketAddr::from_str("127.0.0.1:8080").unwrap();

    // 每个连接都需要一个处理函数,make_service_fn 生成 AddrStream 的处理函数 
    let make_svc = make_service_fn(|_conn| async {
        // service_fn 将函数转换为 service 方法 
        Ok::<_, Infallible>(service_fn(route))
    });

    let server = Server::bind(&addr).serve(make_svc);

    if let Err(e) = server.await {
        eprintln!("server error: {}", e);
    }
}

客户端

use hyper::body::HttpBody;
use hyper::Body;
use hyper::Client;
use hyper::Method;
use hyper::Request;

#[tokio::main]
async fn main() {
    let client = Client::new();
    let request = Request::builder()
        .method(Method::POST)
        .uri("http://127.0.0.1:8080/echo")
        .body(Body::from("version"))
        .unwrap();
    let mut response = client.request(request).await.unwrap();

    let body = response.body_mut();
    let data = body.data().await.unwrap().unwrap();
    println!("{}", data.escape_ascii());
}

TLS 支持

添加 hyper-tls 依赖

$ cargo add hyper-tls

实现

use hyper::body::HttpBody;
use hyper::Body;
use hyper::Client;
use hyper::Method;
use hyper::Request;
use hyper_tls::HttpsConnector;

#[tokio::main]
async fn main() {
    // 创建 TLS HttpsConnector 
    let tlscon = HttpsConnector::new();
    // 使用 TLS HttpsConnector 构建 Client
    let client = Client::builder().build(tlscon);

    let request = Request::builder()
        .method(Method::GET)
        .uri("https://cn.bing.com")
        .body(Body::from(""))
        .unwrap();
    let mut response = client.request(request).await.unwrap();

    let body = response.body_mut();
    let data = body.data().await.unwrap().unwrap();
    println!("{}", data.escape_ascii());
}