reqwest
Reqwest - HTTP Client Reference
Source: https://docs.rs/reqwest/latest/reqwest/
Crate:reqwest(withjsonfeature)
Role in Pour
Reqwest is used to communicate with the Obsidian Local REST API over HTTP/HTTPS on localhost.
Client Setup
use reqwest::Client;
// Basic client
let client = Client::new();
// With custom config (e.g., accept self-signed certs)
let client = Client::builder()
.danger_accept_invalid_certs(true) // needed for Obsidian's self-signed cert
.timeout(std::time::Duration::from_secs(5))
.build()?;
Making Requests
GET
let resp = client.get("https://127.0.0.1:27124/vault/path/to/file.md")
.bearer_auth("your-api-key")
.send()
.await?;
let body = resp.text().await?;
PUT (create/overwrite file)
let resp = client.put("https://127.0.0.1:27124/vault/path/to/note.md")
.bearer_auth("your-api-key")
.header("Content-Type", "text/markdown")
.body(markdown_content)
.send()
.await?;
POST (append to file)
let resp = client.post("https://127.0.0.1:27124/vault/path/to/note.md")
.bearer_auth("your-api-key")
.header("Content-Type", "text/markdown")
.body(content_to_append)
.send()
.await?;
PATCH (surgical edit)
let resp = client.patch("https://127.0.0.1:27124/vault/path/to/note.md")
.bearer_auth("your-api-key")
.header("Operation", "append")
.header("Target-Type", "heading")
.header("Target", "Brain Dump")
.header("Content-Type", "text/markdown")
.body("- New thought here\n")
.send()
.await?;
JSON requests/responses
// Send JSON
let resp = client.post(url)
.bearer_auth(api_key)
.json(&serde_json::json!({"key": "value"}))
.send()
.await?;
// Parse JSON response
let data: serde_json::Value = resp.json().await?;
Response Handling
let resp = client.get(url).bearer_auth(key).send().await?;
// Check status
if resp.status().is_success() {
let body = resp.text().await?;
} else {
let status = resp.status();
let error_body = resp.text().await?;
// handle error
}
Connection Check Pattern (for Pour)
/// Check if Obsidian REST API is available
async fn check_api(client: &Client, port: u16) -> bool {
client.get(format!("https://127.0.0.1:{}/", port))
.send()
.await
.map(|r| r.status().is_success())
.unwrap_or(false)
}
Directory Listing (for Dynamic selects)
let resp = client.get("https://127.0.0.1:27124/vault/02-Logbook/Beans/")
.bearer_auth(api_key)
.send()
.await?;
let listing: serde_json::Value = resp.json().await?;
// listing["files"] is an array of {path, stat} objects