reqwest_protobuf/
lib.rs

1#![doc = include_str!("../README.md")]
2
3use prost::{EncodeError, Message};
4use async_trait::async_trait;
5use reqwest::{RequestBuilder, Response};
6use thiserror::Error;
7
8/// Extension trait for the RequestBuilder
9pub trait ProtobufRequestExt where Self: Sized {
10    /// Configure the request to accept a protobuf response.
11    /// Sets the `Accept` header to `application/protobuf`
12    fn accept_protobuf(self) -> Self;
13
14    /// Set the request payload encoded as protobuf.
15    /// Sets the `Content-Type` header to `application/protobuf`
16    fn protobuf<T: Message + Default>(self, value: T) -> Result<Self, EncodeError>;
17}
18
19/// Decode errors
20#[derive(Debug, Error)]
21pub enum DecodeError {
22    /// Failed to extract the request body bytes
23    #[error("Failed to extract body bytes: {0}")]
24    Reqwest(#[from] reqwest::Error),
25    /// Failed to decode the received bytes
26    #[error("Failed to decode protobuf: {0:?}")]
27    ProstDecode(prost::DecodeError)
28}
29
30impl From<prost::DecodeError> for DecodeError {
31    fn from(x: prost::DecodeError) -> Self {
32        Self::ProstDecode(x)
33    }
34}
35
36
37/// Extension trait for the Response
38#[async_trait]
39pub trait ProtobufResponseExt {
40    /// Get the response body decoded from Protobuf
41    async fn protobuf<T: Message + Default>(self) -> Result<T, DecodeError>;
42}
43
44impl ProtobufRequestExt for RequestBuilder {
45    fn accept_protobuf(self) -> Self {
46        self.header("Accept", "application/protobuf")
47    }
48
49    fn protobuf<T: Message + Default>(self, value: T) -> Result<Self, EncodeError> {
50        let mut buf = Vec::new();
51        value.encode(&mut buf)?;
52        let this = self.header("Content-Type", "application/protobuf");
53        Ok(this.body(buf))
54    }
55}
56
57#[async_trait]
58impl ProtobufResponseExt for Response {
59    async fn protobuf<T: Message + Default>(self) -> Result<T, DecodeError> {
60        let body = self.bytes().await?;
61        let decoded = T::decode(body)?;
62        Ok(decoded)
63    }
64}