Skip to main content

haystack_server/ops/
formats.rs

1//! The `formats` op — list supported MIME types.
2//!
3//! # Overview
4//!
5//! `GET /api/formats` returns the data formats this server can send and
6//! receive. No request grid is needed.
7//!
8//! # Response Grid Columns
9//!
10//! | Column    | Kind   | Description                          |
11//! |-----------|--------|--------------------------------------|
12//! | `mime`    | Str    | MIME type string                     |
13//! | `receive` | Marker | Server can decode this format        |
14//! | `send`   | Marker | Server can encode this format        |
15//!
16//! # Errors
17//!
18//! - **500 Internal Server Error** — encoding failure.
19
20use actix_web::{HttpRequest, HttpResponse, web};
21
22use haystack_core::data::{HCol, HDict, HGrid};
23use haystack_core::kinds::Kind;
24
25use crate::content;
26use crate::state::AppState;
27
28/// GET /api/formats — returns a grid listing supported MIME formats.
29///
30/// Each row represents a MIME type with `mime` (Str), `receive` (Marker),
31/// and `send` (Marker) columns. Supported formats: Zinc, JSON v4, Trio,
32/// JSON v3.
33pub async fn handle(req: HttpRequest, _state: web::Data<AppState>) -> HttpResponse {
34    let accept = req
35        .headers()
36        .get("Accept")
37        .and_then(|v| v.to_str().ok())
38        .unwrap_or("");
39
40    let formats = vec![
41        ("text/zinc", "Zinc"),
42        ("application/json", "JSON (Haystack 4)"),
43        ("text/trio", "Trio"),
44        ("application/json;v=3", "JSON (Haystack 3)"),
45    ];
46
47    let cols = vec![HCol::new("mime"), HCol::new("receive"), HCol::new("send")];
48    let rows: Vec<HDict> = formats
49        .into_iter()
50        .map(|(mime, _label)| {
51            let mut row = HDict::new();
52            row.set("mime", Kind::Str(mime.to_string()));
53            row.set("receive", Kind::Marker);
54            row.set("send", Kind::Marker);
55            row
56        })
57        .collect();
58
59    let grid = HGrid::from_parts(HDict::new(), cols, rows);
60    match content::encode_response_grid(&grid, accept) {
61        Ok((body, ct)) => HttpResponse::Ok().content_type(ct).body(body),
62        Err(e) => {
63            log::error!("Failed to encode formats grid: {e}");
64            HttpResponse::InternalServerError().body("encoding error")
65        }
66    }
67}