Skip to content

Commit a431caf

Browse files
authored
Merge pull request #991 from RutamBhagat/rust-sdk-conditionally-enforce-api-key
feat(rust-sdk): Make API key optional for self-hosted instances
2 parents 65cf4cd + f47e311 commit a431caf

File tree

4 files changed

+49
-4
lines changed

4 files changed

+49
-4
lines changed

SELF_HOST.md

+4
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,10 @@ If you’d like to test the crawl endpoint, you can run this:
116116

117117
This section provides solutions to common issues you might encounter while setting up or running your self-hosted instance of Firecrawl.
118118

119+
### API Keys for SDK Usage
120+
121+
**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).
122+
119123
### Supabase client is not configured
120124

121125
**Symptom:**

apps/rust-sdk/src/error.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use crate::crawl::CrawlStatus;
99
#[derive(Debug, Deserialize, Serialize, Clone)]
1010
pub struct FirecrawlAPIError {
1111
/// Always false.
12-
success: bool,
12+
pub success: bool,
1313

1414
/// Error message
1515
pub error: String,

apps/rust-sdk/src/lib.rs

+17-2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ pub mod map;
99
pub mod scrape;
1010

1111
pub use error::FirecrawlError;
12+
use error::FirecrawlAPIError;
1213

1314
#[derive(Clone, Debug)]
1415
pub struct FirecrawlApp {
@@ -18,16 +19,30 @@ pub struct FirecrawlApp {
1819
}
1920

2021
pub(crate) const API_VERSION: &str = "/v1";
22+
const CLOUD_API_URL: &str = "https://api.firecrawl.dev";
2123

2224
impl FirecrawlApp {
2325
pub fn new(api_key: impl AsRef<str>) -> Result<Self, FirecrawlError> {
24-
FirecrawlApp::new_selfhosted("https://api.firecrawl.dev", Some(api_key))
26+
FirecrawlApp::new_selfhosted(CLOUD_API_URL, Some(api_key))
2527
}
2628

2729
pub fn new_selfhosted(api_url: impl AsRef<str>, api_key: Option<impl AsRef<str>>) -> Result<Self, FirecrawlError> {
30+
let url = api_url.as_ref().to_string();
31+
32+
if url == CLOUD_API_URL && api_key.is_none() {
33+
return Err(FirecrawlError::APIError(
34+
"Configuration".to_string(),
35+
FirecrawlAPIError {
36+
success: false,
37+
error: "API key is required for cloud service".to_string(),
38+
details: None,
39+
}
40+
));
41+
}
42+
2843
Ok(FirecrawlApp {
2944
api_key: api_key.map(|x| x.as_ref().to_string()),
30-
api_url: api_url.as_ref().to_string(),
45+
api_url: url,
3146
client: Client::new(),
3247
})
3348
}

apps/rust-sdk/tests/e2e_with_auth.rs

+27-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use assert_matches::assert_matches;
22
use dotenvy::dotenv;
33
use firecrawl::scrape::{ExtractOptions, ScrapeFormats, ScrapeOptions};
4-
use firecrawl::FirecrawlApp;
4+
use firecrawl::{FirecrawlApp, FirecrawlError};
55
use serde_json::json;
66
use std::env;
77

@@ -155,3 +155,29 @@ async fn test_llm_extraction() {
155155
assert!(llm_extraction["supports_sso"].is_boolean());
156156
assert!(llm_extraction["is_open_source"].is_boolean());
157157
}
158+
159+
#[test]
160+
fn test_api_key_requirements() {
161+
dotenv().ok();
162+
163+
let api_url = env::var("API_URL").unwrap_or("http://localhost:3002".to_string());
164+
let api_key = env::var("TEST_API_KEY").ok();
165+
166+
match (api_url.contains("api.firecrawl.dev"), api_key) {
167+
(false, _) => {
168+
let result = FirecrawlApp::new_selfhosted(&api_url, None::<String>);
169+
assert!(result.is_ok(), "Local setup failed: {:?}", result.err().unwrap());
170+
}
171+
(true, None) => {
172+
let result = FirecrawlApp::new_selfhosted(&api_url, None::<String>);
173+
assert!(matches!(
174+
result,
175+
Err(FirecrawlError::APIError(msg, _)) if msg == "Configuration"
176+
));
177+
}
178+
(true, Some(key)) => {
179+
let result = FirecrawlApp::new_selfhosted(&api_url, Some(&key));
180+
assert!(result.is_ok());
181+
}
182+
}
183+
}

0 commit comments

Comments
 (0)