Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions justfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ set shell := ["pwsh", "-c"]
alias b := build
alias d := develop

list:
@ just --list

build_32:
cargo build --target=i686-pc-windows-msvc --release
Copy-Item -Force -Path "target\i686-pc-windows-msvc\release\*.dll" -Destination "lv_src\lv_reqwest_32.dll"
Expand All @@ -28,6 +31,9 @@ check:
cargo fmt -- --check
cargo clippy

format:
cargo fmt

develop_windows:
@ Write-Host "Installing Rust Windows targets..."
@ rustup target add i686-pc-windows-msvc
Expand Down
Binary file modified lv_src/HTTP Client Plugin/GET.vi
Binary file not shown.
16 changes: 13 additions & 3 deletions lv_src/Request/Request.lvclass

Large diffs are not rendered by default.

Binary file added lv_src/Request/get_response_version.vi
Binary file not shown.
Binary file modified lv_src/lv_reqwest_32.dll
Binary file not shown.
Binary file modified lv_src/lv_reqwest_64.dll
Binary file not shown.
Binary file modified lv_src/lv_reqwest_64.so
Binary file not shown.
10 changes: 9 additions & 1 deletion src/async_support.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@ pub async fn process_request(
) {
match request_future.await {
Ok(response) => {
// Get the status code and headers before consuming the response
// Get the status code, version, and headers before consuming the response
let status = response.status();
let version = response.version();
let headers = response.headers().clone();

// Check if we're streaming to a file
Expand Down Expand Up @@ -52,6 +53,7 @@ pub async fn process_request(
progress.status = RequestStatus::Error;
progress.final_response = Some(Response {
status,
version,
headers,
body: Err(format!("File write error: {e}")),
});
Expand All @@ -69,6 +71,7 @@ pub async fn process_request(
progress.status = RequestStatus::Error;
progress.final_response = Some(Response {
status,
version,
headers,
body: Err(format!("Network error: {e}")),
});
Expand All @@ -82,6 +85,7 @@ pub async fn process_request(
progress.status = RequestStatus::Completed;
progress.final_response = Some(Response {
status,
version,
headers,
body: Ok(Vec::new()), // Empty body since it was streamed to file
});
Expand All @@ -92,6 +96,7 @@ pub async fn process_request(
progress.status = RequestStatus::Error;
progress.final_response = Some(Response {
status,
version,
headers,
body: Err(format!("File open error: {e}")),
});
Expand All @@ -111,6 +116,7 @@ pub async fn process_request(
progress.total_bytes = Some(bytes_len);
progress.final_response = Some(Response {
status,
version,
headers,
body: Ok(bytes_vec),
});
Expand All @@ -121,6 +127,7 @@ pub async fn process_request(
progress.status = RequestStatus::Error;
progress.final_response = Some(Response {
status,
version,
headers,
body: Err(format!("Body read error: {e}")),
});
Expand All @@ -134,6 +141,7 @@ pub async fn process_request(
progress.status = RequestStatus::Error;
progress.final_response = Some(Response {
status: reqwest::StatusCode::BAD_REQUEST, // Default status code for errors
version: reqwest::Version::HTTP_11, // Default to HTTP/1.1 for errors
headers: reqwest::header::HeaderMap::new(),
body: Err(format!("Request error: {e}")),
});
Expand Down
50 changes: 50 additions & 0 deletions src/ffi/request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -246,3 +246,53 @@ pub extern "C" fn request_has_transport_error(request_id: RequestId) -> bool {

false // Return false if request not found or no response yet
}

/// Get the HTTP version as a string directly from a request ID
/// Returns a C string like "HTTP/1.1", "HTTP/2", etc. Caller must free the memory.
#[unsafe(no_mangle)]
pub extern "C" fn request_read_response_version(
request_id: RequestId,
num_bytes: *mut u32,
) -> *mut c_char {
if num_bytes.is_null() {
return ptr::null_mut();
}

// Get the response info
let tracker = REQUEST_TRACKER.lock().unwrap();

if let Some(progress_info) = tracker.get(&request_id) {
let progress = progress_info.read().unwrap();
if let Some(ref response) = progress.final_response {
let version_str = match response.version {
reqwest::Version::HTTP_09 => "HTTP/0.9",
reqwest::Version::HTTP_10 => "HTTP/1.0",
reqwest::Version::HTTP_11 => "HTTP/1.1",
reqwest::Version::HTTP_2 => "HTTP/2",
reqwest::Version::HTTP_3 => "HTTP/3",
_ => "HTTP/Unknown",
};

// Calculate size including null terminator
let str_len = version_str.len();
unsafe { *num_bytes = str_len as u32 };

// Allocate memory for the string + null terminator
let c_str_ptr = unsafe { libc::malloc(str_len + 1) as *mut c_char };
if c_str_ptr.is_null() {
return ptr::null_mut();
}

// Copy the string and add null terminator
unsafe {
std::ptr::copy_nonoverlapping(version_str.as_ptr(), c_str_ptr as *mut u8, str_len);
*(c_str_ptr.add(str_len)) = 0;
}

return c_str_ptr;
}
}

unsafe { *num_bytes = 0 };
ptr::null_mut() // Return null if request not found or no response yet
}
4 changes: 2 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ pub use ffi::multipart::{
pub use ffi::request::{
request_cancel, request_destroy, request_has_transport_error, request_is_complete,
request_read_progress, request_read_received_bytes, request_read_response_body,
request_read_response_headers, request_read_response_status, request_read_total_bytes,
request_read_transport_error,
request_read_response_headers, request_read_response_status, request_read_response_version,
request_read_total_bytes, request_read_transport_error,
};
pub use ffi::request_builder::{
request_builder_basic_auth, request_builder_bearer_auth, request_builder_body,
Expand Down
3 changes: 2 additions & 1 deletion src/types.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use reqwest::{Client, RequestBuilder, StatusCode, header::HeaderMap};
use reqwest::{Client, RequestBuilder, StatusCode, Version, header::HeaderMap};
use std::sync::{Arc, RwLock};

/// Type aliases for IDs
Expand Down Expand Up @@ -68,6 +68,7 @@ pub struct RequestProgress {
/// Response struct that can be passed back to LabVIEW
pub struct Response {
pub status: StatusCode,
pub version: Version,
pub headers: HeaderMap,
pub body: Result<Vec<u8>, String>,
}
Expand Down
Loading