本页面提供了针对插件的一些常见使用场景的代码示例。
如需查看更多 Rust、Go 和 C++ 插件示例,请参阅 Service Extensions 插件 GitHub 代码库。
插件功能目前处于 Media CDN 的预览版阶段。
添加 HTTP 请求和响应标头
以下代码示例展示了如何添加 HTTP 请求标头。
C++
#include "proxy_wasm_intrinsics.h"
class MyHttpContext : public Context {
public:
explicit MyHttpContext(uint32_t id, RootContext* root) : Context(id, root) {}
FilterHeadersStatus onRequestHeaders(uint32_t headers,
bool end_of_stream) override {
// Always be a friendly proxy.
addRequestHeader("Message", "hello");
replaceRequestHeader("Welcome", "warm");
return FilterHeadersStatus::Continue;
}
};
static RegisterContextFactory register_StaticContext(
CONTEXT_FACTORY(MyHttpContext), ROOT_FACTORY(RootContext));Go
package main
import (
"fmt"
"github.com/proxy-wasm/proxy-wasm-go-sdk/proxywasm"
"github.com/proxy-wasm/proxy-wasm-go-sdk/proxywasm/types"
)
func main() {}
func init() {
proxywasm.SetVMContext(&vmContext{})
}
type vmContext struct {
types.DefaultVMContext
}
type pluginContext struct {
types.DefaultPluginContext
}
type httpContext struct {
types.DefaultHttpContext
}
func (vc *vmContext) NewPluginContext(contextID uint32) types.PluginContext {
return &pluginContext{}
}
func (pc *pluginContext) NewHttpContext(contextID uint32) types.HttpContext {
return &httpContext{}
}
func (ctx *httpContext) OnHttpRequestHeaders(numHeaders int, endOfStream bool) types.Action {
defer func() {
if err := recover(); err != nil {
proxywasm.SendHttpResponse(500, [][2]string{}, []byte(fmt.Sprintf("%v", err)), 0)
}
}()
// Add and replace headers.
if err := proxywasm.AddHttpRequestHeader("Message", "hello"); err != nil {
panic(err)
}
if err := proxywasm.ReplaceHttpRequestHeader("Welcome", "warm"); err != nil {
panic(err)
}
return types.ActionContinue
}
Rust
use proxy_wasm::traits::*;
use proxy_wasm::types::*;
proxy_wasm::main! {{
proxy_wasm::set_log_level(LogLevel::Trace);
proxy_wasm::set_http_context(|_, _| -> Box<dyn HttpContext> { Box::new(MyHttpContext) });
}}
struct MyHttpContext;
impl Context for MyHttpContext {}
impl HttpContext for MyHttpContext {
fn on_http_request_headers(&mut self, _: usize, _: bool) -> Action {
// Always be a friendly proxy.
self.add_http_request_header("Message", "hello");
self.set_http_request_header("Welcome", Some("warm"));
return Action::Continue;
}
}以下代码示例展示了如何添加 HTTP 响应标头。
C++
#include "proxy_wasm_intrinsics.h"
class MyHttpContext : public Context {
public:
explicit MyHttpContext(uint32_t id, RootContext* root) : Context(id, root) {}
FilterHeadersStatus onResponseHeaders(uint32_t headers,
bool end_of_stream) override {
// Conditionally add to a header value.
auto msg = getResponseHeader("Message");
if (msg && msg->view() == "foo") {
addResponseHeader("Message", "bar");
}
// Unconditionally remove a header.
removeResponseHeader("Welcome");
return FilterHeadersStatus::Continue;
}
};
static RegisterContextFactory register_StaticContext(
CONTEXT_FACTORY(MyHttpContext), ROOT_FACTORY(RootContext));Go
package main
import (
"fmt"
"github.com/proxy-wasm/proxy-wasm-go-sdk/proxywasm"
"github.com/proxy-wasm/proxy-wasm-go-sdk/proxywasm/types"
)
func main() {}
func init() {
proxywasm.SetVMContext(&vmContext{})
}
type vmContext struct {
types.DefaultVMContext
}
type pluginContext struct {
types.DefaultPluginContext
}
type httpContext struct {
types.DefaultHttpContext
}
func (vc *vmContext) NewPluginContext(contextID uint32) types.PluginContext {
return &pluginContext{}
}
func (pc *pluginContext) NewHttpContext(contextID uint32) types.HttpContext {
return &httpContext{}
}
func (ctx *httpContext) OnHttpResponseHeaders(numHeaders int, endOfStream bool) types.Action {
defer func() {
if err := recover(); err != nil {
proxywasm.SendHttpResponse(500, [][2]string{}, []byte(fmt.Sprintf("%v", err)), 0)
}
}()
// Conditionally add to a header value.
msgValue, err := proxywasm.GetHttpResponseHeader("Message")
if err != nil {
proxywasm.LogCriticalf("failed to get 'Message' header: %v", err)
} else if msgValue == "foo" {
if err := proxywasm.AddHttpResponseHeader("Message", "bar"); err != nil {
panic(err)
}
}
// Unconditionally remove the "Welcome" header.
if err := proxywasm.RemoveHttpResponseHeader("Welcome"); err != nil {
panic(err)
}
return types.ActionContinue
}
Rust
use proxy_wasm::traits::*;
use proxy_wasm::types::*;
proxy_wasm::main! {{
proxy_wasm::set_log_level(LogLevel::Trace);
proxy_wasm::set_http_context(|_, _| -> Box<dyn HttpContext> { Box::new(MyHttpContext) });
}}
struct MyHttpContext;
impl Context for MyHttpContext {}
impl HttpContext for MyHttpContext {
fn on_http_response_headers(&mut self, _: usize, _: bool) -> Action {
// Conditionally add to a header value.
let msg = self.get_http_response_header("Message");
if msg.unwrap_or_default() == "foo" {
self.add_http_response_header("Message", "bar");
}
// Unconditionally remove a header.
self.set_http_response_header("Welcome", None);
return Action::Continue;
}
}重写请求网址
以下代码示例展示了如何使用正则表达式重写请求网址。以下代码示例移除了部分路径,但任何 URI 突变(例如路径、查询或片段)都是可行的。
这些示例还展示了有关正则表达式的最佳实践,即使用线性时间正则表达式库并在插件初始化时编译表达式。
C++
#include "proxy_wasm_intrinsics.h"
#include "re2/re2.h"
class MyRootContext : public RootContext {
public:
explicit MyRootContext(uint32_t id, std::string_view root_id)
: RootContext(id, root_id) {}
bool onConfigure(size_t) override {
// Compile the regex expression at plugin setup time.
path_match.emplace("/foo-([^/]+)/");
return path_match->ok();
}
std::optional<re2::RE2> path_match;
};
class MyHttpContext : public Context {
public:
explicit MyHttpContext(uint32_t id, RootContext* root)
: Context(id, root), root_(static_cast<MyRootContext*>(root)) {}
FilterHeadersStatus onRequestHeaders(uint32_t headers,
bool end_of_stream) override {
const auto path = getRequestHeader(":path");
if (!path) {
LOG_ERROR("Failed to get :path header");
return FilterHeadersStatus::Continue;
}
std::string edit = path->toString(); // mutable copy
if (re2::RE2::Replace(&edit, *root_->path_match, "/\\1/")) {
if (replaceRequestHeader(":path", edit) != WasmResult::Ok) {
LOG_ERROR("Failed to replace :path header");
}
}
return FilterHeadersStatus::Continue;
}
private:
const MyRootContext* root_;
};
static RegisterContextFactory register_StaticContext(
CONTEXT_FACTORY(MyHttpContext), ROOT_FACTORY(MyRootContext));Go
package main
import (
"fmt"
"regexp"
"github.com/proxy-wasm/proxy-wasm-go-sdk/proxywasm"
"github.com/proxy-wasm/proxy-wasm-go-sdk/proxywasm/types"
)
func main() {}
func init() {
proxywasm.SetVMContext(&vmContext{})
}
type vmContext struct {
types.DefaultVMContext
}
type pluginContext struct {
types.DefaultPluginContext
pathMatch *regexp.Regexp
}
type httpContext struct {
types.DefaultHttpContext
pluginContext *pluginContext
}
func (*vmContext) NewPluginContext(contextID uint32) types.PluginContext {
return &pluginContext{}
}
func (ctx *pluginContext