天下难事,必始于易。 慎始如终,则不败事。 --老子
1 基础http路由服务
内建的包 net/http 为http服务提供了很多功能,包括建立tcp连接和 sockets连接管理,这些都被ListenAndserve函数所包括。
然后调用与处理程序一起服务以处理传入连接的请求。接受的连接被配置为启用 TCP,并保持活动。
处理程序通常为 nil,在这种情况下使用 DefaultServeMux。 这在上一节有讲到。
ListenAndServe 总是返回一个非零错误
其主体服务程序形式为:
type zooms struct{}
func (h zooms) ServeHTTP(res http.ResponseWriter, req *http.Request) {
...
}
func httpServer() {
http.ListenAndServe(httpPort, zk)
}
如果Serve的地址 为空,则使用“:http”。 ListenAndServe 总是返回一个非零错误。关机或关闭后,返回的错误是 ErrServerClosed。
Serve 接受 Listener 上的传入连接,每个新的服务都将创建一个 goroutine。
goroutines 服务 读取请求和 然后调用 srv.Handler 来回复他们。
仅当监听器返回 *tls.Conn 时才启用 HTTP/2 支持连接,并且它们在 TLS 中的Config.NextProtos配置为“h2”.
当服务失败时总是返回一个非零错误并关闭 listener. Shutdown 或 Close 后,返回的错误是 ErrServerClosed。
访问猫头鹰
http://127.0.0.1:3010/owls
miao,miao...
访问大象
http://127.0.0.1:3010/elephants
ang,ang...
访问老虎
http://127.0.0.1:3010/tiger
aoo,aoo...
2 多路复用 http路由服务
http请求多路复用器,它为每一个进入的请求,在注册列表进行有针对的匹配使用模式匹配最接近的URL 路由,模式也调用处理器的处理程序。
模式使用最终的,根路径,如 /favicon.ico 或者 根路径子路由树 如 /images/ 注意最后跟了路径分割符长路径优先于短路径匹配。
如果长路径不存在,比如/ele/food/ 不存在, 将缩减直到根路径 / 。请看后面的例子。
如果两个路径都存在,比如 /ele/, /ele/food 此后的程序将使用长路由 /ele/food
需要注意的是,如果/ele/的某个子路由, 比如 /ele/foo 不存在,那么其子路由/ele/foo的任何调用都将 匹配到/ele/。
如果 路由 /ele 没有 路径分割符/, 那么/ele/foo 将直接匹配到 根路由 /
如果路由定义了 最终分隔符 /ele/ 但是调用是没有指定, 只是使用 /ele调用那么,
系统将返回一个 301重定向的提示,如果使用浏览器将被自动导向/ele/, 即 301,200 至少两次调用,
因为在编写路由 /ele/时, ServeMux 将/ele 和 /ele/ 都写入了注册器中。
curl http://127.0.0.1:3020/ele
<a href="/ele/">Moved Permanently</a>.
该注册模式可选以一个主机名开始,因此限制只能在该主机域名进行匹配。 主机特定匹配优先于 一般的模式匹配,
因此一个处理函数可能注册两个模式,而不需要接入 http://www.google.com/
/codesearch
codesearch.google.com
ServeMux 将负责验证URL请求路径和主机的域名,剥离端口号并重定向包含的任何请求,或重复的元素如 //,直到获得干净的url
http://127.0.0.1:3020\/ele\/
http://127.0.0.1:3020//ele//
scheme http
host 127.0.0.1:3020
filename //ele/
比如在本示例中,端口3020服务没有 大象 elephants,该路由算法将 匹配到 根路径 /
curl http://127.0.0.1:3020/
welcome Big Zoom!
错误调用路径将返回到根路由
curl http://127.0.0.1:3020/ele/food/
welcome Big Zoom!
正确调用
curl http://127.0.0.1:3020/ele/food
corn,apple,rice,grass...
其主体服务形式为:
type zooms struct{}
func (h zooms) ServeHTTP(res http.ResponseWriter, req *http.Request) {
...
}
//创建http多路复用服务
func muxHttpServer() {
var manager zooms
router := http.NewServeMux()
router.Handle("/", manager)
http.ListenAndServe(muxPort, router)
}
其中 Handle 注册给定模式的处理程序。如果模式的处理程序已经存在,则抛出恐慌错误。
访问老虎
http://127.0.0.1:3020/tiger
aoo,aoo,aoo,aoo,...
访问猫头鹰
http://127.0.0.1:3020/owl
wu,wu,wu,wu,...
访问大象
http://127.0.0.1:3020/ele/
ang,ang,ang,ang,...
喂食大象
http://127.0.0.1:3020/ele/food
corn,apple,rice,grass...
3 小结
在net/http中ServeHTTP
方法定义自定义处理器。ListenAndServe
在 http 无参数时启动,并始终返回非零错误。
HTTP多路复用ServeMux通过模式匹配路由请求。ServeMux
根据最长匹配路径路由,无子路由时重定向至带尾斜线的路径。主机特定匹配优先。Handle
注册处理程序,重复注册会引发恐慌。
本节完整代码:
https://github.com/hahamx/examples/blob/main/tcps/2_with_http_handler/http_service.go