use crate::protocol::{
headers::names,
problem::{Result, request_instance},
stream_name::StreamName,
};
use crate::storage::Storage;
use axum::{
extract::{OriginalUri, State},
http::{HeaderMap, HeaderValue, StatusCode},
response::{IntoResponse, Response},
};
use chrono::Utc;
use std::sync::Arc;
pub async fn stream_metadata<S: Storage>(
State(storage): State<Arc<S>>,
StreamName(name): StreamName,
original_uri: OriginalUri,
) -> Result<Response> {
let instance = request_instance(&original_uri);
let result = (|| -> Result<Response> {
let metadata = storage.head(&name)?;
let mut headers = HeaderMap::new();
headers.insert(
"content-type",
metadata.config.content_type.parse().unwrap(),
);
headers.insert(
names::STREAM_NEXT_OFFSET,
HeaderValue::from_bytes(metadata.next_offset.as_str().as_bytes()).unwrap(),
);
if metadata.closed {
headers.insert(names::STREAM_CLOSED, "true".parse().unwrap());
}
if let Some(expires_at) = metadata.config.expires_at {
let now = Utc::now();
let remaining_seconds = (expires_at - now).num_seconds();
if remaining_seconds > 0 {
headers.insert(
names::STREAM_TTL,
remaining_seconds.to_string().parse().unwrap(),
);
headers.insert(
names::STREAM_EXPIRES_AT,
expires_at.to_rfc3339().parse().unwrap(),
);
}
}
Ok((StatusCode::OK, headers).into_response())
})();
result.map_err(|problem| problem.with_instance(instance))
}