use reqwest::{Client, Error};
use serde_json::Value;
const BASE_URL: &str = "https://api.shodan.io";
#[derive(Debug, Clone)]
pub struct ShodanClient {
api_key: String,
client: Client,
}
impl ShodanClient {
pub fn new(api_key: String) -> Self {
Self {
api_key,
client: Client::new(),
}
}
async fn request(&self, endpoint: &str) -> Result<Value, Error> {
let url = format!("{BASE_URL}/{endpoint}?key={}", self.api_key);
let response = self.client.get(&url).send().await?;
let json = response.json::<Value>().await?;
Ok(json)
}
pub async fn host_info(&self, ip_address: &str) -> Result<Value, Error> {
let endpoint = format!("shodan/host/{}", ip_address);
self.request(&endpoint).await
}
pub async fn search(&self, query: &str) -> Result<Value, Error> {
let endpoint = format!("shodan/host/search?query={}", query);
self.request(&endpoint).await
}
pub async fn honeyscore(&self, ip_address: &str) -> Result<Value, Error> {
let endpoint = format!("labs/honeyscore/{}", ip_address);
self.request(&endpoint).await
}
}
pub async fn get_host_info(api_key: &str, ip_address: &str) -> Result<Value, Error> {
ShodanClient::new(api_key.to_string())
.host_info(ip_address)
.await
}
pub async fn search_shodan(api_key: &str, query: &str) -> Result<Value, Error> {
ShodanClient::new(api_key.to_string())
.search(query)
.await
}
pub async fn get_honeyscore(api_key: &str, ip_address: &str) -> Result<Value, Error> {
ShodanClient::new(api_key.to_string())
.honeyscore(ip_address)
.await
}