mockforge_openapi/response_rewriter.rs
1//! Response-mutation hooks the OpenAPI router calls on each generated body.
2//!
3//! 1. [`ResponseRewriter`] expands template tokens like `{{uuid}}`.
4//! 2. [`OverrideHook`] applies user-supplied override rules.
5//!
6//! Both engines live in `mockforge-core`. The router dispatches through
7//! these traits so `mockforge-openapi` does not depend on core's templating
8//! and conditions graph. Core supplies the implementations
9//! (`mockforge_core::openapi_rewriter::CoreResponseRewriter` and
10//! `mockforge_core::SharedOverrides`).
11
12use axum::http::HeaderMap;
13use serde_json::Value;
14
15/// Hook for template token expansion, called only when expansion is enabled
16/// for the current context.
17pub trait ResponseRewriter: Send + Sync {
18 /// Expand template tokens (e.g. `{{uuid}}`, `{{now}}`) in-place inside
19 /// the response body.
20 fn expand_tokens(&self, body: &mut Value);
21}
22
23/// The request an override rule is evaluated against
24#[derive(Debug, Clone, Copy)]
25pub struct OverrideRequest<'a> {
26 /// HTTP method, uppercase
27 pub method: &'a str,
28 /// The OpenAPI path template, e.g. `/users/{id}`
29 pub path_template: &'a str,
30 /// The operation's `operationId`, or empty when the spec has none
31 pub operation_id: &'a str,
32 /// The operation's OpenAPI tags followed by its `operationId`
33 pub tags: &'a [String],
34 /// Request headers
35 pub headers: &'a HeaderMap,
36 /// Raw query string, without the leading `?`
37 pub query: Option<&'a str>,
38 /// Raw request body
39 pub body: &'a [u8],
40}
41
42/// Hook that applies override rules to a generated response body
43pub trait OverrideHook: Send + Sync {
44 /// Patch `body` in place with every rule that matches `request`
45 fn apply(&self, request: &OverrideRequest<'_>, body: &mut Value);
46}