GRPC开发(9)-grpc服务开发-grpc-gateway的中间件

其实grpc的中间件和编写http的中间件一样

http服务

处理器:Handler

定义

type Handler interface {
	ServeHTTP(ResponseWriter, *Request)
}

http服务,最重要的就是处理器:Handler ,一个接口
我们需要定义一个处理器,实现ServeHTTP方法用来响应HTTP请求
下面是对处理器:Handler 的介绍

ServeHTTP应该将响应头和数据写入ResponseWriter,然后返回。
Returning signals代表请求结束,在完成ServeHTTP调用的时候或之后,不允许使用ResponseWriter ,也不允许从 Request.Body读取信息

根据HTTP客户端软件、HTTP协议版本以及客户端和Go服务器之间的任何中介,在ResponseWriter写入之后可能无法从Request.Body读取数据。
谨慎的处理程序应该首先读取Request.Body,然后回复。

除了读取Body之外,处理程序不应该修改提供的请求。

如果ServeHTTP panics,服务器(ServeHTTP的调用者)假设恐慌的影响与active request隔离。
它恢复恐慌,将堆栈跟踪记录到服务器错误日志,并根据HTTP协议关闭网络连接或发送HTTP/2 RST_STREAM。
然后中止处理程序,以便客户端看到中断的响应,服务器不记录错误,而是使用ErrAbortHandler值去panic。

对指定url添加中间件

我们先定义一个类型:myHandler1,并实现ServeHTTP 方法来实现Handler 接口
type myHandler1 struct{}

func (my *myHandler1) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Hello  myHandler1  ")
}

然后直接访问127.0.0.1:8888/h1 就可以返回Hello myHandler1
这是最简单的服务。
这里我们想给该服务价格中间件用来做全局log记录或者验证
因为myh实现了Handler接口,name就可以直接传递进来

func middleware1(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		// http.Error(w, http.StatusText(403), 403)
		tStart := time.Now()
		next.ServeHTTP(w, r)
		tEnd := time.Since(tStart)
		fmt.Println("middleware1:", tEnd)
	})
}

mux.Handle("/h1", &myh)
改成
mux.Handle("/h2", middleware1(&myh))

简单实现一个服务

package main

import (
        "fmt"
        "net/http"
        "time"
)
type myHandler1 struct{}

func (my *myHandler1) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Hello  myHandler1  ")
}

func middleware1(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		// http.Error(w, http.StatusText(403), 403)
		tStart := time.Now()
		next.ServeHTTP(w, r)
		tEnd := time.Since(tStart)
		fmt.Println("middleware1:", tEnd)
	})
}

func main() {
        mux := http.NewServeMux()
        myh := &myHandler1{}
        mux.Handle("/h1", middleware1(myh))
        if err := http.ListenAndServe(":8888", mux); err != nil {
                panic(err)
        }
}

对路由器添加中间件

上面是对单个url的验证,因为mux 也实现了ServeHTTP方法,所以middleware1可以直接对mux使用

func main() {
        mux := http.NewServeMux()
        myh := &myHandler1{}
        mux.Handle("/h1", myh)
        if err := http.ListenAndServe(":8888", middleware1(mux)); err != nil {
                panic(err)
        }
}

换句话说,只要实现了ServeHTTP方法,就可以对该对象使用上面的中间件。。。

对于grpc-gateway

mux := runtime.NewServeMux()
其中mux 就实现了ServeHTTP ,实现了Handler方法,所以按照该方式编写中间件即可

Handler的适配器:HandlerFunc

定义

type HandlerFunc func(ResponseWriter, *Request)

// ServeHTTP calls f(w, r).
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
	f(w, r)
}

介绍

HandlerFunc类型是一个适配器,允许使用普通函数作为HTTP处理程序。如果f是具有适当签名的函数,HandlerFunc(f)是调用f的处理程序。

这里提供了个适配器,也就是说,你按照(w http.ResponseWriter, r *http.Request)格式实现一个函数,然后转换成HandlerFunc 类型,因为HandlerFunc 实现了ServeHTTP 方法,方法内部调用了自身,所以免去了去实现Handler 接口的步骤。
这样可以快速实现一个服务。
对此也提供了实现中间件的方式,对指定url加中间件

package main

import (
        "fmt"
        "net/http"
        "time"
)

func hello1(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "Hello  111 ")
}
func middleware2(h http.HandlerFunc) http.HandlerFunc {
        return func(w http.ResponseWriter, r *http.Request) {
                tStart := time.Now()
                h(w, r) //执行调用
                tEnd := time.Since(tStart)
                fmt.Println("middleware1:", tEnd)
        }
}
func main() {
        mux := http.NewServeMux()
        mux.HandleFunc("/h2", middleware2( http.HandlerFunc(hello1)))
         if err := http.ListenAndServe(":8888", mux); err != nil {
                panic(err)
        }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

InterestingFigure

迈克 Let's Go

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值