Skip to content

Async HTTP request in hyperware_app_common #32

@Gohlub

Description

@Gohlub

A function I wrote for making async HTTP requests for the provider seems like something we could potentially add to our app framework 'standard process lib' (would probably go in hyperware_app_common).

https://github.com/hyperware-ai/hpn/blob/fd30c675b54d5f3941ae76c8bb57bb558788b2ff/provider/provider/src/util.rs#L22 <- this is the function I mean, but I will paste it in here for reference as well.

/// Make an HTTP request using http-client and await its response.
///
/// Returns HTTP response from the `http` crate if successful, with the body type as bytes.
pub async fn send_async_http_request(
    method: HyperwareHttpMethod,
    url: url::Url,
    headers: Option<HashMap<String, String>>,
    timeout: u64,
    body: Vec<u8>,
) -> std::result::Result<HyperwareHttpResponse<Vec<u8>>, HttpClientError> {
    let req = Request::to(("our", "http-client", "distro", "sys"))
        .expects_response(timeout)
        .body(
            serde_json::to_vec(&HttpClientAction::Http(OutgoingHttpRequest {
                method: method.to_string(),
                version: None,
                url: url.to_string(),
                headers: headers.unwrap_or_default(),
            }))
            .map_err(|_| HttpClientError::MalformedRequest)?,
        )
        .blob_bytes(body);

    let result_from_http_client =
        send::<std::result::Result<HttpClientResponse, HttpClientError>>(req).await;

    match result_from_http_client {
        Ok(Ok(HttpClientResponse::Http(resp_data))) => {
            let mut http_response = HyperwareHttpResponse::builder()
                .status(StatusCode::from_u16(resp_data.status).unwrap_or_default());
            let headers_map = http_response.headers_mut().unwrap();
            for (key, value) in &resp_data.headers {
                let Ok(key) = HeaderName::from_str(key) else {
                    continue;
                };
                let Ok(value) = HeaderValue::from_str(value) else {
                    continue;
                };
                headers_map.insert(key, value);
            }
            Ok(http_response
                .body(get_blob().unwrap_or_default().bytes)
                .unwrap())
        }
        Ok(Ok(HttpClientResponse::WebSocketAck)) => Err(HttpClientError::ExecuteRequestFailed(
            "http-client gave unexpected response".to_string(),
        )),
        Ok(Err(http_client_err)) => Err(http_client_err),
        Err(app_send_err) => Err(HttpClientError::ExecuteRequestFailed(format!(
            "http-client gave invalid response: {app_send_err:?}"
        ))),
    }
}

It's equivalent in standard process library:
https://docs.rs/hyperware_process_lib/latest/src/hyperware_process_lib/http/client.rs.html#134-191

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions