go使用net/http 创建middleware中间件
在上一节文章 go使用net/http 创建web服务器-高阶篇
我们学会了创建 服务器。
在一般的C/S架构中,在多个客户端与服务器进行通信时,我们经常使用中间件,来出来一些,在业务逻辑之前的,客户端发送给服务器的数据验证。
一、什么是http中间件
在互联网的http通信中,如果多个客户端访问服务器,我们就会构建一个 client/server 客户端/服务器 架构来实现。
服务器用来接受客户端的请求,然后返回特定的资源或者数据给客户端。
中间件是客户端请求到达处理方法之前对其进行预处理的一些逻辑。
常用的应用场景有:
- 客户端身份校验
- 用户鉴权
- 客户端对服务器提供的特定服务是否有访问权限
- 验证用户 session,并保持通信存活
- 客户端请求参数解密
- 客户端参数格式化
- 日志记录器,用于记录每个 REST API 访问请求
- 跨域配置
- 返回数据格式化
- Header设置
二、中间件原理
在 Go 语言中,中间件 Handler 是封装另一个 http.Handler 以对请求进行预处理或后续处理的 http.Handler。它介于 Go Web 服务器与实际的处理程序之间,因此被称为“中间件”。
原理分析:
我们先看一个最简单的一个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)
}
推荐阅读
go语法入门-any类型的使用场景与注意
在没有any类型之前,go语言中,我们经常使用interface{},来表示一个类型是未知的,或者有好几种其他基础类型的情况。从 Go1.18开始,go官方定义了一个预声明标识符(Predeclared identifiers):any。
海生阅读 825
数据结构与算法:二分查找
一、常见数据结构简单数据结构(必须理解和掌握)有序数据结构:栈、队列、链表。有序数据结构省空间(储存空间小)无序数据结构:集合、字典、散列表,无序数据结构省时间(读取时间快)复杂数据结构树、 堆图二...
白鲸鱼赞 9阅读 6.5k
「刷起来」Go必看的进阶面试题详解
逃逸分析是Go语言中的一项重要优化技术,可以帮助程序减少内存分配和垃圾回收的开销,从而提高程序的性能。下面是一道涉及逃逸分析的面试题及其详解。
王中阳Go赞 4阅读 1.9k评论 1
初学后端,如何做好表结构设计?
这篇文章介绍了设计数据库表结构应该考虑的4个方面,还有优雅设计的6个原则,举了一个例子分享了我的设计思路,为了提高性能我们也要从多方面考虑缓存问题。
王中阳Go赞 4阅读 1.7k评论 2
滚蛋吧,正则表达式!
你是不是也有这样的操作,比如你需要使用「电子邮箱正则表达式」,首先想到的就是直接百度上搜索一个,然后采用 CV 大法神奇地接入到你的代码中?
良许赞 4阅读 2.2k
又一款眼前一亮的Linux终端工具!
今天给大家介绍一款最近发现的功能十分强大,颜值非常高的一款终端工具。这个神器我是在其他公众号文章上看到的,但他们都没把它的强大之处介绍明白,所以我自己体验一波后,再向大家分享自己的体验。
良许赞 5阅读 1.8k
一分钟搞明白!快速掌握 Go WebAssembly
最近因为各种奇怪的原因,更多的接触到了 WebAssembly。虽然之前很多博客也翻过写过各种文章,但总感觉欠些味道。于是今天梳理了一版,和大家一起展开学习。
煎鱼赞 4阅读 2.1k
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。