cognite/api/request_builder/
response.rs

1use std::future::Future;
2use std::marker::PhantomData;
3
4use prost::Message;
5use serde::de::DeserializeOwned;
6
7use reqwest::Response;
8
9use crate::Result;
10
11/// Trait for a type that produces a typed response from a successful
12/// HTTP response message.
13pub trait ResponseHandler {
14    /// Output type.
15    type Output;
16    /// Accept header added to request.
17    const ACCEPT_HEADER: &'static str;
18
19    /// Consume the response and produce an instance of `Output`
20    ///
21    /// # Arguments
22    ///
23    /// * `response` - Response from API.
24    fn handle_response(
25        self,
26        response: Response,
27    ) -> impl Future<Output = Result<Self::Output>> + Send + Sync;
28}
29
30// Uses fn() -> T since that is covariant, and allows us to have a Send future
31// without T being Send, technically.
32/// Response handler for parsing a payload as JSON.
33pub struct JsonResponseHandler<T>(PhantomData<fn() -> T>);
34
35impl<T> Default for JsonResponseHandler<T> {
36    fn default() -> Self {
37        Self::new()
38    }
39}
40
41impl<T> JsonResponseHandler<T> {
42    /// Create a new JSON response handler.
43    pub fn new() -> Self {
44        Self(PhantomData)
45    }
46}
47
48impl<T: DeserializeOwned> ResponseHandler for JsonResponseHandler<T> {
49    type Output = T;
50    const ACCEPT_HEADER: &'static str = "application/json";
51    async fn handle_response(self, response: Response) -> Result<Self::Output> {
52        Ok(response.json().await?)
53    }
54}
55
56/// Response handler for parsing a payload as Protobuf.
57pub struct ProtoResponseHandler<T>(PhantomData<fn() -> T>);
58
59impl<T> Default for ProtoResponseHandler<T> {
60    fn default() -> Self {
61        Self::new()
62    }
63}
64
65impl<T> ProtoResponseHandler<T> {
66    /// Create a new protobuf response handler.
67    pub fn new() -> Self {
68        Self(PhantomData)
69    }
70}
71
72impl<T: Message + Default + Send + Sync> ResponseHandler for ProtoResponseHandler<T> {
73    type Output = T;
74    const ACCEPT_HEADER: &'static str = "application/protobuf";
75    async fn handle_response(self, response: Response) -> Result<Self::Output> {
76        let bytes = response.bytes().await?;
77        Ok(T::decode(bytes)?)
78    }
79}
80
81/// Response handler for just returning the raw response.
82#[derive(Default)]
83pub struct RawResponseHandler;
84
85impl ResponseHandler for RawResponseHandler {
86    type Output = Response;
87    const ACCEPT_HEADER: &'static str = "*/*";
88    async fn handle_response(self, response: Response) -> Result<Self::Output> {
89        Ok(response)
90    }
91}
92
93/// Response handler for ignoring the response payload on success.
94#[derive(Default)]
95pub struct NoResponseHandler;
96
97impl ResponseHandler for NoResponseHandler {
98    type Output = ();
99    const ACCEPT_HEADER: &'static str = "*/*";
100    async fn handle_response(self, _response: Response) -> Result<Self::Output> {
101        Ok(())
102    }
103}