mirror of
https://github.com/R0m1k3/Loki.git
synced 2026-10-17 12:16:21 +02:00
Lot 4 (socle) : store accessible à Rust, routeur /api côté façade
Le Go expose sa base à la façade par l'API interne : lecture, écriture, suppression d'une clé et lecture d'un bucket entier. Il reste l'unique propriétaire du fichier bbolt ; les écritures passent par putBytes/update et invalident son cache comme une écriture locale. Base illisible : 503, pour que Rust distingue « rien » de « pas pu lire ». Côté Rust : client du store (seul point de passage, que la migration finale de la base ne touchera qu'ici), routeur /api avec contexte partagé et garde d'authentification réutilisable ; /api/ping y emménage. Modules réservés aux aides portées ensuite (système, état du moteur, presets, chemins, GGUF). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
a672760f3c
commit
bea29bc6a9
14 files changed
+401
-22
No files matched your search
@@ -0,0 +1,73 @@
|
||||
//! Routes `/api/*` servies par Rust. Toute route listée dans [`handles`] est
|
||||
//! traitée ici ; les autres partent au Go.
|
||||
//!
|
||||
//! Chaque route de pilotage passe par [`Ctx::guard`], port de
|
||||
//! `requireWebAuth` (clé relue à chaque requête, fermeture sur erreur).
|
||||
|
||||
use bytes::Bytes;
|
||||
use hyper::body::Incoming;
|
||||
use hyper::header::HeaderMap;
|
||||
use hyper::{Method, Request, Response, StatusCode};
|
||||
use serde_json::json;
|
||||
|
||||
use crate::auth::{self, HostEnv, InternalClient};
|
||||
use crate::engine;
|
||||
use crate::proxy::Body;
|
||||
use crate::store::Store;
|
||||
|
||||
/// Ce dont les routes ont besoin, partagé par toutes les connexions.
|
||||
pub struct Ctx {
|
||||
pub store: Store,
|
||||
pub internal: InternalClient,
|
||||
pub host_env: HostEnv,
|
||||
/// `$LOKI_HOME` et nom du service moteur (fichiers PID / journal).
|
||||
pub engine: engine::Paths,
|
||||
}
|
||||
|
||||
impl Ctx {
|
||||
/// `Ok` = requête autorisée (avec la version du Go, pour `/api/ping`) ;
|
||||
/// sinon la réponse de refus.
|
||||
pub async fn guard(&self, headers: &HeaderMap) -> Result<String, Box<Response<Body>>> {
|
||||
let info = self.internal.auth().await;
|
||||
if let Some(refus) = auth::authorize(headers, &info, &self.host_env) {
|
||||
return Err(Box::new(refus));
|
||||
}
|
||||
Ok(info.map(|i| i.version).unwrap_or_default())
|
||||
}
|
||||
}
|
||||
|
||||
/// Cette route est-elle servie par Rust ?
|
||||
pub fn handles(_method: &Method, path: &str) -> bool {
|
||||
matches!(path, "/api/ping")
|
||||
}
|
||||
|
||||
pub async fn serve(ctx: &Ctx, req: Request<Incoming>) -> Response<Body> {
|
||||
let (parts, _body) = req.into_parts();
|
||||
let version = match ctx.guard(&parts.headers).await {
|
||||
Ok(v) => v,
|
||||
Err(refus) => return *refus,
|
||||
};
|
||||
match parts.uri.path() {
|
||||
// Vérifie la connectivité ET la clé (200 = bonne clé, 401 = mauvaise).
|
||||
"/api/ping" => auth::json(
|
||||
StatusCode::OK,
|
||||
&json!({ "ok": true, "service": "loki", "version": version }),
|
||||
),
|
||||
_ => not_found(),
|
||||
}
|
||||
}
|
||||
|
||||
fn not_found() -> Response<Body> {
|
||||
auth::json(StatusCode::NOT_FOUND, &json!({ "error": "route inconnue" }))
|
||||
}
|
||||
|
||||
/// Lecture bornée du corps d'une requête (routes POST portées).
|
||||
#[allow(dead_code)]
|
||||
pub async fn read_body(body: Incoming, max: usize) -> Result<Bytes, String> {
|
||||
use http_body_util::{BodyExt, Limited};
|
||||
Limited::new(body, max)
|
||||
.collect()
|
||||
.await
|
||||
.map(|c| c.to_bytes())
|
||||
.map_err(|e| e.to_string())
|
||||
}
|
||||
Reference in new issue
Block a user