-
Notifications
You must be signed in to change notification settings - Fork 2
/
example.txt
93 lines (80 loc) · 3.13 KB
/
example.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
use log::debug;
use proxy_wasm::hostcalls::log;
use proxy_wasm::types::LogLevel::Info;
use proxy_wasm::traits::*;
use proxy_wasm::types::*;
use std::time::Duration;
use std::any::Any;
#[no_mangle]
pub fn _start() {
//proxy_wasm::set_log_level(wasm::types::LogLevel::Trace);
proxy_wasm::set_http_context(|_, _| -> Box<dyn HttpContext> { Box::new(HttpAuth) });
}
struct HttpAuth;
impl HttpAuth {
fn fail(&mut self) {
debug!("auth: allowed");
self.send_http_response(403, vec![], Some(b"not authorized"));
}
}
// Implement http functions related to this request.
// This is the core of the filter code.
impl HttpContext for HttpAuth {
// This callback will be invoked when request headers arrive
fn on_http_request_headers(&mut self, num_headers: usize) -> Action {
// get all the request headers
let headers = self.get_http_request_headers();
log(Info, "Got {} HTTP headers in #{}.");
// transform them from Vec<(String,String)> to Vec<(&str,&str)>; as dispatch_http_call needs
// Vec<(&str,&str)>.
let ref_headers : Vec<(&str,&str)> = headers.iter().map(|(ref k,ref v)|(k.as_str(),v.as_str())).collect();
// Dispatch a call to the auth-cluster. Here we assume that envoy's config has a cluster
// named auth-cluster. We send the auth cluster all our headers, so it has context to
// perform auth decisions.
let res = self.dispatch_http_call(
"auth-cluster", // cluster name
ref_headers, // headers
None, // no body
vec![], // no trailers
Duration::from_secs(1), // one second timeout
);
// If dispatch reutrn an error, fail the request.
match res {
Err(_) =>{
self.fail();
}
Ok(_) => {}
}
// the dispatch call is asynchronous. This means it returns immediatly, while the request
// happens in the background. When the response arrives `on_http_call_response` will be
// called. In the mean time, we need to pause the request, so it doesn't continue upstream.
Action::Pause
}
fn on_http_response_headers(&mut self, _: usize) -> Action {
// Add a header on the response.
self.set_http_response_header("Hello", Some("world"));
Action::Continue
}
}
impl Context for HttpAuth {
fn on_http_call_response(&mut self, _ : u32, header_size: usize, _: usize, _: usize) {
// We have a response to the http call!
// if we have no headers, it means the http call failed. Fail the incoming request as well.
if header_size == 0 {
self.fail();
return;
}
// Check if the auth server returned "200", if so call `resume_http_request` so request is
// sent upstream.
// Otherwise, fail the incoming request.
match self.get_http_request_header(":status") {
Some(ref status) if status == "200" => {
self.resume_http_request();
}
_ => {
debug!("auth: not authorized");
self.fail();
}
}
}
}