Go Web 编程入门:中间件

简介: 中间件通常位于前端的客户端站点请求和请求的后端资源之间。中间件非常有用,尤其是当我们希望在进行 API 调用之前进行一些验证,例如请求方法、标头和 JWT 等。

前言

中间件通常位于前端的客户端站点请求和请求的后端资源之间。中间件非常有用,尤其是当我们希望在进行 API 调用之前进行一些验证,例如请求方法、标头和 JWT 等。

网络异常,图片无法展示
|


日志中间件


http.Handler 包装器是一个具有一个输入参数和一个输出参数的函数,两者都是 http.Handler 类型。

func Middleware(next http.Handler) http.Handler {
  return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        //code before make the backend api call
  next.ServeHTTP(w, r) //serve and handle the http request
        //code after make the backend api call
  })
}

现在,而不是直接服务和监听我们的 http 处理程序,例如:

http.ListenAndServe(":3000", handler)

我们现在可以将它包装在我们的中间件中并变成:

http.ListenAndServe(":3000", Middleware(handler))


接下来将介绍如何创建一个 Go 语言的日志中间件。


中间件只需将 http.HandlerFunc 作为其参数之一,将其包装并返回一个新的 http.HandlerFunc 供服务器调用。


新建一个 main.go 文件:

package main
import (
    "fmt"
    "log"
    "net/http"
)
func logging(f http.HandlerFunc) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
        log.Println(r.URL.Path)
        f(w, r)
    }
}
func foo(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintln(w, "foo")
}
func bar(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintln(w, "bar")
}
func main() {
    http.HandleFunc("/foo", logging(foo))
    http.HandleFunc("/bar", logging(bar))
    http.ListenAndServe(":8080", nil)
}


创建 mod 文件:

$ go mod init main.go 
go: creating new go.mod: module main.go
go: to add module requirements and sums:
        go mod tidy


打开另一个终端:

$ curl -s http://localhost:8080/foo
foo
$ curl -s http://localhost:8080/bar
bar
$ curl -s http://localhost:8080/foo\?bar
foo

运行上述代码:

$ go run main.go         
2022/05/25 23:12:00 /foo
2022/05/25 23:12:09 /bar
2022/05/25 23:12:16 /foo


中间件框架

中间件本身只是将 a 作为其参数之一,将其包装并返回一个新的供服务器调用。在这里,我们定义了一种新类型,它最终使将多个中间件链接在一起变得更加容易。这个想法的灵感来自于 Mat Ryers 关于构建 API 的演讲。

这个片段详细解释了如何创建一个新的中间件。在下面的完整示例中,代码结构示例如下:

func createNewMiddleware() Middleware {
    // Create a new Middleware
    middleware := func(next http.HandlerFunc) http.HandlerFunc {
        // Define the http.HandlerFunc which is called by the server eventually
        handler := func(w http.ResponseWriter, r *http.Request) {
            // ... do middleware things
            // Call the next middleware/handler in chain
            next(w, r)
        }
        // Return newly created handler
        return handler
    }
    // Return newly created middleware
    return middleware
}

完整测试

package main
import (
    "fmt"
    "log"
    "net/http"
    "time"
)
type Middleware func(http.HandlerFunc) http.HandlerFunc
// Logging logs all requests with its path and the time it took to process
func Logging() Middleware {
    // Create a new Middleware
    return func(f http.HandlerFunc) http.HandlerFunc {
        // Define the http.HandlerFunc
        return func(w http.ResponseWriter, r *http.Request) {
            // Do middleware things
            start := time.Now()
            defer func() { log.Println(r.URL.Path, time.Since(start)) }()
            // Call the next middleware/handler in chain
            f(w, r)
        }
    }
}
// Method ensures that url can only be requested with a specific method, else returns a 400 Bad Request
func Method(m string) Middleware {
    // Create a new Middleware
    return func(f http.HandlerFunc) http.HandlerFunc {
        // Define the http.HandlerFunc
        return func(w http.ResponseWriter, r *http.Request) {
            // Do middleware things
            if r.Method != m {
                http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
                return
            }
            // Call the next middleware/handler in chain
            f(w, r)
        }
    }
}
// Chain applies middlewares to a http.HandlerFunc
func Chain(f http.HandlerFunc, middlewares ...Middleware) http.HandlerFunc {
    for _, m := range middlewares {
        f = m(f)
    }
    return f
}
func Hello(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintln(w, "hello world")
}
func main() {
    http.HandleFunc("/", Chain(Hello, Method("GET"), Logging()))
    http.ListenAndServe(":8080", nil)
}

运行代码:

$ go run main.go 

打开另外的终端:

