ApiRequest

Trait ApiRequest 

Source
pub trait ApiRequest<Res>
where Self: Serialize + Debug, Res: Default + DeserializeOwned,
{ const ENDPOINT: &'static str; const METHOD: Method = reqwest::Method::GET; const DATA_TRANSMISSION_METHOD: DataTransmissionMethod = DataTransmissionMethod::QueryParams; const AUTHENTICATION_METHOD: AuthenticationMethod = AuthenticationMethod::None; // Provided methods async fn from_response(resp: Response) -> Result<Res, ApiForgeError> { ... } fn multipart_form_data(&self) -> Form { ... } fn generate_request( &self, base_url: &str, headers: Option<HeaderMap>, token: Option<(String, Option<String>)>, ) -> RequestBuilder { ... } async fn send_request( &self, base_url: &str, headers: Option<HeaderMap>, token: Option<(String, Option<String>)>, ) -> Result<Response> { ... } async fn send_and_parse( &self, base_url: &str, headers: Option<HeaderMap>, token: Option<(String, Option<String>)>, ) -> Result<Res, ApiForgeError> { ... } }
Expand description

ApiRequest trait.

This trait defines a structure for making HTTP requests with custom serialization and response handling. It is intended to be implemented by request types that are serializable and can generate HTTP requests.

§Requirements

Implementing types must:

  • Implement the Serialize trait from serde for serializing the request data.
  • Implement the Debug trait for debugging purposes.
  • Define a constant ENDPOINT representing the API endpoint.

§Associated Constants

  • ENDPOINT: A static string representing the endpoint for the request.
  • METHOD: The HTTP method (default is GET).
  • DATA_TRANSMISSION_METHOD: Specifies how the request data is sent (default is QueryParams).
  • AUTHENTICATION_METHOD: Specifies the authentication method (default is None).

§Methods

  • generate_request: Generates a reqwest::RequestBuilder based on the request type.
  • send_request: Sends the request asynchronously and returns the response.
  • send_and_parse: Sends the request and parses the response, returning a result or an error.

§Example

use serde::{Serialize, Deserialize};
use reqwest::header::HeaderMap;
use reqwest::Method;
use api_forge::{ApiRequest, DataTransmissionMethod, AuthenticationMethod, ApiForgeError};

#[derive(Serialize, Debug)]
struct MyRequest {
    field1: String,
    field2: i32,
}

#[derive(Deserialize, Debug, Default)]
struct MyResponse {
    result: String,
}

impl From<reqwest::Response> for MyResponse {
    fn from(resp: reqwest::Response) -> Self {
        // Convert the response into your response structure
        resp.json().unwrap_or_else(|_| MyResponse {
            result: "Error parsing response".into(),
        })
    }
}

impl ApiRequest<MyResponse> for MyRequest {
    const ENDPOINT: &'static str = "/api/my_endpoint";
    const METHOD: Method = Method::POST; // Override HTTP method if necessary
    const DATA_TRANSMISSION_METHOD: DataTransmissionMethod = DataTransmissionMethod::Json; // Send data as JSON
    const AUTHENTICATION_METHOD: AuthenticationMethod = AuthenticationMethod::Bearer; // Use Bearer authentication
    async fn from_response(resp: reqwest::Response) -> Result<Self::Response, ApiForgeError> where <Self as ApiRequest<MyResponse>>::Response: From<reqwest::Response> {
        resp.json().await
    }
}

#[tokio::main]
async fn main() {
    let request = MyRequest {
        field1: "Test".to_string(),
        field2: 42,
    };

    let headers = HeaderMap::new();
    let token = Some(("my_token".to_string(), None));

    match request.send_and_parse("https://api.example.com", Some(headers), token).await {
        Ok(response) => println!("Success: {:?}", response),
        Err(e) => eprintln!("Request failed: {:?}", e),
    }
}

Required Associated Constants§

Source

const ENDPOINT: &'static str

A static string representing the endpoint for the request.

Provided Associated Constants§

Source

const METHOD: Method = reqwest::Method::GET

Determines the HTTP method for the request. Defaults to GET.

Source

const DATA_TRANSMISSION_METHOD: DataTransmissionMethod = DataTransmissionMethod::QueryParams

Specifies how the data will be transmitted in the request. The default is DataTransmissionMethod::QueryParams.

Source

const AUTHENTICATION_METHOD: AuthenticationMethod = AuthenticationMethod::None

Specifies the method of authentication for the request. The default is AuthenticationMethod::None.

Provided Methods§

Source

async fn from_response(resp: Response) -> Result<Res, ApiForgeError>

Source

fn multipart_form_data(&self) -> Form

Optional: Provides multipart form data for file uploads.

Source

fn generate_request( &self, base_url: &str, headers: Option<HeaderMap>, token: Option<(String, Option<String>)>, ) -> RequestBuilder

Generates a reqwest::RequestBuilder based on the request’s parameters, including optional headers and authentication.

Source

async fn send_request( &self, base_url: &str, headers: Option<HeaderMap>, token: Option<(String, Option<String>)>, ) -> Result<Response>

Sends the request asynchronously and returns the result.

Source

async fn send_and_parse( &self, base_url: &str, headers: Option<HeaderMap>, token: Option<(String, Option<String>)>, ) -> Result<Res, ApiForgeError>

Sends the request and attempts to parse the response. Returns a Result containing the parsed response or an error.

Examples found in repository?
examples/json_placeholder.rs (line 29)
21async fn main() {
22    // Initialize the request.
23    let request = GetPosts;
24
25    // Define the base URL (e.g., JSONPlaceholder API for testing).
26    let base_url = "https://jsonplaceholder.typicode.com";
27
28    // Send the request and await the response.
29    let result = request.send_and_parse(base_url, None, None).await;
30
31    match result {
32        Ok(post) => println!("Successfully fetched post: {:?}", post),
33        Err(e) => eprintln!("Error occurred: {:?}", e),
34    }
35}
More examples
Hide additional examples
examples/derive.rs (line 54)
46async fn main() {
47    // Initialize the request.
48    let request = GetPosts;
49
50    // Define the base URL (e.g., JSONPlaceholder API for testing).
51    let base_url = "https://jsonplaceholder.typicode.com";
52
53    // Send the request and await the response.
54    let result = request.send_and_parse(base_url, None, None).await;
55
56    match result {
57        Ok(post) => println!("Successfully fetched post: {:?}", post),
58        Err(e) => eprintln!("Error occurred: {:?}", e),
59    }
60
61    // Initialize the request.
62    let request = CreatePost {
63        user_id: 1,
64        title: "Test".to_string(),
65        body: "Test".to_string(),
66        header: Some("test-header".to_string()),
67    };
68
69    // Send the request and await the response.
70    let result = request.send_and_parse(base_url, None, None).await;
71
72    match result {
73        Ok(post) => println!("Successfully created post: {:?}", post),
74        Err(e) => eprintln!("Error occurred: {:?}", e),
75    }
76
77    // Initialize the request.
78    let request = DeletePost { id: 100 };
79
80    // Send the request and await the response.
81    let result = request.send_and_parse(base_url, None, None).await;
82
83    match result {
84        Ok(post) => println!("Successfully deleted post: {:?}", post),
85        Err(e) => eprintln!("Error occurred: {:?}", e),
86    }
87}

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.

Implementors§