use grapsus_config::{
Config, ListenerConfig, MatchCondition, RouteConfig, ServiceType, UpstreamConfig,
UpstreamTarget,
};
use std::collections::HashMap;
use std::net::SocketAddr;
use tempfile::TempDir;
use tokio::fs;
pub const TEST_PORT: u16 = 18080;
pub const TEST_ADMIN_PORT: u16 = 19090;
pub fn minimal_config() -> Config {
Config {
listeners: vec![ListenerConfig {
address: format!("127.0.0.1:{}", TEST_PORT).parse().unwrap(),
tls: None,
http2: false,
}],
admin: None,
routes: vec![],
upstreams: vec![],
agents: vec![],
global: Default::default(),
}
}
pub fn test_upstream(id: &str, targets: Vec<&str>) -> UpstreamConfig {
UpstreamConfig {
id: id.to_string(),
targets: targets
.into_iter()
.map(|t| UpstreamTarget {
address: t.to_string(),
weight: 100,
})
.collect(),
load_balancing: Default::default(),
health_check: None,
connection_pool: Default::default(),
tls: None,
}
}
pub fn test_route(id: &str, path: &str, upstream: &str) -> RouteConfig {
RouteConfig {
id: id.to_string(),
priority: Default::default(),
matches: vec![MatchCondition::Path {
pattern: path.to_string(),
match_type: Default::default(),
}],
upstream: Some(upstream.to_string()),
service_type: ServiceType::Api,
static_files: None,
api_schema: None,
error_pages: None,
timeout_ms: None,
retry: None,
agents: vec![],
policies: Default::default(),
}
}
pub struct StaticFilesFixture {
pub temp_dir: TempDir,
pub root: std::path::PathBuf,
}
impl StaticFilesFixture {
pub async fn new() -> anyhow::Result<Self> {
let temp_dir = TempDir::new()?;
let root = temp_dir.path().to_path_buf();
fs::write(root.join("index.html"), "<html><body>Test</body></html>").await?;
fs::write(root.join("style.css"), "body { margin: 0; }").await?;
fs::write(root.join("app.js"), "console.log('test');").await?;
fs::create_dir_all(root.join("assets")).await?;
fs::write(root.join("assets/image.txt"), "fake image data").await?;
Ok(Self { temp_dir, root })
}
pub async fn add_file(&self, path: &str, content: &[u8]) -> anyhow::Result<()> {
let file_path = self.root.join(path);
if let Some(parent) = file_path.parent() {
fs::create_dir_all(parent).await?;
}
fs::write(file_path, content).await?;
Ok(())
}
}
pub fn test_request_id() -> String {
format!("test-{}", uuid::Uuid::new_v4())
}
pub fn assert_content_type(headers: &http::HeaderMap, expected: &str) {
let content_type = headers
.get("Content-Type")
.expect("missing Content-Type header")
.to_str()
.expect("invalid Content-Type header");
assert!(
content_type.contains(expected),
"expected Content-Type to contain '{}', got '{}'",
expected,
content_type
);
}
pub fn assert_has_header(headers: &http::HeaderMap, name: &str) {
assert!(
headers.contains_key(name),
"expected header '{}' to be present",
name
);
}