20 网络编程 Web 服务器
[TOC]
Web 服务器
Go 提供了一个完善的 net/http 包,通过 http 包很容易就可以搭建 Web 服务器。使用net/http包能很简单地对 Web 的路由、静态文件、模版、cookie 等数据进行设置和操作,不需要再去引入其它任何额外的依赖。
net/http 包也提供了HTTP客户端的相关API,可以很简单发起HTTP请求。
Go HTTP 服务器
net/http下 常用API
注册处理函数 http.HandleFunc(资源url string, 资源对应处理函数))
监听一个端口启动HTTP服务器 http.ListenAndServe("ip:port",nil)
HTTP 处理器和处理器函数
处理器需要实现Handler接口,接口有一个ServeHTTP(ResponseWriter, *Request)方法,任何实现了这个接口的类型都是处理器。
ListenAndServe 使用指定的监听地址和处理器启动一个HTTP服务端。处理器参数通常是nil,这表示采用包变量 DefaultServeMux 作为处理器。
Handle 和 HandleFunc 函数可以向 DefaultServeMux 添加处理器。
package main
import (
"fmt"
"net/http"
)
type MyHandler1 struct {}
func (h1 *MyHandler1) ServeHTTP(writer http.ResponseWriter,request *http.Request){
fmt.Println("h1处理器")
writer.Write([]byte("h1响应数据"))
}
type MyHandler2 struct {}
func (h2 *MyHandler2) ServeHTTP(write http.ResponseWriter,request *http.Request){
fmt.Println("h2处理器")
write.Write([]byte("h2响应数据"))
}
func main() {
server := http.Server{
Addr: "0.0.0.0:8080",
}
http.Handle("/h1",&MyHandler1{})
http.Handle("/h2",&MyHandler2{})
server.ListenAndServe()
// 分别访问 http://localhost:8080/h1 和 http://localhost:8080/h2,不同处理器监听了不同的 url
}处理器函数是与处理器拥有相同行为的函数,它与ServeHTTP(ResponseWriter, *Request)方法有相同的签名。
读取数据 流方式
读取请求体body数据
请求方式除了Get以外,其它请求方式数据都可在body中读取。
如果body中的数据已经被读取,则其它方式都将读取不到数据。
读取表单数据 FormValue,读取Header数据
通过FormValue读取数据,可以读取Get请求和表单提交,但要注意,在非Get请求情况如果先把body数据读取了,再到FormValue是读取不到数据的。
表单数据,增加请求头 【Content-Type:application/x-www-form-urlencoded】
要读取表单数据要先 request.ParseForm()
读取请求头使用 request.Header.Get(key)
设置响应头 writer.Header().Set("test-header","test")
带有配置的Web服务器
要带配置的Web服务器使用http.Server,需要自定义Handler,自定义Handler需要实现Handler接口。
响应 json数据 application/json
响应状态码设置 重定向302
多路复用器 ServeMux 和 DefaultServeMux
ServeMux是一个HTTP请求多路复用器,它负责接收HTTP请求并根据请求中的URL将请求交给正确的处理器。
ServeMux结构包含了一个map,map会将URL作为key处理器作为value。
ServeMux结构也实现了ServeHTTP方法,所以它也是一个处理器,当ServeMux的ServeHTTP方法接收到一个请求的时候,它会在结构的map中找出被请求URL最为匹配的URL(绝对路径将会优先于相对路径),然后调用与之相应的处理器。
ServeMux不是接口而是一个结构体,所以DefaultServeMux并不是ServeMux的实现。
DefaultServeMux是ServeMux的一个实例,并且所有引入net/http标准库的程序都可以使用这个实例。如果没有指定ServeMux,服务器就会默认使用DefaultServeMux。
第三方多路复用器 "github.com/julienschmidt/httprouter",有开发了一些新的功能(如从URL中提取出参数)。

多路复用器转发给处理器图

多路复用器的工作原理图
多路复用器使用:
HTTP 静态资源处理器配置
静态资源处理器配置
http.FileServer 创建一个文件HTTP请求的处理器,文件路径在Dir下,【http.FileServer(http.Dir("./web/webapp/page"))】。配置的路径是从goPath开始的,在集成开发工具中是从项目根路径开始。
http.StripPrefix 如果URL前缀是prefix则URL会被TrimPrefix截去前缀,因为目录配置是【"./web/webapp/page"】访问的URL一般是http://域名/page/index.html,如果不截去前缀则会在【"./web/webapp/page/page/index.html"】,而实际上文件的目录在【"./web/webapp/page/index.html"】就会无法访问到而出现404。
http.Handle注册处理器,处理请求资源URL与"/page/"最匹配的。
使用 HTTPS
申请了SSL证书之后使用 ListenAndServeTLS 开启HTTPS。
开启HTTPS模式启动服务器,服务器默认使用HTTP2。
Go HTTP 客户端
请求提交数据的常见编码格式有三种:
application/x-www-form-urlencoded 浏览器的原生form表单,如果不设置enctype属性,那么最终就会默认以application/x-www-form-urlencoded方式提交数据。这种情况下请求头的Content-Type被设置成application/x-www-form-urlencoded,提交的数据按照key1=value1&key2=value2的方式进行编码,key和value都进行了URL转码。大部分服务端语言都对这种方式有很好的支持。默认用Ajax提交数据时,也是使用这种方式。
multipart/form-data 是一个常见的POST数据提交的方式,表示在发送前不对数据进行编码,这种方式一般出现在通过form表单上传文件的场景中,在HTML的form标签中通过设置属性enctype=multipart/form-data来表示通过这种方式提交数据。上面提到的这两种POST数据的方式,都是浏览器原生支持的。各大服务端语言对它也有着良好的支持。
application/json 这个Content-Type请求头和响应头都很常见,用来告诉服务端消息主体是序列化后的JSON字符串。由于JSON规范的流行,除了低版本IE之外的各大浏览器都原生支持JSON.stringify,服务端语言也都有处理JSON的函数,使用JSON不会遇上什么麻烦。
Go 作为客户端发起HTTP请求
Get、Post 函数发出 HTTP/ HTTPS请求
http.NewRequest 管理HTTP客户端的头和其他设置
Transport
Client 和 Transport 类型都可以安全的被多个协程同时使用。出于效率考虑,应该一次建立、尽量重用。
transport的主要功能其实就是缓存了长连接,用于大量http请求场景下的连接复用,减少发送请求时TCP(TLS)连接建立的时间损耗,同时transport还能对连接做一些限制,如连接超时时间,每个host的最大连接数等。transport对长连接的缓存和控制仅限于TCP+(TLS)+HTTP1,不对HTTP2做缓存和限制。
Go 文件上传
接收文件上传服务器
HTML 表单上传文件
upload.html
访问 http://localhost:19580/page/upload.html
Go 上传文件
Last updated