feat(api-server): add container loadtest observability
This commit is contained in:
@@ -1,4 +1,13 @@
|
||||
use axum::Json;
|
||||
use std::convert::Infallible;
|
||||
|
||||
use axum::{
|
||||
Json,
|
||||
body::Body,
|
||||
http::{HeaderValue, header},
|
||||
response::{IntoResponse, Response},
|
||||
};
|
||||
use bytes::Bytes;
|
||||
use futures_util::stream;
|
||||
use serde::Serialize;
|
||||
use serde_json::Value;
|
||||
#[cfg(test)]
|
||||
@@ -32,6 +41,30 @@ where
|
||||
Json(serde_json::to_value(data).unwrap_or(Value::Null))
|
||||
}
|
||||
|
||||
pub fn json_success_data_bytes_response(
|
||||
request_context: Option<&RequestContext>,
|
||||
data_json: Bytes,
|
||||
) -> Response {
|
||||
if let Some(context) = request_context
|
||||
&& context.wants_envelope()
|
||||
{
|
||||
let meta = serde_json::to_vec(&build_api_response_meta(Some(context)))
|
||||
.map(Bytes::from)
|
||||
.unwrap_or_else(|_| Bytes::from_static(b"null"));
|
||||
let chunks = [
|
||||
Bytes::from_static(b"{\"ok\":true,\"data\":"),
|
||||
data_json,
|
||||
Bytes::from_static(b",\"error\":null,\"meta\":"),
|
||||
meta,
|
||||
Bytes::from_static(b"}"),
|
||||
];
|
||||
let stream = stream::iter(chunks.into_iter().map(Ok::<Bytes, Infallible>));
|
||||
return json_body_response(Body::from_stream(stream));
|
||||
}
|
||||
|
||||
json_bytes_response(data_json)
|
||||
}
|
||||
|
||||
pub fn json_error_body(
|
||||
request_context: Option<&RequestContext>,
|
||||
error: &ApiErrorPayload,
|
||||
@@ -65,6 +98,19 @@ fn build_api_response_meta(request_context: Option<&RequestContext>) -> ApiRespo
|
||||
)
|
||||
}
|
||||
|
||||
fn json_bytes_response(bytes: Bytes) -> Response {
|
||||
json_body_response(Body::from(bytes))
|
||||
}
|
||||
|
||||
fn json_body_response(body: Body) -> Response {
|
||||
let mut response = body.into_response();
|
||||
response.headers_mut().insert(
|
||||
header::CONTENT_TYPE,
|
||||
HeaderValue::from_static("application/json; charset=utf-8"),
|
||||
);
|
||||
response
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
@@ -106,6 +152,31 @@ mod tests {
|
||||
assert!(body.get("meta").is_none());
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn success_response_streams_cached_data_inside_standard_envelope() {
|
||||
use http_body_util::BodyExt;
|
||||
|
||||
let request_context = build_request_context(true);
|
||||
let response = json_success_data_bytes_response(
|
||||
Some(&request_context),
|
||||
Bytes::from_static(br#"{"items":[]}"#),
|
||||
);
|
||||
let body = response
|
||||
.into_body()
|
||||
.collect()
|
||||
.await
|
||||
.expect("response body should collect")
|
||||
.to_bytes();
|
||||
let payload: Value = serde_json::from_slice(&body).expect("body should be json");
|
||||
|
||||
assert_eq!(payload["ok"], Value::Bool(true));
|
||||
assert_eq!(payload["data"]["items"], Value::Array(Vec::new()));
|
||||
assert_eq!(
|
||||
payload["meta"]["requestId"],
|
||||
Value::String("req-test".to_string())
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn error_body_returns_legacy_shape_without_envelope_header() {
|
||||
let request_context = build_request_context(false);
|
||||
|
||||
Reference in New Issue
Block a user