在上一节文章 go使用net/http 创建web服务器-高阶篇
我们学会了创建 服务器。
在一般的C/S架构中,在多个客户端与服务器进行通信时,我们经常使用中间件,来出来一些,在业务逻辑之前的,客户端发送给服务器的数据验证。

一、什么是http中间件

在互联网的http通信中,如果多个客户端访问服务器,我们就会构建一个 client/server 客户端/服务器 架构来实现。
服务器用来接受客户端的请求,然后返回特定的资源或者数据给客户端。

中间件是客户端请求到达处理方法之前对其进行预处理的一些逻辑。
常用的应用场景有:

  1. 客户端身份校验
  2. 用户鉴权
  3. 客户端对服务器提供的特定服务是否有访问权限
  4. 验证用户 session,并保持通信存活
  5. 客户端请求参数解密
  6. 客户端参数格式化
  7. 日志记录器,用于记录每个 REST API 访问请求
  8. 跨域配置
  9. 返回数据格式化
  10. Header设置

二、中间件原理

在 Go 语言中,中间件 Handler 是封装另一个 http.Handler 以对请求进行预处理或后续处理的 http.Handler。它介于 Go Web 服务器与实际的处理程序之间,因此被称为“中间件”。
image.png

原理分析:
我们先看一个最简单的一个http服务器

package main

import (
    "fmt"
    "net/http"
)

func index(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintln(w, "Hello World")
}

func main() {
    http.HandleFunc("/index", index)
    http.ListenAndServe(":8090", nil)
}

上面的示例代码就实现了一个 http服务器。
在路由的处理方面,主要是 通过http.HandleFunc函数,我们可以看一下官方的源代码

// HandleFunc registers the handler function for the given pattern
// HandleFunc 注册handler处理函数到DefaultServeMux,用来绑定给定的url
// in the DefaultServeMux.
// The documentation for ServeMux explains how patterns are matched.
// ServeMux文档有详细的url解析匹配介绍
func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
    DefaultServeMux.HandleFunc(pattern, handler)
}

// HandleFunc registers the handler function for the given pattern.
func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
    if handler == nil {
        panic("http: nil handler")
    }
    mux.Handle(pattern, HandlerFunc(handler))
}

// The HandlerFunc type is an adapter to allow the use of
// ordinary functions as HTTP handlers. If f is a function
// with the appropriate signature, HandlerFunc(f) is a
// Handler that calls f.
type HandlerFunc func(ResponseWriter, *Request)

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

我们可以看到最后的处理是通过 HandlerFunc 反射。
这个正是我们传过去的index(w http.ResponseWriter, r *http.Request)

三、代码实现 middleware中间件

我们实现了一个 简单的 中间件日志 代码如下:

package main

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

// middlewareLog中间件日志,用来记录每个请求,写进日子
func middlewareLog(handler http.HandlerFunc) http.HandlerFunc {
    return func(writer http.ResponseWriter, request *http.Request) {
        // 日志中间件
        log.Println(request.Header)
        handler(writer, request)
    }
}

func index(w http.ResponseWriter, r *http.Request) {
    _, _ = fmt.Fprintln(w, "Hello World")
}

func main() {
    http.HandleFunc("/index", middlewareLog(index))
    _ = http.ListenAndServe(":8090", nil)
}

海生
104 声望32 粉丝

与黑夜里,追求那一抹萤火。