From f47e3114d6d08989d00fd527954b22ed7924fee9 Mon Sep 17 00:00:00 2001 From: RutamBhagat Date: Tue, 17 Dec 2024 15:11:23 -0800 Subject: [PATCH] feat(rust-sdk): improve API key handling for cloud vs self-hosted services in FirecrawlApp --- SELF_HOST.md | 4 ++++ apps/rust-sdk/src/error.rs | 2 +- apps/rust-sdk/src/lib.rs | 19 +++++++++++++++++-- apps/rust-sdk/tests/e2e_with_auth.rs | 28 +++++++++++++++++++++++++++- 4 files changed, 49 insertions(+), 4 deletions(-) diff --git a/SELF_HOST.md b/SELF_HOST.md index 46e08db95..e8a3444fa 100644 --- a/SELF_HOST.md +++ b/SELF_HOST.md @@ -116,6 +116,10 @@ If you’d like to test the crawl endpoint, you can run this: This section provides solutions to common issues you might encounter while setting up or running your self-hosted instance of Firecrawl. +### API Keys for SDK Usage + +**Note:** When using Firecrawl SDKs with a self-hosted instance, API keys are optional. API keys are only required when connecting to the cloud service (api.firecrawl.dev). + ### Supabase client is not configured **Symptom:** diff --git a/apps/rust-sdk/src/error.rs b/apps/rust-sdk/src/error.rs index f04a286a8..33e4edc61 100644 --- a/apps/rust-sdk/src/error.rs +++ b/apps/rust-sdk/src/error.rs @@ -9,7 +9,7 @@ use crate::crawl::CrawlStatus; #[derive(Debug, Deserialize, Serialize, Clone)] pub struct FirecrawlAPIError { /// Always false. - success: bool, + pub success: bool, /// Error message pub error: String, diff --git a/apps/rust-sdk/src/lib.rs b/apps/rust-sdk/src/lib.rs index 38c2dc113..5d95cc7d2 100644 --- a/apps/rust-sdk/src/lib.rs +++ b/apps/rust-sdk/src/lib.rs @@ -9,6 +9,7 @@ pub mod map; pub mod scrape; pub use error::FirecrawlError; +use error::FirecrawlAPIError; #[derive(Clone, Debug)] pub struct FirecrawlApp { @@ -18,16 +19,30 @@ pub struct FirecrawlApp { } pub(crate) const API_VERSION: &str = "/v1"; +const CLOUD_API_URL: &str = "https://api.firecrawl.dev"; impl FirecrawlApp { pub fn new(api_key: impl AsRef) -> Result { - FirecrawlApp::new_selfhosted("https://api.firecrawl.dev", Some(api_key)) + FirecrawlApp::new_selfhosted(CLOUD_API_URL, Some(api_key)) } pub fn new_selfhosted(api_url: impl AsRef, api_key: Option>) -> Result { + let url = api_url.as_ref().to_string(); + + if url == CLOUD_API_URL && api_key.is_none() { + return Err(FirecrawlError::APIError( + "Configuration".to_string(), + FirecrawlAPIError { + success: false, + error: "API key is required for cloud service".to_string(), + details: None, + } + )); + } + Ok(FirecrawlApp { api_key: api_key.map(|x| x.as_ref().to_string()), - api_url: api_url.as_ref().to_string(), + api_url: url, client: Client::new(), }) } diff --git a/apps/rust-sdk/tests/e2e_with_auth.rs b/apps/rust-sdk/tests/e2e_with_auth.rs index 75568f92b..a9187511a 100644 --- a/apps/rust-sdk/tests/e2e_with_auth.rs +++ b/apps/rust-sdk/tests/e2e_with_auth.rs @@ -1,7 +1,7 @@ use assert_matches::assert_matches; use dotenvy::dotenv; use firecrawl::scrape::{ExtractOptions, ScrapeFormats, ScrapeOptions}; -use firecrawl::FirecrawlApp; +use firecrawl::{FirecrawlApp, FirecrawlError}; use serde_json::json; use std::env; @@ -154,3 +154,29 @@ async fn test_llm_extraction() { assert!(llm_extraction["supports_sso"].is_boolean()); assert!(llm_extraction["is_open_source"].is_boolean()); } + +#[test] +fn test_api_key_requirements() { + dotenv().ok(); + + let api_url = env::var("API_URL").unwrap_or("http://localhost:3002".to_string()); + let api_key = env::var("TEST_API_KEY").ok(); + + match (api_url.contains("api.firecrawl.dev"), api_key) { + (false, _) => { + let result = FirecrawlApp::new_selfhosted(&api_url, None::); + assert!(result.is_ok(), "Local setup failed: {:?}", result.err().unwrap()); + } + (true, None) => { + let result = FirecrawlApp::new_selfhosted(&api_url, None::); + assert!(matches!( + result, + Err(FirecrawlError::APIError(msg, _)) if msg == "Configuration" + )); + } + (true, Some(key)) => { + let result = FirecrawlApp::new_selfhosted(&api_url, Some(&key)); + assert!(result.is_ok()); + } + } +}