spotify_web_api/api/
ignore.rs

1use crate::api::{ApiError, AsyncClient, AsyncQuery, Client, Endpoint, Query, query};
2use async_trait::async_trait;
3use http::{
4    Method, Request,
5    header::{self, LOCATION},
6};
7
8/// A query modifier that ignores the data returned from an endpoint.
9#[derive(Debug, Clone, Copy, PartialEq, Eq)]
10pub struct Ignore<E> {
11    endpoint: E,
12}
13
14/// Ignore the resulting data from an endpoint.
15///
16/// Use this when you only care about whether the request succeeded,
17/// not the response body (e.g., for PUT/DELETE operations).
18///
19/// # Example
20///
21/// ```no_run
22/// use spotify_web_api::api::{ignore, Query, player::PausePlayback};
23///
24/// # fn example(client: &impl spotify_web_api::api::Client) {
25/// // Pause playback without caring about the response
26/// ignore(PausePlayback::default()).query(client).unwrap();
27/// # }
28/// ```
29pub fn ignore<E>(endpoint: E) -> Ignore<E> {
30    Ignore { endpoint }
31}
32
33impl<E, C> Query<(), C> for Ignore<E>
34where
35    E: Endpoint,
36    C: Client,
37{
38    fn query(&self, client: &C) -> Result<(), ApiError<C::Error>> {
39        let mut url = self
40            .endpoint
41            .url_base()
42            .endpoint_for(client, &self.endpoint.endpoint())?;
43
44        self.endpoint.parameters().add_to_url(&mut url);
45
46        let (mime, data) = self
47            .endpoint
48            .body()?
49            .map_or((None, Vec::new()), |(mime, data)| {
50                (Some(mime), data.clone())
51            });
52
53        let mut req = Request::builder()
54            .method(self.endpoint.method())
55            .uri(query::url_to_http_uri(&url));
56
57        if let Some(mime) = mime {
58            req = req.header(header::CONTENT_TYPE, mime);
59        }
60
61        if matches!(self.endpoint.method(), Method::POST | Method::PUT) {
62            req = req.header(header::CONTENT_LENGTH, data.len().to_string());
63        }
64
65        let rsp = client.rest(req, data)?;
66        let status = rsp.status();
67
68        if !status.is_success() {
69            let v = serde_json::from_slice(rsp.body())
70                .map_err(|_e| ApiError::server_error(status, rsp.body()))?;
71            return Err(ApiError::from_spotify_with_status(status, v));
72        } else if status == http::StatusCode::MOVED_PERMANENTLY {
73            return Err(ApiError::moved_permanently(rsp.headers().get(LOCATION)));
74        }
75
76        Ok(())
77    }
78}
79
80#[async_trait]
81impl<E, C> AsyncQuery<(), C> for Ignore<E>
82where
83    E: Endpoint + Sync,
84    C: AsyncClient + Sync,
85{
86    async fn query_async(&self, client: &C) -> Result<(), ApiError<C::Error>> {
87        let mut url = self
88            .endpoint
89            .url_base()
90            .endpoint_for(client, &self.endpoint.endpoint())?;
91
92        self.endpoint.parameters().add_to_url(&mut url);
93
94        let (mime, data) = self
95            .endpoint
96            .body()?
97            .map_or((None, Vec::new()), |(mime, data)| {
98                (Some(mime), data.clone())
99            });
100
101        let mut req = Request::builder()
102            .method(self.endpoint.method())
103            .uri(query::url_to_http_uri(&url));
104
105        if let Some(mime) = mime {
106            req = req.header(header::CONTENT_TYPE, mime);
107        }
108
109        if matches!(self.endpoint.method(), Method::POST | Method::PUT) {
110            req = req.header(header::CONTENT_LENGTH, data.len().to_string());
111        }
112
113        let rsp = client.rest_async(req, data).await?;
114        let status = rsp.status();
115
116        if !status.is_success() {
117            let v = serde_json::from_slice(rsp.body())
118                .map_err(|_e| ApiError::server_error(status, rsp.body()))?;
119            return Err(ApiError::from_spotify_with_status(status, v));
120        } else if status == http::StatusCode::MOVED_PERMANENTLY {
121            return Err(ApiError::moved_permanently(rsp.headers().get(LOCATION)));
122        }
123
124        Ok(())
125    }
126}