micro自定义plugin

2020-05-27  本文已影响0人  路人甲Boger

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"

上一篇下一篇

猜你喜欢

热点阅读