1use crate::error::Error;
2use crate::fetch::{FetchKind, FetchOutputModes, FetchPhase};
3use crate::middleware::MiddlewareKind;
4
5pub struct MiddlewareMetadata {
6 pub kind: MiddlewareKind,
7 pub stateless: bool,
8 pub needs_body: bool,
9 pub validate_args: fn(&serde_json::Value) -> Result<(), Error>,
10}
11
12pub trait MiddlewareMetadataProvider {
13 fn get(&self, name: &str) -> Option<MiddlewareMetadata>;
14}
15
16pub struct FetchMetadata {
17 pub kind: FetchKind,
18 pub phase: FetchPhase,
19 pub output_modes: FetchOutputModes,
20 pub validate_args: fn(&serde_json::Value) -> Result<(), Error>,
21}
22
23pub trait FetchMetadataProvider {
24 fn get(&self, kind: FetchKind) -> Option<FetchMetadata>;
25}
26
27#[cfg(test)]
28mod tests {
29 use serde_json::{Value, json};
30
31 use super::*;
32 use crate::error::Error;
33
34 fn reject_null_accept_object(v: &Value) -> Result<(), Error> {
35 match v {
36 Value::Object(_) => Ok(()),
37 _ => Err(Error::compile("expected object")),
38 }
39 }
40
41 struct StaticMwProvider;
42 impl MiddlewareMetadataProvider for StaticMwProvider {
43 fn get(&self, name: &str) -> Option<MiddlewareMetadata> {
44 if name == "rate_limit" {
45 Some(MiddlewareMetadata {
46 kind: MiddlewareKind::L7Request,
47 stateless: false,
48 needs_body: false,
49 validate_args: reject_null_accept_object,
50 })
51 } else {
52 None
53 }
54 }
55 }
56
57 struct StaticFetchProvider;
58 impl FetchMetadataProvider for StaticFetchProvider {
59 fn get(&self, kind: FetchKind) -> Option<FetchMetadata> {
60 if kind == FetchKind::HttpProxy {
61 Some(FetchMetadata {
62 kind: FetchKind::HttpProxy,
63 phase: FetchPhase::L7,
64 output_modes: FetchOutputModes { response: true, tunnel: false },
65 validate_args: reject_null_accept_object,
66 })
67 } else {
68 None
69 }
70 }
71 }
72
73 #[test]
74 fn middleware_provider_returns_known_record_and_none_for_unknown() {
75 let p = StaticMwProvider;
76 let meta = p.get("rate_limit").expect("known entry");
77 assert_eq!(meta.kind, MiddlewareKind::L7Request);
78 assert!(!meta.stateless);
79 assert!(!meta.needs_body);
80 assert!(p.get("no_such_middleware").is_none());
81 }
82
83 #[test]
84 fn middleware_validate_args_fn_pointer_dispatches() {
85 let p = StaticMwProvider;
86 let meta = p.get("rate_limit").expect("known entry");
87 assert!((meta.validate_args)(&Value::Null).is_err());
88 assert!((meta.validate_args)(&json!({ "rate": 100 })).is_ok());
89 }
90
91 #[test]
92 fn middleware_provider_is_object_safe() {
93 let p: &dyn MiddlewareMetadataProvider = &StaticMwProvider;
94 assert!(p.get("rate_limit").is_some());
95 assert!(p.get("unknown").is_none());
96 }
97
98 #[test]
99 fn fetch_provider_returns_known_kind_and_none_for_unknown() {
100 let p = StaticFetchProvider;
101 let meta = p.get(FetchKind::HttpProxy).expect("known kind");
102 assert_eq!(meta.kind, FetchKind::HttpProxy);
103 assert_eq!(meta.phase, FetchPhase::L7);
104 assert_eq!(meta.output_modes, FetchOutputModes { response: true, tunnel: false });
105 assert!(p.get(FetchKind::L4Forward).is_none());
106 }
107
108 #[test]
109 fn fetch_validate_args_fn_pointer_dispatches() {
110 let p = StaticFetchProvider;
111 let meta = p.get(FetchKind::HttpProxy).expect("known kind");
112 assert!((meta.validate_args)(&Value::Null).is_err());
113 assert!((meta.validate_args)(&json!({ "upstream": "127.0.0.1:80" })).is_ok());
114 }
115
116 #[test]
117 fn fetch_provider_is_object_safe() {
118 let p: &dyn FetchMetadataProvider = &StaticFetchProvider;
119 assert!(p.get(FetchKind::HttpProxy).is_some());
120 assert!(p.get(FetchKind::WebSocketUpgrade).is_none());
121 }
122}