Go语言经典库使用分析(三)| Gorilla Handlers 详细介绍
qiyuwang 2024-11-22 19:42 9 浏览 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语言经典库使用分析,未完待续,第一时间看后续系列。觉得有帮助的话,顺手分享、转发、收藏吧,感谢支持。
相关推荐
- centos7使用yum安装nginx+php7+mysql5.6
-
本文主要介绍安装在centos7下如何安装nginx+php+mysql的环境,centos7的版本自带安装源的版本无法实现PHP5.4以上的版本,数据库默认用的是mariadb,文章介绍的安装是如何...
- Linux基础入门(VMWare中CentOS7配置yum)
-
上一章节,介绍了《Linux基础入门(CentOS7下通过命令行配置网络)》,本章将介绍如何配置yum源,方便后续在学习和使用的过程中,对所需工具的安装;...
- CentOS 7搭建Nextcloud私有云(centos搭建云盘)
-
Nextcloud简介:对于私人网盘,其中最出名的就是seafile、owncloud和nextcloud。seafile是国人开发的,有免费和企业版,免费的功能有限;nextcloud是owncl...
- 分享一个docker镜像源地址,解决docker不能拉取的问题
-
自己搭建的代理,centos7只需要修改/etc/docker/daemon.json并输入以下内容:{"registry-mirrors":["https://next...
- 源支付5.18版全套开源源码客户端+云端+监控+协议三网免挂免输入
-
源支付5.18最新版协议去授权全套三端开源源码_客户端+云端+监控+协议三网免挂免输入(全套版)推荐系统为:CentOS7.6Linux系统环境:Nginx1.20.1+MySQL5.6....
- centos7飞速搭建zabbix5.0并添加windows、linux监控
-
一、环境zabbix所在服务器系统为centos7,监控的服务器为windows2016和centos7。二、安装zabbix官方安装帮助页面...
- CentOS上配置 Docker 使用代理服务器
-
hub.docker最近总被墙,国内大厂搞的docker镜像源代理被封被停,对于一个严重依赖一些海外项目的软件开发人员,简直没法干活了。docker要在CentOS上配置Docker使用代理服...
- CentOS 7 (阿里云虚拟机) 安装 Docker
-
一、安装Docker1.使用root权限登录CentOS。确保yum包更新到最新sudoyumupdate...
- Centos离线静默安装 oracle11g,步骤细验证成功
-
一、环境要求1.1.涉及工具及环境1)CentOS764位系统2)oracle安装包文件a)linux.x64_11gR2_database_1of2.zip...
- Linux运维之制作指定软件包的YUM源
-
#挑战30天在头条写日记#关注我,不迷路,大家好,我是大王。--记录运维中遇到的故障及排查方法...
- 在CentOS 9 安装Nvidia显卡驱动详细操作步骤
-
今天给粉丝网友演示CentOS9系统下如何安装nvidia显卡驱动。·将下载好的显卡驱动放到文件夹中,这里以download为例,放入文件夹中开始对系统软件升级,是为了防止在安装显卡驱动时显示报错...
- 基于Linux系统的本地Yum源搭建与配置(ISO方式、RPM方式)
-
前言:由于公司业务服务器大部分都在内网环境下运行,内网环境无法直接使用yum安装升级更新软件,所以需要自建Yum源来满足目前日常工作需要。...
- 最新zabbix一键安装脚本(基于centos8)
-
一、环境准备注意:操作系统必须是centos8及以上的,因为我配的安装源是centos8的。并且必须连接互联网,脚本是基于yum安装的!!!...
- CentOS7中使用yum安装Nginx的方法
-
1、添加源 默认情况Centos7中无Nginx的源,最近发现Nginx官网提供了Centos的源地址。因此可以如下执行命令添加源(...
- Centos8出现Failed to download metadata for repo 'AppStream'解决
-
大家都知道Centos8于2021年年底停止了服务,大家再在使用yum源安装时候,出现下面错误“错误:Failedtodownloadmetadataforrepo'AppStre...
你 发表评论:
欢迎- 一周热门
- 最近发表
-
- centos7使用yum安装nginx+php7+mysql5.6
- Linux基础入门(VMWare中CentOS7配置yum)
- CentOS 7搭建Nextcloud私有云(centos搭建云盘)
- 分享一个docker镜像源地址,解决docker不能拉取的问题
- 源支付5.18版全套开源源码客户端+云端+监控+协议三网免挂免输入
- centos7飞速搭建zabbix5.0并添加windows、linux监控
- CentOS上配置 Docker 使用代理服务器
- CentOS 7 (阿里云虚拟机) 安装 Docker
- Centos离线静默安装 oracle11g,步骤细验证成功
- Linux运维之制作指定软件包的YUM源
- 标签列表
-
- 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)