use crate::error::Result;
use crate::http::HttpClient;
use crate::http::encode_path_segment;
use reqwest::Method;
use serde::Deserialize;
use serde::Serialize;
#[derive(Clone)]
pub struct ResourceApi {
http: HttpClient,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ResourceInfo {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub uri: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub name: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub content: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub mime_type: Option<String>,
#[serde(flatten)]
pub extra: serde_json::Value,
}
impl ResourceApi {
pub fn new(http: HttpClient) -> Self {
Self { http }
}
pub async fn get(&self, uri: &str) -> Result<ResourceInfo> {
let encoded_uri = encode_path_segment(uri);
self.http
.request_json(
Method::GET,
&format!("/experimental/resource?uri={encoded_uri}"),
None,
)
.await
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::http::HttpConfig;
use std::time::Duration;
use wiremock::Mock;
use wiremock::MockServer;
use wiremock::ResponseTemplate;
use wiremock::matchers::method;
use wiremock::matchers::path;
use wiremock::matchers::query_param;
#[tokio::test]
async fn test_get_resource() {
let mock_server = MockServer::start().await;
Mock::given(method("GET"))
.and(path("/experimental/resource"))
.and(query_param("uri", "file:///path/to/file.txt"))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"uri": "file:///path/to/file.txt",
"name": "file.txt",
"content": "Hello, world!",
"mimeType": "text/plain"
})))
.mount(&mock_server)
.await;
let client = HttpClient::new(HttpConfig {
base_url: mock_server.uri(),
directory: None,
timeout: Duration::from_secs(30),
})
.unwrap();
let api = ResourceApi::new(client);
let resource = api.get("file:///path/to/file.txt").await.unwrap();
assert_eq!(resource.uri, Some("file:///path/to/file.txt".to_string()));
assert_eq!(resource.name, Some("file.txt".to_string()));
assert_eq!(resource.content, Some("Hello, world!".to_string()));
assert_eq!(resource.mime_type, Some("text/plain".to_string()));
}
#[test]
fn test_resource_info_minimal() {
let json = r"{}";
let resource: ResourceInfo = serde_json::from_str(json).unwrap();
assert!(resource.uri.is_none());
assert!(resource.content.is_none());
}
#[test]
fn test_resource_info_extra_fields() {
let json = r#"{"uri": "test://uri", "futureField": "value"}"#;
let resource: ResourceInfo = serde_json::from_str(json).unwrap();
assert_eq!(resource.uri, Some("test://uri".to_string()));
assert_eq!(resource.extra["futureField"], "value");
}
}