Go语言经典库使用分析(三)| Gorilla Handlers 详细介绍
qiyuwang 2024-11-22 19:42 8 浏览 0 评论
Go语言经典库使用分析,未完待续,第一时间看后续系列。觉得有帮助的话,顺手分享、转发、收藏吧,感谢支持。
在我们编写web服务端程序的时候,我们可能会对一些甚至全部的Http Request统一处理,比如我们记录每个访问的Request,对提交的Form表单进行映射等,要达到这些目的,比较优雅的做法是Http 中间件。
中间件,顾名思义,强调的是中间,他是一种业务无关的,在正常的的业务handler处理前后的,独立的逻辑处理片段。一般调用顺序如下:
ServeMux路由分发->调用中间件1->调用中间件2……->调用真正的业务处理逻辑
因为中间件非常独立,可以我们不用的时候,去掉即可;需要用的时候,加上,并不会修改真正的业务处理逻辑代码,可谓非常简洁方便。
这里我选用Gorilla Handlers这个中间件库演示如何使用和定义一个中间件,这一篇主要讲Gorilla Handlers的使用,下一篇会讲Gorilla Handlers里每个中间件的实现原理。
安装
Gorilla Handlers是一个很简单,但是很有代表性的中间件库,所以拿他来分析,更容易理解handler中间件。在使用之前,我们要先安装,该中间件库已经托管在Github上,所以我们直接使用go get即可。
$ go get github.com/gorilla/handlers
安装之后,我们在代码里使用如下代码即可导入使用。
import "github.com/gorilla/handlers"
Gorilla Handlers以函数的方式提供了好几种中间件,比如CombinedLoggingHandler、CompressHandler、ContentTypeHandler、LoggingHandler等,下面我们就一一介绍他们。
LoggingHandler
我们应该都用过Nginx,Nginx的访问日志,类似于如下这样:
[05/Aug/2017:21:06:24 +0800] "GET /favicon.ico HTTP/1.1" 200 11
从中我们可以看到访问的什么资源,使用的什么协议,返回的HTTP状态以及请求的大小是多少,这种一种日志风格,和Apache Common Log Format很像,LoggingHandler中间件就是帮我们做这个事情的。
它可以记录request的日志,输出到一个io.Writer里。
func main() {
http.Handle("/",useLoggingHandler(handler()))
http.ListenAndServe(":1234",nil)
}
func handler() http.Handler{
return http.HandlerFunc(myHandler)
}
func myHandler(rw http.ResponseWriter, r *http.Request) {
rw.WriteHeader(http.StatusOK)
io.WriteString(rw,"Hello World")
}
func useLoggingHandler(next http.Handler) http.Handler {
return handlers.LoggingHandler(os.Stdout,next)
}
我这里的io.Writer是一个os.Stdout,也就是标准的控制台输出,所以我们访问http://localhost:1234/的时候,可以看到控制台打印的Request日志信息输出。
::1 - - [05/Aug/2017:21:06:24 +0800] "GET / HTTP/1.1" 200 11
::1 - - [05/Aug/2017:21:06:24 +0800] "GET /favicon.ico HTTP/1.1" 200 11
从handlers.LoggingHandler函数的参数我们可以看出,它接受一个Handler,然后返回一个Handler,其实就是对现有的Handler的一次包装,这就是中间件。
这里的输出参数类型是io.Writer,所以我们可以输出文件等实现了该接口的任何类型。
Go语言经典库使用分析,未完待续,第一时间看后续系列。觉得有帮助的话,顺手分享、转发、收藏吧,感谢支持。
CombinedLoggingHandler
还有一种日志格式,这种日志格式输出的日志信息更详细,更全面,比如包含UA等信息,这种格式被称为Apache Combined Log Format。
CombinedLoggingHandler就是为我们提供输出一种这种格式的中间件,使用方式和LoggingHandler一样。
func useCombinedLoggingHandler(next http.Handler) http.Handler {
return handlers.CombinedLoggingHandler(os.Stdout,next)
}
看下这个中间件输出的日志信息
::1 - - [05/Aug/2017:21:39:45 +0800] "GET /favicon.ico HTTP/1.1" 200 11 "http://localhost:1234/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.78 Safari/537.36"
UA+HOST,日志信息更全面了。
CompressHandler
这是一个压缩response的中间件,支持gzip和deflate压缩。如果客户端的请求头里包含Accept-Encoding,并且值为gzip或者deflate,该中间件就会压缩返回的response,这样就可以减少response的大小,减少响应的时间,使用访问也很简单,这里简单举个例子。
func main() {
http.Handle("/gzip",useCompressHandler(handler()))
http.ListenAndServe(":1234",nil)
}
func handler() http.Handler{
return http.HandlerFunc(myHandler)
}
func myHandler(rw http.ResponseWriter, r *http.Request) {
rw.WriteHeader(http.StatusOK)
rw.Header().Set("Content-Type", "text/plain")
io.WriteString(rw,"Hello World")
}
func useCompressHandler(next http.Handler) http.Handler {
return handlers.CompressHandler(next)
}
这里尤其注意的是我们返回的response的内容类型要特别指定一下,不然就会被自动解析为gzip,就变成下载一个gz文件了。我这里强制指定文本类型,这样就可以看到返回的内容Hello World。
该中间件还有一个函数CompressHandlerLevel可以指定压缩的级别,级别是gzip.BestSpeed和gzip.BestCompression之间的值,如果大家不想用默认压缩级别,可以使用这个函数指定。
还记得Nginx可以开启Gzip加速吧,差不多也是这么个实现。
ContentTypeHandler
这也是一个很有意思的中间件,他的作用是只处理支持的内容类型,如果不支持,则返回415状态码。该中间件只对PUT,POST,PATCH方法有效,其他方法则不做处理,也就相当于没有使用这个中间件。
func useContentTypeHandler(next http.Handler) http.Handler {
return handlers.ContentTypeHandler(next,"application/x-www-form-urlencoded")
}
最后一个参数是可变参数,我们可以指定多个ContextType类型,这些类型是被我们支持的,其他类型则不支持。如果我们使用PUT、POST、PATCH方法提交的请求的内容类型不在我们支持的内容类型范围内,则返回415错误。
CanonicalHost
这是一个重定向的中间件,他可以把一个Request请求重新定向到另外一个域名上,并且会带上原请求的Path和Query。
func main() {
http.Handle("/flysnow",useCanonicalHost(handler()))
http.ListenAndServe(":1234",nil)
}
func handler() http.Handler{
return http.HandlerFunc(myHandler)
}
func myHandler(rw http.ResponseWriter, r *http.Request) {
rw.WriteHeader(http.StatusOK)
rw.Header().Set("Content-Type", "text/plain")
io.WriteString(rw,"Hello World")
}
func useCanonicalHost(next http.Handler) http.Handler {
return handlers.CanonicalHost("http://www.flysnow.org/",http.StatusFound)(next)
}
上面的示例,当我们在浏览器内输入http://localhost:1234/flysnow的访问的时候,会自动跳转到http://www.flysnow.org/flysnow。
小结
其他的一些不常用的中间的使用方式也类似,大家可以自己看下文档测试下。Go Http的中间件,有点类似于HTTP的拦截器,通过一层层的包装,我们可以组成一个中间件的处理链,便于我们处理我们需要处理的通用性问题,如果哪个中间件不想要,去掉即可,不用对业务代码做任何修改。
例子中的演示,都是一个url对应一个中间件的处理,这个主要是为了演示方面。如果我们相对所有的请求都使用某个中间件怎么做呢?肯定不能使用我们例子中的方式了,因为这样会写很多个。
对于以上这种方式,我们可以借助HTTP Mux路由,因为一个路由也是一个Handler,只用对这个路由应用中间件,就可以拦截处理所有的请求了。
下一篇开始分享这些常用中间件的实现原理和源代码的分析。
Go语言经典库使用分析,未完待续,第一时间看后续系列。觉得有帮助的话,顺手分享、转发、收藏吧,感谢支持。
相关推荐
- # 安装打开 ubuntu-22.04.3-LTS 报错 解决方案
-
#安装打开ubuntu-22.04.3-LTS报错解决方案WslRegisterDistributionfailedwitherror:0x800701bcError:0x80070...
- 利用阿里云镜像在ubuntu上安装Docker
-
简介:...
- 如何将Ubuntu Kylin(优麒麟)19.10系统升级到20.04版本
-
UbuntuKylin系统使用一段时间后,有新的版本发布,如何将现有的UbuntuKylin系统升级到最新版本?可以通过下面的方法进行升级。1.先查看相关的UbuntuKylin系统版本情况。使...
- Ubuntu 16.10内部代号确认为Yakkety Yak
-
在正式宣布Ubuntu16.04LTS(XenialXerus)的当天,Canonical创始人MarkShuttleworth还非常开心的在个人微博上宣布Ubuntu下个版本16.10的内...
- 如何在win11的wsl上装ubuntu(怎么在windows上安装ubuntu)
-
在Windows11的WSL(WindowsSubsystemforLinux)上安装Ubuntu非常简单。以下是详细的步骤:---...
- Win11学院:如何在Windows 11上使用WSL安装Ubuntu
-
IT之家2月18日消息,科技媒体pureinfotech昨日(2月17日)发布博文,介绍了3中简便的方法,让你轻松在Windows11系统中,使用WindowsSubs...
- 如何查看Linux的IP地址(如何查看Linux的ip地址)
-
本头条号每天坚持更新原创干货技术文章,欢迎关注本头条号"Linux学习教程",公众号名称“Linux入门学习教程"。...
- 怎么看电脑系统?(怎么看电脑系统配置)
-
要查看电脑的操作系统信息,可以按照以下步骤操作,根据不同的操作系统选择对应的方法:一、Windows系统通过系统属性查看右键点击桌面上的“此电脑”(或“我的电脑”)图标,选择“属性”。在打开的...
- 如何查询 Linux 内核版本?这些命令一定要会!
-
Linux内核是操作系统的核心,负责管理硬件资源、调度进程、处理系统调用等关键任务。不同的内核版本可能支持不同的硬件特性、提供新的功能,或者修复了已知的安全漏洞。以下是查询内核版本的几个常见场景:...
- 深度剖析:Linux下查看系统版本与CPU架构
-
在Linux系统管理、维护以及软件部署的过程中,精准掌握系统版本和CPU架构是极为关键的基础操作。这些信息不仅有助于我们深入了解系统特性、判断软件兼容性,还能为后续的软件安装、性能优化提供重要依据。接...
- 504 错误代码解析与应对策略(504错误咋解决)
-
在互联网的使用过程中,用户偶尔会遭遇各种错误提示,其中504错误代码是较为常见的一种。504错误并非意味着网站被屏蔽,它实际上是指服务器在规定时间内未能从上游服务器获取响应,专业术语称为“Ga...
- 猎聘APP和官网崩了?回应:正对部分职位整改,临时域名可登录
-
10月12日,有网友反映猎聘网无法打开,猎聘APP无法登录。截至10月14日,仍有网友不断向猎聘官方微博下反映该情况,而猎聘官方微博未发布相关情况说明,只是在微博内对反映该情况的用户进行回复,“抱歉,...
- 域名解析的原理是什么?域名解析的流程是怎样的?
-
域名解析是网站正常运行的关键因素,因此网站管理者了解域名解析的原理和流程对于做好域名管理、解决常见解析问题,保障网站的正常运转十分必要。那么域名解析的原理是什么?域名解析的流程是怎样的?接下来,中科三...
- Linux无法解析域名的解决办法(linux 不能解析域名)
-
如果由于误操作,删除了系统原有的dhcp相关设置就无法正常解析域名。 此时,需要手动修改配置文件: /etc/resolv.conf 将域名解析服务器手动添加到配置文件中 该文件是DNS域名解...
- 域名劫持是什么?(域名劫持是什么)
-
域名劫持是互联网攻击的一种方式,通过攻击域名解析服务器(DNS),或伪造域名解析服务器(DNS)的方法,把目标网站域名解析到错误的地址从而实现用户无法访问目标网站的目的。说的直白些,域名劫持,就是把互...
你 发表评论:
欢迎- 一周热门
- 最近发表
-
- # 安装打开 ubuntu-22.04.3-LTS 报错 解决方案
- 利用阿里云镜像在ubuntu上安装Docker
- 如何将Ubuntu Kylin(优麒麟)19.10系统升级到20.04版本
- Ubuntu 16.10内部代号确认为Yakkety Yak
- 如何在win11的wsl上装ubuntu(怎么在windows上安装ubuntu)
- Win11学院:如何在Windows 11上使用WSL安装Ubuntu
- 如何查看Linux的IP地址(如何查看Linux的ip地址)
- 怎么看电脑系统?(怎么看电脑系统配置)
- 如何查询 Linux 内核版本?这些命令一定要会!
- 深度剖析:Linux下查看系统版本与CPU架构
- 标签列表
-
- navicat无法连接mysql服务器 (65)
- 下横线怎么打 (71)
- flash插件怎么安装 (60)
- lol体验服怎么进 (66)
- ae插件怎么安装 (62)
- yum卸载 (75)
- .key文件 (63)
- cad一打开就致命错误是怎么回事 (61)
- rpm文件怎么安装 (66)
- linux取消挂载 (81)
- ie代理配置错误 (61)
- ajax error (67)
- centos7 重启网络 (67)
- centos6下载 (58)
- mysql 外网访问权限 (69)
- centos查看内核版本 (61)
- ps错误16 (66)
- nodejs读取json文件 (64)
- centos7 1810 (59)
- 加载com加载项时运行错误 (67)
- php打乱数组顺序 (68)
- cad安装失败怎么解决 (58)
- 因文件头错误而不能打开怎么解决 (68)
- js判断字符串为空 (62)
- centos查看端口 (64)