pub mod capabilities;
pub mod records;
use crate::error::{ServiceError, ServiceResult};
use axum::{
extract::{Query, State},
response::Response,
};
use serde::Deserialize;
use std::sync::Arc;
#[derive(Clone)]
pub struct CswState {
pub service_info: Arc<ServiceInfo>,
pub records: Arc<dashmap::DashMap<String, MetadataRecord>>,
}
#[derive(Debug, Clone)]
pub struct ServiceInfo {
pub title: String,
pub abstract_text: Option<String>,
pub provider: String,
pub service_url: String,
pub versions: Vec<String>,
}
#[derive(Debug, Clone)]
pub struct MetadataRecord {
pub identifier: String,
pub title: String,
pub abstract_text: Option<String>,
pub keywords: Vec<String>,
pub bbox: Option<(f64, f64, f64, f64)>,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "UPPERCASE")]
pub struct CswRequest {
pub service: Option<String>,
pub version: Option<String>,
pub request: String,
#[serde(flatten)]
pub params: serde_json::Value,
}
impl CswState {
pub fn new(service_info: ServiceInfo) -> Self {
Self {
service_info: Arc::new(service_info),
records: Arc::new(dashmap::DashMap::new()),
}
}
pub fn add_record(&self, record: MetadataRecord) -> ServiceResult<()> {
self.records.insert(record.identifier.clone(), record);
Ok(())
}
}
pub async fn handle_csw_request(
State(state): State<CswState>,
Query(params): Query<CswRequest>,
) -> Result<Response, ServiceError> {
if let Some(ref service) = params.service {
if service.to_uppercase() != "CSW" {
return Err(ServiceError::InvalidParameter(
"SERVICE".to_string(),
format!("Expected 'CSW', got '{}'", service),
));
}
}
match params.request.to_uppercase().as_str() {
"GETCAPABILITIES" => {
let version = params.version.as_deref().unwrap_or("2.0.2");
capabilities::handle_get_capabilities(&state, version).await
}
"GETRECORDS" => {
let version = params.version.as_deref().unwrap_or("2.0.2");
records::handle_get_records(&state, version, ¶ms.params).await
}
"GETRECORDBYID" => {
let version = params.version.as_deref().unwrap_or("2.0.2");
records::handle_get_record_by_id(&state, version, ¶ms.params).await
}
_ => Err(ServiceError::UnsupportedOperation(params.request.clone())),
}
}