diff --git a/README.md b/README.md index 7db3cdc..97a9dc5 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,7 @@ - [HTTP Response body](./examples/http_body/) - [HTTP Configuration](./examples/http_config/) - [gRPC Auth (random)](./examples/grpc_auth_random/) +- [Filter metadata](./examples/filter_metadata/) ## Articles & blog posts from the community diff --git a/examples/filter_metadata/Cargo.toml b/examples/filter_metadata/Cargo.toml new file mode 100644 index 0000000..5916bb4 --- /dev/null +++ b/examples/filter_metadata/Cargo.toml @@ -0,0 +1,21 @@ +[package] +publish = false +name = "proxy-wasm-example-filter-metadata" +version = "0.0.1" +authors = ["Martijn Swaagma "] +description = "Proxy-Wasm plugin example: Filter metadata" +license = "Apache-2.0" +edition = "2018" + +[lib] +crate-type = ["cdylib"] + +[dependencies] +proxy-wasm = { path = "../../" } + +[profile.release] +lto = true +opt-level = 3 +codegen-units = 1 +panic = "abort" +strip = "debuginfo" diff --git a/examples/filter_metadata/README.md b/examples/filter_metadata/README.md new file mode 100644 index 0000000..13eb08e --- /dev/null +++ b/examples/filter_metadata/README.md @@ -0,0 +1,33 @@ +## Proxy-Wasm plugin example: Metadata + +Proxy-Wasm plugin that demonstrates reading metadata set by other filters + +### Building + +```sh +$ cargo build --target wasm32-wasip1 --release +``` + +### Using in Envoy + +This example can be run with [`docker compose`](https://docs.docker.com/compose/install/) +and has a matching Envoy configuration. + +```sh +$ docker compose up +``` + +Send a HTTP request to `localhost:10000/` will return the configured response. + +```sh +$ curl localhost:10000/ +Welcome, set the `x-custom-metadata` header to change the response! +``` + + +Send a HTTP request to `localhost:10000/` with a `x-custom-metadata` header value. + +```sh +$ curl localhost:10000/ -H "x-custom-metadata: some-value" +Custom response with `x-custom-metadata` value "some-value" +``` diff --git a/examples/filter_metadata/docker-compose.yaml b/examples/filter_metadata/docker-compose.yaml new file mode 100644 index 0000000..844dc9b --- /dev/null +++ b/examples/filter_metadata/docker-compose.yaml @@ -0,0 +1,27 @@ +# Copyright 2022 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. + +services: + envoy: + image: envoyproxy/envoy:v1.31-latest + hostname: envoy + ports: + - "10000:10000" + volumes: + - ./envoy.yaml:/etc/envoy/envoy.yaml + - ./target/wasm32-wasip1/release:/etc/envoy/proxy-wasm-plugins + networks: + - envoymesh +networks: + envoymesh: {} diff --git a/examples/filter_metadata/envoy.yaml b/examples/filter_metadata/envoy.yaml new file mode 100644 index 0000000..083398c --- /dev/null +++ b/examples/filter_metadata/envoy.yaml @@ -0,0 +1,73 @@ +# Copyright 2022 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. + +static_resources: + listeners: + address: + socket_address: + address: 0.0.0.0 + port_value: 10000 + filter_chains: + - filters: + - name: envoy.filters.network.http_connection_manager + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager + stat_prefix: ingress_http + codec_type: AUTO + route_config: + name: local_routes + virtual_hosts: + - name: local_service + domains: + - "*" + routes: + - match: + prefix: "/" + direct_response: + status: 200 + body: + inline_string: "Welcome, set the `x-custom-metadata` header to change the response!\n" + http_filters: + # Set metadata + - name: envoy.filters.http.lua + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua + default_source_code: + inline_string: | + function envoy_on_request(request_handle) + local headers = request_handle:headers() + local data = headers:get("x-custom-metadata") + + if data then + request_handle:streamInfo():dynamicMetadata():set("envoy.filters.http.lua", "x-custom-metadata", data) + end + + request_handle:logInfo("Metadata set by lua filter") + end + # Read it from a WASM filter + - name: envoy.filters.http.wasm + typed_config: + "@type": type.googleapis.com/udpa.type.v1.TypedStruct + type_url: type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm + value: + config: + name: "metadata_filter" + vm_config: + runtime: "envoy.wasm.runtime.v8" + code: + local: + filename: "/etc/envoy/proxy-wasm-plugins/proxy_wasm_example_filter_metadata.wasm" + - name: envoy.filters.http.router + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router diff --git a/examples/filter_metadata/src/lib.rs b/examples/filter_metadata/src/lib.rs new file mode 100644 index 0000000..9017e3a --- /dev/null +++ b/examples/filter_metadata/src/lib.rs @@ -0,0 +1,56 @@ +// 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::traits::*; +use proxy_wasm::types::*; + +proxy_wasm::main! {{ + proxy_wasm::set_log_level(LogLevel::Trace); + proxy_wasm::set_http_context(|_, _| -> Box { Box::new(MetadataHttp {}) }); +}} + +struct MetadataHttp {} + +impl Context for MetadataHttp {} + +impl HttpContext for MetadataHttp { + fn on_http_request_headers(&mut self, _: usize, _: bool) -> Action { + // Read data set by the lua filter + match self.get_property(vec![ + "metadata", + "filter_metadata", + "envoy.filters.http.lua", + "x-custom-metadata", + ]) { + Some(metadata) => match String::from_utf8(metadata) { + Ok(data) => { + self.send_http_response( + 200, + vec![("Powered-By", "proxy-wasm")], + Some( + format!( + "Custom response with `x-custom-metadata` value {:?}!\n", + data + ) + .as_bytes(), + ), + ); + Action::Pause + } + _ => Action::Continue, + }, + _ => Action::Continue, + } + } +}