tiktok_api/endpoints/oauth/
refresh_token.rs

1use http_api_client_endpoint::{
2    http::{
3        header::{ACCEPT, USER_AGENT},
4        Method,
5    },
6    Body, Endpoint, Request, Response,
7};
8use serde::{Deserialize, Serialize};
9use url::Url;
10
11use super::common::{endpoint_parse_response, EndpointError, EndpointRet};
12use crate::objects::oauth::{AccessToken, Message};
13
14//
15pub const URL: &str = "https://open-api.tiktok.com/oauth/refresh_token/";
16pub const GRANT_TYPE: &str = "refresh_token";
17
18//
19#[derive(Debug, Clone)]
20pub struct RefreshTokenEndpoint {
21    pub client_key: String,
22    pub refresh_token: String,
23}
24impl RefreshTokenEndpoint {
25    pub fn new(client_key: impl AsRef<str>, refresh_token: impl AsRef<str>) -> Self {
26        Self {
27            client_key: client_key.as_ref().into(),
28            refresh_token: refresh_token.as_ref().into(),
29        }
30    }
31}
32
33impl Endpoint for RefreshTokenEndpoint {
34    type RenderRequestError = EndpointError;
35
36    type ParseResponseOutput = EndpointRet<RefreshTokenResponseBody>;
37    type ParseResponseError = EndpointError;
38
39    fn render_request(&self) -> Result<Request<Body>, Self::RenderRequestError> {
40        let mut url = Url::parse(URL).map_err(EndpointError::MakeRequestUrlFailed)?;
41        url.query_pairs_mut()
42            .append_pair("client_key", &self.client_key)
43            .append_pair("grant_type", GRANT_TYPE)
44            .append_pair("refresh_token", &self.refresh_token);
45
46        let request = Request::builder()
47            .method(Method::POST)
48            .uri(url.as_str())
49            .header(USER_AGENT, "tiktok-api")
50            .header(ACCEPT, "application/json")
51            .body(vec![])
52            .map_err(EndpointError::MakeRequestFailed)?;
53
54        Ok(request)
55    }
56
57    fn parse_response(
58        &self,
59        response: Response<Body>,
60    ) -> Result<Self::ParseResponseOutput, Self::ParseResponseError> {
61        endpoint_parse_response(response)
62    }
63}
64
65//
66#[derive(Serialize, Deserialize, Debug, Clone)]
67pub struct RefreshTokenResponseBody {
68    pub data: AccessToken,
69    pub message: Message,
70}
71
72#[cfg(test)]
73mod tests {
74    use super::*;
75
76    #[test]
77    fn test_render_request() {
78        let req = RefreshTokenEndpoint::new("KEY", "TOKEN")
79            .render_request()
80            .unwrap();
81        assert_eq!(req.method(), Method::POST);
82        assert_eq!(req.uri(), "https://open-api.tiktok.com/oauth/refresh_token/?client_key=KEY&grant_type=refresh_token&refresh_token=TOKEN");
83    }
84
85    #[test]
86    fn test_de_response_body() {
87        match serde_json::from_str::<RefreshTokenResponseBody>(include_str!(
88            "../../../tests/response_body_files/oauth/refresh_token.json"
89        )) {
90            Ok(ok_json) => {
91                assert_eq!(ok_json.data.open_id, "_000fwZ23Mw4RY9cB4lDQyKCgQg4Ft6SyTuE");
92                assert_eq!(ok_json.message, Message::Success);
93            }
94            x => panic!("{x:?}"),
95        }
96    }
97}