use fetchkit::{FetchRequest, LocalFileSaver, Tool};
#[tokio::main]
async fn main() {
println!("FetchKit save_to_file Example");
println!("==============================\n");
let dir = tempfile::tempdir().expect("Failed to create temp dir");
let saver = LocalFileSaver::new(Some(dir.path().to_path_buf()));
let tool = Tool::builder()
.enable_markdown(true)
.enable_save_to_file(true)
.build();
let mut passed = 0;
let mut failed = 0;
println!("1. Save HTML page to file");
let req = FetchRequest::new("https://example.com").save_to_file("downloads/page.html");
match tool.execute_with_saver(req, Some(&saver)).await {
Ok(resp) => {
println!(" Status: {}", resp.status_code);
println!(" Saved to: {:?}", resp.saved_path);
println!(" Bytes written: {:?}", resp.bytes_written);
if resp.status_code == 200 && resp.saved_path.is_some() && resp.content.is_none() {
let on_disk = std::fs::read_to_string(dir.path().join("downloads/page.html"))
.expect("File should exist on disk");
assert!(!on_disk.is_empty());
println!(" PASS\n");
passed += 1;
} else {
println!(" FAIL\n");
failed += 1;
}
}
Err(e) => {
println!(" Error: {e}\n FAIL\n");
failed += 1;
}
}
println!("2. Save binary file (SVG)");
let req = FetchRequest::new("https://docs.everruns.com/favicon.svg")
.save_to_file("downloads/favicon.svg");
match tool.execute_with_saver(req, Some(&saver)).await {
Ok(resp) => {
println!(" Status: {}", resp.status_code);
println!(" Saved to: {:?}", resp.saved_path);
println!(" Bytes written: {:?}", resp.bytes_written);
if resp.status_code == 200 && resp.saved_path.is_some() {
let bytes = std::fs::read(dir.path().join("downloads/favicon.svg"))
.expect("File should exist");
assert!(!bytes.is_empty());
println!(" PASS\n");
passed += 1;
} else {
println!(" FAIL\n");
failed += 1;
}
}
Err(e) => {
println!(" Error: {e}\n FAIL\n");
failed += 1;
}
}
println!("3. Path traversal rejection (safety check)");
let req = FetchRequest::new("https://example.com").save_to_file("../../etc/passwd");
match tool.execute_with_saver(req, Some(&saver)).await {
Err(e) => {
println!(" Correctly rejected: {e}");
println!(" PASS\n");
passed += 1;
}
Ok(_) => {
println!(" Should have been rejected!\n FAIL\n");
failed += 1;
}
}
println!("4. No saver provided (safety check)");
let req = FetchRequest::new("https://example.com").save_to_file("file.txt");
match tool.execute_with_saver(req, None).await {
Err(e) => {
println!(" Correctly rejected: {e}");
println!(" PASS\n");
passed += 1;
}
Ok(_) => {
println!(" Should have been rejected!\n FAIL\n");
failed += 1;
}
}
println!("5. Feature disabled (safety check)");
let disabled_tool = Tool::builder().build();
let req = FetchRequest::new("https://example.com").save_to_file("file.txt");
match disabled_tool.execute_with_saver(req, Some(&saver)).await {
Err(e) => {
println!(" Correctly rejected: {e}");
println!(" PASS\n");
passed += 1;
}
Ok(_) => {
println!(" Should have been rejected!\n FAIL\n");
failed += 1;
}
}
println!("6. Normal fetch (no save_to_file) still works");
let req = FetchRequest::new("https://example.com");
match tool.execute_with_saver(req, Some(&saver)).await {
Ok(resp) => {
println!(" Status: {}", resp.status_code);
if resp.content.is_some() && resp.saved_path.is_none() {
println!(" PASS\n");
passed += 1;
} else {
println!(" FAIL\n");
failed += 1;
}
}
Err(e) => {
println!(" Error: {e}\n FAIL\n");
failed += 1;
}
}
println!("==============================");
println!("Results: {} passed, {} failed", passed, failed);
if failed > 0 {
std::process::exit(1);
}
}