Skip to main content

haystack_server/ops/
formats.rs

1//! The `formats` op — list supported MIME types.
2
3use axum::extract::State;
4use axum::http::{HeaderMap, StatusCode};
5use axum::response::{IntoResponse, Response};
6
7use haystack_core::data::{HCol, HDict, HGrid};
8use haystack_core::kinds::Kind;
9
10use crate::content;
11use crate::state::SharedState;
12
13/// GET /api/formats — returns a grid listing supported MIME formats.
14pub async fn handle(State(_state): State<SharedState>, headers: HeaderMap) -> Response {
15    let accept = headers
16        .get("Accept")
17        .and_then(|v| v.to_str().ok())
18        .unwrap_or("");
19
20    let formats = vec![
21        ("text/zinc", "Zinc"),
22        ("application/json", "JSON (Haystack 4)"),
23        ("text/trio", "Trio"),
24        ("application/json;v=3", "JSON (Haystack 3)"),
25    ];
26
27    let cols = vec![HCol::new("mime"), HCol::new("receive"), HCol::new("send")];
28    let rows: Vec<HDict> = formats
29        .into_iter()
30        .map(|(mime, _label)| {
31            let mut row = HDict::new();
32            row.set("mime", Kind::Str(mime.to_string()));
33            row.set("receive", Kind::Marker);
34            row.set("send", Kind::Marker);
35            row
36        })
37        .collect();
38
39    let grid = HGrid::from_parts(HDict::new(), cols, rows);
40    match content::encode_response_grid(&grid, accept) {
41        Ok((body, ct)) => ([(axum::http::header::CONTENT_TYPE, ct)], body).into_response(),
42        Err(e) => {
43            log::error!("Failed to encode formats grid: {e}");
44            (StatusCode::INTERNAL_SERVER_ERROR, "encoding error").into_response()
45        }
46    }
47}