rust 我如何实现一个自定义类型的头与超使用?

3yhwsihp  于 2023-05-29  发布在  其他
关注(0)|答案(2)|浏览(185)

我更喜欢利用Hyper的hyper::header::Headers#get方法的类型安全性,而不是将get_raw&str一起使用。
实现这一点的最佳方式是什么?

r6vfmomb

r6vfmomb1#

通过深入研究hyper::header::Headers源代码,我发现有一个用于生成代码的简洁宏:header!。不过,您需要一些咒语才能使其有用:

#[macro_use]
extern crate hyper;

use hyper::{Body, Method, Request, Response};
use std::fmt::{self, Display};
use std::str::FromStr;
use std::num::ParseIntError;

// For a header that looks like this:
//    x-arbitrary-header-with-an-integer: 8

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct ArbitraryNumber(i8);

impl Display for ArbitraryNumber {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Arbitrary Protocol v{}", self.0)
    }
}

impl FromStr for ArbitraryNumber {
    type Err = ParseIntError;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        s.parse::<i8>().map(|int| ArbitraryNumber(int))
    }
}

//impl Header for ArbitraryNumberHeader
header! { (ArbitraryNumberHeader, "x-arbitrary-header-with-an-integer") => [ArbitraryNumber] }

一旦在作用域中有了一个名为resResponse,就可以像这样访问这个头文件:

let arbitrary_header: AribitraryNumber = res.headers().get::<ArbitraryNumberHeader>().unwrap();
2g32fytz

2g32fytz2#

我想在此期间情况已经改变了。在hyper中找不到header!宏。这是我实现自定义头的解决方案(我使用的是从hyper重新导出的axum,它应该在没有axum的情况下工作,只是使用不同的导入):

use axum::headers::Error;
use http::{HeaderName, HeaderValue};

#[derive(Eq, PartialEq, Clone, Hash)]
pub struct XXsrfToken(pub String);

pub static X_XSRF_TOKEN: HeaderName = HeaderName::from_static("x-xsrf-token");

impl axum::headers::Header for XXsrfToken {
    fn name() -> &'static HeaderName {
        &X_XSRF_TOKEN
    }

    fn decode<'i, I>(values: &mut I) -> Result<Self, Error>
    where
        Self: Sized,
        I: Iterator<Item = &'i HeaderValue>,
    {
        values
            .next()
            .and_then(|v| v.to_str().ok())
            .map(|it| XXsrfToken(it.to_string()))
            .ok_or_else(Error::invalid)
    }

    fn encode<E: Extend<HeaderValue>>(&self, values: &mut E) {
        let bytes = self.0.as_str().as_bytes();
        let val = HeaderValue::from_bytes(bytes).expect("XXsrfToken is a valid HeaderValue");

        values.extend(::std::iter::once(val));
    }
}

相关问题