$ curl -s http://localhost:8080/
hello world
$ curl -s -XPOST http://localhost:8080/
Bad Request
$ go run main.go         
2022/05/25 23:20:01 / 21.595µs
2022/05/25 23:20:13 / 5.129µs
相关文章
|
5月前
|
算法 Java Go
【GoGin】(1)上手Go Gin 基于Go语言开发的Web框架,本文介绍了各种路由的配置信息;包含各场景下请求参数的基本传入接收
gin 框架中采用的路优酷是基于httprouter做的是一个高性能的 HTTP 请求路由器,适用于 Go 语言。它的设计目标是提供高效的路由匹配和低内存占用,特别适合需要高性能和简单路由的应用场景。
521 4
|
5月前
|
开发框架 前端开发 Go
【GoGin】(0)基于Go的WEB开发框架,GO Gin是什么?怎么启动?本文给你答案
Gin:Go语言编写的Web框架,以更好的性能实现类似Martini框架的APInet/http、Beego:开源的高性能Go语言Web框架、Iris:最快的Go语言Web框架,完备的MVC支持。
550 1
|
9月前
|
开发框架 JSON 中间件
Go语言Web开发框架实践:路由、中间件、参数校验
Gin框架以其极简风格、强大路由管理、灵活中间件机制及参数绑定校验系统著称。本文详解其核心功能:1) 路由管理,支持分组与路径参数;2) 中间件机制,实现全局与局部控制;3) 参数绑定,涵盖多种来源;4) 结构体绑定与字段校验,确保数据合法性;5) 自定义校验器扩展功能;6) 统一错误处理提升用户体验。Gin以清晰模块化、流程可控及自动化校验等优势,成为开发者的优选工具。
|
9月前
|
开发框架 JSON 中间件
Go语言Web开发框架实践:使用 Gin 快速构建 Web 服务
Gin 是一个高效、轻量级的 Go 语言 Web 框架,支持中间件机制,非常适合开发 RESTful API。本文从安装到进阶技巧全面解析 Gin 的使用:快速入门示例(Hello Gin)、定义 RESTful 用户服务(增删改查接口实现),以及推荐实践如参数校验、中间件和路由分组等。通过对比标准库 `net/http`,Gin 提供更简洁灵活的开发体验。此外,还推荐了 GORM、Viper、Zap 等配合使用的工具库,助力高效开发。
|
10月前
|
设计模式 缓存 算法
Go如何进行高质量编程与性能调优实践
本文介绍了Go语言高质量编程与性能调优的实践方法。高质量编程包括良好的编码习惯(如清晰注释、命名规范)、代码风格与设计(如MVC模式)、简洁明了的代码原则,以及单元测试与代码重构的重要性。性能调优方面,涵盖算法优化、数据结构选择、I/O优化、内存管理、并行与并发处理优化及代码层面的改进。通过这些方法,可有效提升代码质量和系统性能。
208 13
|
10月前
|
分布式计算 Go C++
初探Go语言RPC编程手法
总的来说,Go语言的RPC编程是一种强大的工具,让分布式计算变得简单如同本地计算。如果你还没有试过,不妨挑战一下这个新的编程领域,你可能会发现新的世界。
254 10
|
中间件 关系型数据库 数据库
docker快速部署OS web中间件 数据库 编程应用
通过Docker,可以轻松地部署操作系统、Web中间件、数据库和编程应用。本文详细介绍了使用Docker部署这些组件的基本步骤和命令,展示了如何通过Docker Compose编排多容器应用。希望本文能帮助开发者更高效地使用Docker进行应用部署和管理。
390 19
|
监控 Linux PHP
【02】客户端服务端C语言-go语言-web端PHP语言整合内容发布-优雅草网络设备监控系统-2月12日优雅草简化Centos stream8安装zabbix7教程-本搭建教程非docker搭建教程-优雅草solution
【02】客户端服务端C语言-go语言-web端PHP语言整合内容发布-优雅草网络设备监控系统-2月12日优雅草简化Centos stream8安装zabbix7教程-本搭建教程非docker搭建教程-优雅草solution
497 20
|
Java 开发者 微服务
Spring Boot 入门:简化 Java Web 开发的强大工具
Spring Boot 是一个开源的 Java 基础框架,用于创建独立、生产级别的基于Spring框架的应用程序。它旨在简化Spring应用的初始搭建以及开发过程。
923 7
Spring Boot 入门:简化 Java Web 开发的强大工具
|
监控 关系型数据库 MySQL
【01】客户端服务端C语言-go语言-web端PHP语言整合内容发布-优雅草网络设备监控系统-硬件设备实时监控系统运营版发布-本产品基于企业级开源项目Zabbix深度二开-分步骤实现预计10篇合集-自营版
【01】客户端服务端C语言-go语言-web端PHP语言整合内容发布-优雅草网络设备监控系统-硬件设备实时监控系统运营版发布-本产品基于企业级开源项目Zabbix深度二开-分步骤实现预计10篇合集-自营版
483 0

热门文章

最新文章