chap 2.5.0

Chap is an easy to learn, interpretive, scripting language written in Rust
Documentation
use std::str::FromStr;

#[cfg(not(target_family = "wasm"))]
use reqwest::{
    blocking::Client,
    header::{HeaderMap, HeaderName, HeaderValue, USER_AGENT},
};

use crate::{
    builtin_function::utils::{param_to_datatype, returns},
    common::{
        data_type::DataType,
        errors::{ChapError, Result},
        executable::ExecutableLine,
    },
    runtime::Runtime,
};

#[cfg(not(target_family = "wasm"))]
pub fn http_get(runtime: &mut Runtime, executable: &ExecutableLine) -> Result<()> {
    let p1 = param_to_datatype(runtime, executable.params.first(), executable.line_number)?;
    let p2 = if let Some(_) = executable.params.get(1) {
        Some(param_to_datatype(
            runtime,
            executable.params.get(1),
            executable.line_number,
        )?)
    } else {
        None
    };

    match p1 {
        DataType::String(url) => {
            let mut headers = HeaderMap::new();

            headers.insert(USER_AGENT, HeaderValue::from_static("Chap"));

            if let Some(p2) = p2 {
                if let DataType::Map(p2) = p2 {
                    for (key, value) in p2 {
                        let header = HeaderName::from_str(key).map_err(|_| {
                            ChapError::runtime_with_msg(
                                executable.line_number,
                                format!("invalid header name: {}", key),
                            )
                        })?;

                        let value = if let DataType::String(value) = value {
                            value
                        } else {
                            return Err(ChapError::runtime_with_msg(
                                executable.line_number,
                                format!("header value must me a string, got {}", value.type_name()),
                            ));
                        };

                        let value = HeaderValue::from_str(value).map_err(|_| {
                            ChapError::runtime_with_msg(
                                executable.line_number,
                                format!("failed to initialize TLS backend"),
                            )
                        })?;

                        headers.insert(header, value);
                    }
                } else {
                    return Err(ChapError::runtime_with_msg(
                        executable.line_number,
                        format!(
                            "second parameter for headers must be a map, got {}",
                            p2.type_name()
                        ),
                    ));
                }
            }

            let client = Client::builder()
                .default_headers(headers)
                .build()
                .map_err(|_| {
                    ChapError::runtime_with_msg(
                        executable.line_number,
                        format!("failed to initialize TLS backend"),
                    )
                })?;

            let resp = client.get(url).send().map_err(|e| {
                ChapError::runtime_with_msg(
                    executable.line_number,
                    format!("failed to send GET HTTP request: {}", e),
                )
            })?;

            let body = resp.text().map_err(|e| {
                ChapError::runtime_with_msg(
                    executable.line_number,
                    format!("failed to read response body: {}", e),
                )
            })?;

            returns(runtime, executable, DataType::String(body))
        }
        _ => {
            return Err(ChapError::runtime_with_msg(
                executable.line_number,
                format!("first parameter must be a string, got {}", p1.type_name()),
            ));
        }
    }
}

#[cfg(target_family = "wasm")]
pub fn http_get(runtime: &mut Runtime, executable: &ExecutableLine) -> Result<()> {
    Err(ChapError::runtime_with_msg(
        executable.line_number,
        "http_get not supported in wasm".to_string(),
    ))
}