// Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. use proxy_wasm_experimental as proxy_wasm; use proxy_wasm::traits::*; use proxy_wasm::types::*; #[no_mangle] pub fn _start() { proxy_wasm::set_log_level(LogLevel::Trace); proxy_wasm::set_root_context(|_| -> Box { Box::new(HttpBodyRoot) }); } struct HttpBodyRoot; impl Context for HttpBodyRoot {} impl RootContext for HttpBodyRoot { fn get_type(&self) -> Option { Some(ContextType::HttpContext) } fn create_http_context(&self, _: u32) -> Option> { Some(Box::new(HttpBody)) } } struct HttpBody; impl Context for HttpBody {} impl HttpContext for HttpBody { fn on_http_response_headers(&mut self, _: usize, _: bool) -> Action { // If there is a Content-Length header and we change the length of // the body later, then clients will break. So remove it. // We must do this here, because once we exit this function we // can no longer modify the response headers. self.set_http_response_header("content-length", None); Action::Continue } fn on_http_response_body(&mut self, body_size: usize, end_of_stream: bool) -> Action { if !end_of_stream { // Wait -- we'll be called again when the complete body is buffered // at the host side. return Action::Pause; } // Replace the message body if it contains the text "secret". // Since we returned "Pause" previuously, this will return the whole body. if let Some(body_bytes) = self.get_http_response_body(0, body_size) { let body_str = body_bytes.into_string().unwrap(); if body_str.contains("secret") { let new_body = format!("Original message body ({} bytes) redacted.", body_size); self.set_http_response_body(0, body_size, &new_body.into_bytes()); } } Action::Continue } }