Expand description
§Serper SDK
A minimalistic yet ergonomic Rust SDK for the Serper Google Search API.
§Features
- Type-safe API with comprehensive error handling
- Modular architecture with clear separation of concerns
- Async-first design with concurrent request support
- Flexible configuration with environment variable support
- Comprehensive testing with extensive test coverage
§Quick Start
use serper_sdk::{SearchService, SearchQuery, SearchResponse};
fn main() -> Result<(), Box<dyn std::error::Error>> {
// Create a search service (with example API key for documentation)
let service = SearchService::new("demo-key-for-docs".to_string())?;
// Build a search query
let query = SearchQuery::new("Hamze Ghalebi CTO at Remolab".to_string())?
.with_location("Paris".to_string())
.with_page(1);
// Create a mock response for documentation example
let response = SearchResponse::new();
// Process results (in real usage, you'd use service.search(&query).await?)
println!("Query: {}", query.q);
println!("Location: {:?}", query.location);
println!("Results found: {}", response.organic_count());
Ok(())
}
§Architecture
The SDK is organized into several focused modules:
core
: Fundamental types and error handlingsearch
: Query construction and response parsinghttp
: Transport layer and HTTP client functionalityconfig
: Configuration managementutils
: Common utilities and helpers
§Advanced Usage
§Custom Configuration
use serper_sdk::{SearchService, http::TransportConfig};
use std::time::Duration;
fn main() -> Result<(), Box<dyn std::error::Error>> {
// Create service with custom configuration
let transport_config = TransportConfig::default()
.with_timeout(Duration::from_secs(60));
let service = SearchService::with_config(
"demo-key-for-docs".to_string(),
"https://google.serper.dev".to_string(),
transport_config
)?;
println!("Service created with custom 60s timeout");
Ok(())
}
§Concurrent Searches
use serper_sdk::{SearchService, SearchQuery};
fn main() -> Result<(), Box<dyn std::error::Error>> {
// Create service and queries
let _service = SearchService::new("demo-key-for-docs".to_string())?;
let queries = vec![
SearchQuery::new("Hamze Ghalebi CTO at Remolab".to_string())?,
SearchQuery::new("Hamze Ghalebi Remolab technology".to_string())?,
SearchQuery::new("Remolab France innovation".to_string())?,
];
// In real usage: let results = service.search_concurrent(&queries, Some(3)).await?;
println!("Prepared {} queries for concurrent execution", queries.len());
for (i, query) in queries.iter().enumerate() {
println!("Query {}: {}", i + 1, query.q);
}
Ok(())
}
§Query Builder Pattern
use serper_sdk::{SearchService, SearchQueryBuilder};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let _service = SearchService::new("demo-key-for-docs".to_string())?;
// Demonstrate the builder pattern
let query = SearchQueryBuilder::new()
.query("Hamze Ghalebi CTO at Remolab")
.location("Paris")
.country("fr")
.language("en")
.page(1)
.build()?;
println!("Built query: {}", query.q);
println!("Location: {:?}", query.location);
println!("Country: {:?}", query.gl);
println!("Language: {:?}", query.hl);
println!("Page: {:?}", query.page);
// In real usage: let response = service.search_with(|builder| { ... }).await?;
Ok(())
}
Re-exports§
pub use config::SdkConfig;
pub use config::SdkConfigBuilder;
pub use core::Result;
pub use core::SerperError;
pub use search::AnswerBox;
pub use search::KnowledgeGraph;
pub use search::OrganicResult;
pub use search::SearchMetadata;
pub use search::SearchQuery;
pub use search::SearchQueryBuilder;
pub use search::SearchResponse;
pub use search::SearchService;
pub use search::SearchService as SerperClient;