awpak-web-client 0.1.0

Web client for awpak projects.
Documentation

pub mod request;
pub mod response;
use std::{collections::HashMap, time::{Duration, Instant}};

use reqwest::RequestBuilder;

use crate::{request::{AwpakBody, AwpakHeader, AwpakMethod, AwpakQueryParam, AwpakRequest}, response::AwpakResponse};

pub async fn send_request( request : AwpakRequest ) -> Result<AwpakResponse, reqwest::Error>
{
    let builder = request_builder( &request.url, request.method );

    let builder = append_headers(builder, request.headers );

    let mut builder = append_query_params( builder, request.query_params );

    if let Some( t ) = request.timeout
    {
        if t > 0 { builder = builder.timeout( Duration::from_secs( t ) ) }
    }

    let builder = match request.body
    {
        Some( b ) => append_body( builder, b ),
        _ => builder
    };

    send( builder ).await
}

async fn send( builder : RequestBuilder ) -> Result<AwpakResponse, reqwest::Error>
{
    let start = Instant::now();
    
    let response = builder.send().await?;

    let duration = start.elapsed();

    let version =  format!( "{:?}", response.version() );

    let status = usize::from( response.status().as_u16() );

    let headers = response.headers().into_iter()
    .fold( 
        HashMap::new(), 
        | mut a,  ( n, v ) | 
        {
            a.insert( n.to_string(), v.to_str().unwrap_or( "" ).to_string() );

            a
        }
    );

    let text = response.text().await?;

    Ok(
        AwpakResponse
        {
            version,
            status,
            headers,
            text,
            time_millis : duration.as_millis(),
            time_str : format!( "{:?}", duration )
        }
    )
}

fn append_query_params( builder : RequestBuilder, query_params : Vec<AwpakQueryParam> ) -> RequestBuilder
{
    if query_params.len() == 0 { return builder }

    builder.query( 
        query_params.into_iter()
        .map( | q | ( q.name, q.value ) )
        .collect::<Vec<_>>()
        .as_slice()
    )
}

fn append_headers( mut builder : RequestBuilder, headers : Vec<AwpakHeader> ) -> RequestBuilder
{
    if headers.len() == 0 { return builder; }

    for h in headers
    {
        builder = builder.header( h.name, h.value )
    }
    
    builder
}

fn append_body( builder : RequestBuilder, body : AwpakBody ) -> RequestBuilder
{
    match body
    {
        AwpakBody::Json( j ) => builder.json( &j ),
        AwpakBody::Form( f ) =>
        {
            if f.len() == 0
            {
                builder
            }
            else
            {
                builder.form(
                    f.into_iter()
                    .map( | q | ( q.name, q.value ) )
                    .collect::<Vec<_>>()
                    .as_slice()
                )    
            }
        }
    }
}

fn request_builder( url : &str, method : AwpakMethod ) -> RequestBuilder
{
    let client = reqwest::Client::new();

    client.request( method.into(), url )
}