120 lines
3.3 KiB
Rust
120 lines
3.3 KiB
Rust
use std::collections::BTreeMap;
|
|
|
|
use axum::{
|
|
Json, Router,
|
|
extract::{Path, Query},
|
|
http::HeaderMap,
|
|
routing::{get, post},
|
|
};
|
|
use crank_adapter_rest::{RestAdapter, RestAdapterError, RestRequest};
|
|
use crank_core::{HttpMethod, RestTarget};
|
|
use serde_json::{Value, json};
|
|
use tokio::net::TcpListener;
|
|
|
|
#[tokio::test]
|
|
async fn executes_rest_request_and_normalizes_json_response() {
|
|
let base_url = spawn_test_server().await;
|
|
let adapter = RestAdapter::new();
|
|
let target = RestTarget {
|
|
base_url,
|
|
method: HttpMethod::Post,
|
|
path_template: "/users/{user_id}".to_owned(),
|
|
static_headers: BTreeMap::from([("x-static".to_owned(), "static".to_owned())]),
|
|
};
|
|
let request = RestRequest {
|
|
path_params: BTreeMap::from([("user_id".to_owned(), "42".to_owned())]),
|
|
query_params: BTreeMap::from([("expand".to_owned(), "true".to_owned())]),
|
|
headers: BTreeMap::from([("x-trace-id".to_owned(), "trace-123".to_owned())]),
|
|
body: Some(json!({ "name": "Ada" })),
|
|
timeout_ms: 1_000,
|
|
};
|
|
|
|
let response = adapter.execute(&target, &request).await.unwrap();
|
|
|
|
assert_eq!(response.status_code, 200);
|
|
assert_eq!(
|
|
response.body,
|
|
json!({
|
|
"id": "42",
|
|
"query": "true",
|
|
"trace": "trace-123",
|
|
"static": "static",
|
|
"payload": { "name": "Ada" }
|
|
})
|
|
);
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn returns_unexpected_status_with_normalized_body() {
|
|
let base_url = spawn_test_server().await;
|
|
let adapter = RestAdapter::new();
|
|
let target = RestTarget {
|
|
base_url,
|
|
method: HttpMethod::Get,
|
|
path_template: "/fail".to_owned(),
|
|
static_headers: BTreeMap::new(),
|
|
};
|
|
let request = RestRequest {
|
|
path_params: BTreeMap::new(),
|
|
query_params: BTreeMap::new(),
|
|
headers: BTreeMap::new(),
|
|
body: None,
|
|
timeout_ms: 1_000,
|
|
};
|
|
|
|
let error = adapter.execute(&target, &request).await.unwrap_err();
|
|
|
|
assert!(matches!(
|
|
error,
|
|
RestAdapterError::UnexpectedStatus {
|
|
status: 502,
|
|
body: Value::Object(_)
|
|
}
|
|
));
|
|
}
|
|
|
|
async fn spawn_test_server() -> String {
|
|
let app = Router::new()
|
|
.route("/users/{user_id}", post(create_user))
|
|
.route("/fail", get(fail));
|
|
let listener = TcpListener::bind("127.0.0.1:0").await.unwrap();
|
|
let address = listener.local_addr().unwrap();
|
|
|
|
tokio::spawn(async move {
|
|
axum::serve(listener, app).await.unwrap();
|
|
});
|
|
|
|
format!("http://{}", address)
|
|
}
|
|
|
|
async fn create_user(
|
|
Path(user_id): Path<String>,
|
|
Query(query): Query<BTreeMap<String, String>>,
|
|
headers: HeaderMap,
|
|
Json(payload): Json<Value>,
|
|
) -> Json<Value> {
|
|
let trace = headers
|
|
.get("x-trace-id")
|
|
.and_then(|value| value.to_str().ok())
|
|
.unwrap_or_default();
|
|
let static_header = headers
|
|
.get("x-static")
|
|
.and_then(|value| value.to_str().ok())
|
|
.unwrap_or_default();
|
|
|
|
Json(json!({
|
|
"id": user_id,
|
|
"query": query.get("expand").cloned().unwrap_or_default(),
|
|
"trace": trace,
|
|
"static": static_header,
|
|
"payload": payload
|
|
}))
|
|
}
|
|
|
|
async fn fail() -> (axum::http::StatusCode, Json<Value>) {
|
|
(
|
|
axum::http::StatusCode::BAD_GATEWAY,
|
|
Json(json!({ "error": "upstream failed" })),
|
|
)
|
|
}
|