micro plugin 开发
plugin 会在每次调用服务的都会触发,根据注册的顺序进行调用,作用上可以理解为拦截器。可以利用plugin实现拦截功能,比如token验证等,可结合jwt来实现。plugin实现有两种方式。
1. 实现plugin 的所有的接口,并且在启动micro 的时候注册服务
1.1 实现Plugin的接口
type Plugin interface {
// Global Flags
Flags() []cli.Flag
// Sub-commands
Commands() []cli.Command
// Handle is the middleware handler for HTTP requests. We pass in
// the existing handler so it can be wrapped to create a call chain.
Handler() Handler
// Init called when command line args are parsed.
// The initialised cli.Context is passed in.
Init(*cli.Context) error
// Name of the plugin
String() string
}
1.2 例如实现一个打印请求信息的插件
package httpLog
import (
"github.com/micro/cli"
"github.com/micro/micro/plugin"
"log"
"net/http"
)
var DeFaultPreFix="http-log-prefix"
type HttpLog struct {
Name string
Prefix string
}
//定义一些参数,可以通过启动micro 的时候传参
func (l *HttpLog) Flags() []cli.Flag {
return []cli.Flag{ cli.StringFlag{
Name:"httplog",
Usage:"需要从命令行传过来的参数",
EnvVar:"HTTPLOG",
}}
}
func (l *HttpLog) Commands() []cli.Command {
return nil
}
//处理程序 会在每次请求的时候调用
func (l *HttpLog) Handler() plugin.Handler {
return func(handler http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
log.Printf("%s: %s",l.Prefix, r.URL.Path)
handler.ServeHTTP(w, r)
})
}
}
//初始化数据,程序启动的时候会调用这个方法,可以在这里初始化一些参数
func (l *HttpLog) Init(ctx *cli.Context) error {
prefix:=ctx.String("httplog")
if prefix==""{
l.Prefix=DeFaultPreFix
}else {
l.Prefix=prefix
}
return nil
}
func (l *HttpLog) String() string {
return l.Name
}
//调用这个方法 new 插件,也可以在启动的时候这样子写
func NewPlugin() plugin.Plugin {
return &HttpLog{
Name:"httpLog",
}
}
1.3 使用插件
package main
import (
"github.com/micro/micro/cmd"
"github.com/micro/micro/plugin"
"microservices/lib/httpLog"
)
func init() {
plugin.Register(httpLog.NewPlugin())
}
func main() {
cmd.Init()
}
1.4 启动服务进行测试,这里启动api服务然后进行测试,
go run main.go --httplog=MyHttpLogPrefix api
2020/05/27 16:59:58 log.go:18: [api] Registering API Default Handler at /
2020/05/27 16:59:58 log.go:18: [api] HTTP API Listening on [::]:8080
2020/05/27 16:59:58 log.go:18: [api] Transport [http] Listening on [::]:31651
2020/05/27 16:59:58 log.go:18: [api] Broker [http] Connected to [::]:31652
2020/05/27 16:59:58 log.go:18: [api] Registry [etcd] Registering node: go.micro.api-6554b04d-eb16-4558-94e5-ff15a3e1a61c
访问默认的api 服务 http://localhost:8080/
2020-05-27 17:01:46.541000 I | MyHttpLogPrefix: /
::1 - - [27/May/2020:17:01:46 +0800] "GET / HTTP/1.1" 200 21 "" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36"
2020-05-27 17:01:46.575000 I | MyHttpLogPrefix: /favicon.ico
::1 - - [27/May/2020:17:01:46 +0800] "GET /favicon.ico HTTP/1.1" 200 0 "http://localhost:8080/" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36"
可以看到我定义的插件起作用了,打印了MyHttpLogPrefix
2. 直接 new plugin
plugin.Register(plugin.NewPlugin(
plugin.WithName("httpLog"),
plugin.WithHandler(func(handler http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter,r *http.Request) {
log.Printf("%s: %s","myprofix", r.URL.Path)
handler.ServeHTTP(w, r)
})
}),
plugin.WithFlag(
cli.StringFlag{
Name:"httpLog",
Usage:"需要从命令行传过来的参数",
EnvVar:"HTTP_LOG",
}),
plugin.WithInit(func(context *cli.Context) error {
// TODO
return nil
}),
))
完整程序
package main
import (
"github.com/micro/cli"
"github.com/micro/micro/cmd"
"github.com/micro/micro/plugin"
"log"
"net/http"
)
func init() {
//plugin.Register(httpLog.NewPlugin())
plugin.Register(plugin.NewPlugin(
plugin.WithName("httpLog"),
plugin.WithHandler(func(handler http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter,r *http.Request) {
log.Printf("%s: %s","myprofix", r.URL.Path)
handler.ServeHTTP(w, r)
})
}),
plugin.WithFlag(
cli.StringFlag{
Name:"httpLog",
Usage:"需要从命令行传过来的参数",
EnvVar:"HTTP_LOG",
}),
plugin.WithInit(func(context *cli.Context) error {
// TODO
return nil
}),
))
}
func main() {
cmd.Init()
}
运行结果
go run main.go --httpLog=MyHttpLogPrefix api
2020/05/27 17:17:12 log.go:18: [api] Registering API Default Handler at /
2020/05/27 17:17:12 log.go:18: [api] HTTP API Listening on [::]:8080
2020/05/27 17:17:12 log.go:18: [api] Transport [http] Listening on [::]:32972
2020/05/27 17:17:12 log.go:18: [api] Broker [http] Connected to [::]:32973
2020/05/27 17:17:12 log.go:18: [api] Registry [etcd] Registering node: go.micro.api-cdc7bb48-03c9-4aff-8cb4-02a85f5aaddd
这里访问了 http://localhost:8080/
2020-05-27 17:17:16.537000 I | myprofix: /
::1 - - [27/May/2020:17:17:16 +0800] "GET / HTTP/1.1" 200 21 "" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36"
2020-05-27 17:17:16.554000 I | myprofix: /favicon.ico
::1 - - [27/May/2020:17:17:16 +0800] "GET /favicon.ico HTTP/1.1" 200 0 "http://localhost:8080/" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36"
网友评论