Go Web:自带的ServeMux multiplexer
ServeMux简介
ServeMux扮演的角色是Multiplexer,它用来将将请求根据url路由给已注册的handler。如下图:

上图中为3个路径注册了handler,一个是"/",另外两个是"/hello"和"/world"。这表示访问http://hostname/hello时,multiplexer会调用上图中对应的第二个handler,当访问http://hostname/world时,multiplexer会调用上图中对应的第三个handler,当不是这两个路径时,将调用第一个绑定在"/"上的handler。
注意,go的mux路由请求时,handler绑定的路径是否带尾随"/"是不一样的。带上尾随"/",表示此路径以及此路径下的子路径,都会调用注册在此路径上的handler。
例如,当请求uri为"/hello/abc"的时候,不会调用"/hello"对应的handler,而是调用"/"对应的handler。只有注册handler的路径为"/hello/"时,uri为"/hello/abc"才会调用此handler。
实际上,当注册handler的路径带上尾随斜"/"时,在发起此路径的请求时,会通过301重定向的方式自动补齐这个尾随斜线,让浏览器发起第二次请求。例如,下面是注册handler的路径:
http.Handle("/hello/", &myHandler)
发起http://hostname/hello的请求时,会自动补齐为http://hostname/hello/,然后浏览器自动发起第二次请求。
ServeMux的匹配规则
ServeMux对每次流入的http请求的URL进行模式(pattern)匹配,然后调用注册在此pattern上的handler来处理这个请求。
Pattern部分可以定义为匹配host的模式。如果pattern以"/"开头,表示匹配URL的路径部分,如果不以"/"开头,表示从host开始匹配。
匹配时选择匹配匹配度最高(长匹配优先于短匹配)。例如为"/images/"注册了handler1,"/images/thumbnails/"注册了handler2,如果请求的URL路径部分为"/images/thumbnails/",将会调用handler2处理这个请求,如果请求的URL路径部分为"/images/foo/",将调用handler1处理。
注意,注册在"/"上的pattern会在其它模式匹配不上时被选中,因为所有请求都可以匹配这个pattern,只不过能匹配到的长度最短。
如果pattern带上了尾随斜线"/",ServeMux将会对请求不带尾随斜线的URL进行301重定向。例如,在"/images/"模式上注册了一个handler,当请求的URL路径为"/images"时,将自动重定向为"/images/"。除非再单独为"/images"模式注册一个handler。
如果为"/images"注册了handler,当请求URL路径为"/images/"时,将无法匹配该模式。
ServeMux详细解释
看看net/http/server.go文件中ServeMux的结构:
type ServeMux struct {
mu sync.RWMutex
m map[string]muxEntry
hosts bool // whether any patterns contain hostnames
}
type muxEntry struct {
h Handler
pattern string
}
结构看上去很简单。一个字段mu是RWMutex,m是注册handler和pattern的,hosts用于判断pattern是否包含了host的匹配。看看Handle()函数的定义会更清晰:
func (mux *ServeMux) Handle(pattern string, handler Handler) {
mux.mu.Lock()
defer mux.mu.Unlock()
if pattern == "" {
panic("http: invalid pattern")
}
if handler == nil {
panic("http: nil handler")
}
if _, exist := mux.m[pattern]; exist {
panic("http: multiple registrations for " + pattern)
}
if mux.m == nil {
mux.m = make(map[string]muxEntry)
}
mux.m[pattern] = muxEntry{h: handler, pattern: pattern}
if pattern[0] != '/' {
mux.hosts = true
}
}
// HandleFunc registers the handler function for the given pattern.
func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
mux.Handle(pattern, HandlerFunc(handler))
}
pattern为空或者handler为空时,都会panic。此外,想要定义重复的pattern,也会panic。如果pattern的第一个字符不是"/",则表示这个pattern是从主机名开始匹配的。
唯一需要注意的是,每个Handle()都会对ServeMux实例加上写锁。
以常用的DefaultServeMux为例,它是ServeMux的一个实例。当使用DefualtServeMux时,每调用一次Handle()或HandleFunc(),都意味着向这个DefaultServeMux的结构中的m字段添加pattern和对应的handler。由于加了写锁,如果使用多个goroutine同时启动多个web服务,在同一时刻将只能有一个goroutine启动的web服务能设置DefaultServeMux。当然,一般情况下不会使用goroutine的方式同时启动多个web服务。
第三方ServeMux
自带的默认的DefaultServeMux其实功能限制很大。比如请求的URL路径为"/images/123.png",想要匹配这个确实容易,但是想要取出其中的"123.png"字符串,DefaultServeMux就没法实现。
有一个非常强大的Gorilla工具包(www.gorillatoolkit.org),它有好几个功能,其中一个功能是提供multiplexer。
Go Web:自带的ServeMux multiplexer的更多相关文章
- 【WEB】带边框的网页页面实现
前言 这是编程入学者尝试各种技术的备忘记录和自我激励,内容非常简单而单纯. 正文 成品 样式参考 http://tenhou.net/ 上边框 http://tenhou.net/img/f0t ...
- Go语言系列文章
这个系列写的不是很好,未来重构. Go基础系列 Go基础 Go基础 1.Go简介 2.Go数据结构struct 3.构建Go程序 4.import导包和初始化阶段 5.array 6.Slice详解 ...
- Gulp实现web服务器
Gulp实现web服务器 阅读目录 一:gulp实现web服务器配置: 二:添加实时刷新(livereload)支持 回到顶部 一:gulp实现web服务器配置: 对于前端开发而言,需要在本地搭建一个 ...
- 代码实现PHP web服务器下绝对路径到Web网址的转换
代码实现PHP web服务器下绝对路径到Web网址的转换 代码中用到几个系统变量或常量: 1. 路径中各目录分隔字符 DIRECTORY_SEPARATOR(常量),Windows下DIRECTORY ...
- 整理六百篇web前端知识混总
9个有用的和免费的工具来支持动态网页开发 8个基本的引导工具的网页设计师 11款CSS3动画工具的开发 2016年某前端群题目答案参考 9最好的JavaScript压缩工具 创建响应式布局的10款优秀 ...
- [Web安全] XXE漏洞攻防学习(中)
0x00.XXE漏洞攻击实例 攻击思路: 1. 引用外部实体远程文件读取 2. Blind XXE 3. Dos 0x01.外部实体引用,有回显 实验操作平台:bWAPP平台上的XXE题目 题目: 进 ...
- Progressive Web App
下一代 Web 应用? 近年来,Web 应用在整个软件与互联网行业承载的责任越来越重,软件复杂度和维护成本越来越高,Web 技术,尤其是 Web 客户端技术,迎来了爆发式的发展. 包括但不限于基于 N ...
- 《Agile Web Development With Rails》读后感--rails基于web设计的best Practices
最近看完<Agile Web Development with Rails>一书,受益匪浅.书中先是用一个简单的web应用带你进入Rails的世界,然后在你大致熟悉之后,再带你了解Rail ...
- java web 开发三剑客 -------电子书
Internet,人们通常称为因特网,是当今世界上覆盖面最大和应用最广泛的网络.根据英语构词法,Internet是Inter + net,Inter-作为前缀在英语中表示“在一起,交互”,由此可知In ...
随机推荐
- 20145232韩文浩《网络对抗》MSF基础应用
MS08-067漏洞攻击 攻击机:Kali:192.168.31.132 靶机:win XP SP3(English):192.168.31.180 在VMware中设置两台虚拟机网络为NAT模式,自 ...
- openXML向Word插入表
表是 Word 中的另一类型的块级内容,它是以行和列排列的一组段落(以及其他块级内容). Word 中的表格通过 tbl 元素定义,该元素类似于 HTML <表格>标记. 表元素指定文档中 ...
- kubernetes CRD学习笔记
前言 最近在极客时间订阅了kubernetes的专栏,这篇文章是想记录一下自己学习CRD(custom resource definition)的过程,加深一下记忆. 准备工作 首先安装一下我们用的g ...
- ubuntu+apache2设置访问、重定向到https
环境:ubunt14裸机,apache2,php5 条件:证书(部分商家买域名送一年),域名,为了方便均在root用户下进行的 web目录:/var/www/test 证书目录(自建):/etc/ap ...
- day_7数据类型的相互转换,与字符编码
首先复一下昨天的内容 1:深浅拷贝 1:值拷贝 直接赋值 列表1=列表2 列表1中的任何值发生改变,列表2中的值都会随之改变 2:浅拷贝,列表2=列表1 列表1中存放的值的地址没有改变, ...
- job定时任务
1,定时任务依赖的执行类 2.引入job 3.执行时间 4.管理job
- [转] OpenStack — nova image-create, under the hood
I was trying to understand what kind of image nova image-create creates. It's not entirely obvious f ...
- 【腾讯Bugly干货分享】人人都可以做深度学习应用:入门篇
导语 2016年,继虚拟现实(VR)之后,人工智能(AI)的概念全面进入大众的视野.谷歌,微软,IBM等科技巨头纷纷重点布局,AI 貌似将成为互联网的下一个风口. 很多开发同学,对人工智能非常感兴趣, ...
- Apache Sentry部署
三台hadoop集群,分别是master.slave1和slave2.下面是这三台机器的软件分布: master:NameNode.ZK.HiveMetaSotre.HiveServer2.Sentr ...
- Bitmap too larget to be uploaded into a texture的解决方法
Bitmap too larget to be uploaded into a texture的解决方法 问题描述 使用canvas.drawBitmap()系列方法时,抛出错误Bitmap too ...