skipper 的扩展包含filter类型的,以及Predicates ,当然script(lua)脚本也是
这次主要是filter类型的开发
filter 接口约定
- 格式
filter 至少需要包含spec&&filter 类型
spec 包含用户初始化filter 必备的参数,spec 必须实现的方法
Name() string
CreateFilter([]interface{}) (filters.Filter,error)
filter 的实现必须满足Filter 接口的
Request(filters.FilterContext)
Response(filters.FilterContext)
对于需要进行资源清理的,使用Close 方法
参考代码模版
type myFilter struct{}
func NewMyFilter() filters.Spec {
return &myFilter{}
}
func (spec *myFilter) Name() string { return "myFilter" }
func (spec *myFilter) CreateFilter(config []interface{}) (filters.Filter, error) {
return NewMyFilter(), nil
}
func (f *myFilter) Request(ctx filters.FilterContext) {
// change data in ctx.Request() for example
}
func (f *myFilter) Response(ctx filters.FilterContext) {
// change data in ctx.Response() for example
}
简单demo
实现比较简单,就是在请求header中添加一个token 值
- 代码位置
直接放到代码的filters目录中
- 代码说明
很简单,就是在response 阶段添加token,如果请求没有token,会自动生成一个,有的话,根据参数校验是否是正确的,进行参数回写
实际上是基于cors的简单改写,没什么实际的意义,就是测试的。
package myfilter
import (
"github.com/zalando/skipper/filters"
)
const (
name = "myfilterToken"
defaultToken = "dalongrong"
)
type basicSpec struct {
}
type filter struct {
allowTokens []string
}
func NewDefaultToken() filters.Spec {
return &basicSpec{}
}
func (a filter) Response(ctx filters.FilterContext) {
if len(a.allowTokens) == 0 {
ctx.Response().Header.Add(defaultToken, "default-rongfengliang")
return
}
token := ctx.Request().Header.Get(defaultToken)
if token == "" {
return
}
for _, o := range a.allowTokens {
if o == token {
ctx.Response().Header.Add(defaultToken, o)
return
}
}
}
// Request is a noop
func (a filter) Request(filters.FilterContext) {}
// CreateFilter takes an optional string array.
// If any argument is not a string, it will return an error
func (spec basicSpec) CreateFilter(args []interface{}) (filters.Filter, error) {
f := &filter{}
for _, a := range args {
if s, ok := a.(string); ok {
f.allowTokens = append(f.allowTokens, s)
} else {
return nil, filters.ErrInvalidFilterParameters
}
}
return f, nil
}
func (spec basicSpec) Name() string { return name }
- 注册filter
buildin代码中添加注册
import (
+ "github.com/zalando/skipper/filters/myfilter"
)
func MakeRegistry() filters.Registry {
+ myfilter.NewDefaultToken(),
构建&&使用
注意有依赖包的问题,注意合理上网
- 构建
make build
- 使用
./bin/skipper -address :9999 -inline-routes 'r: * -> setQuery("lang", "pt")->myfilterToken() -> "http://10.15.0.80"'
- 测试效果
说明
因为新版本使用了golang 的mod 所以会有版本的要求,使用docker 进行构建可能会更方便,其中官方文档有
比较详细的如果开发一个filter,包含测试,文档
参考资料
http://opensource.zalando.com/skipper/reference/development/#how-to-develop-a-filter
https://github.com/rongfengliang/skipper-docker-build