hyperium / headers

Typed HTTP Headers from hyper
https://hyper.rs
MIT License
163 stars 84 forks source link

http::Response::Builder interop #42

Open lnicola opened 5 years ago

lnicola commented 5 years ago

An extension trait to offer something like typed_header on http::response::Builder would be nice.

izderadicka commented 5 years ago

Yes, I have same issue - how to easily use this crate in creation of hyper::Response with http:response::Builder.

As WA I have now this trait, which adds typed header:

struct HeadersExtender<'a, 'b> {
    builder: &'a mut Builder,
    name: &'b HeaderName

}

impl <'a, 'b> Extend<HeaderValue> for HeadersExtender<'a, 'b> {
    fn extend<I:IntoIterator<Item=HeaderValue>>(&mut self, iter:I) {
        for v in iter.into_iter() {
            self.builder.header(self.name,v);
        }
    }
}

pub trait ResponseBuilderExt {
    fn typed_header<H: Header>(&mut self, header: H) -> &mut Builder;
}

impl ResponseBuilderExt for Builder {
    fn typed_header<H: Header>(&mut self, header: H) -> &mut Builder {
        let mut extender = HeadersExtender{builder:self,name:H::name()};
        header.encode(&mut extender);
        self
    }
}

I hope it's efficient enough, but it would be nice to have it in library already.

kevinastone commented 4 years ago

Here's my implementation for a typed header trait extension:

use headers::{Header, HeaderMapExt};

pub trait ResponseTypedHeaderExt {
    fn typed_header<H: Header>(self, header: H) -> Self;
}

impl ResponseTypedHeaderExt for hyper::http::response::Builder {
    fn typed_header<H: Header>(mut self, header: H) -> Self {
        self.headers_mut().map(|res| res.typed_insert(header));
        self
    }
}

And an example of it's use:

pub fn redirect_to(uri: Uri) -> http::Response {
    HTTPResponse::builder()
        .status(StatusCode::FOUND)
        .typed_header(Location::from(uri))
        .body(Body::empty())
}