http网络编程
客户端http
http包中提供了一个Client的struct
type Client struct {
Transport RoundTripper
CheckRedirect func(req *Request, via []*Request) error
Jar CookieJar
Timeout time.Duration
}
其提供的函数也比较少,只有Do、Get、Post、PostForm以及Head,后面四个函数都是用Do函数来实现的。其中Get是发起一个Get请求,Post和PostForm函数表示发送一个Post请求,Head表示发送一个Head请求,而Do表示发送一个任意method请求。Do函数的签名为
func (c *Client) Do(req *Request) (*Response, error)
是个非常典型的同步调用函数,传入一个req返回一个resp。
Request类型无非就包括那么些http的请求参数,比如method类型(GET/POST/HEAD等),url、header等,将这些参数传给Request就能构造出一个发起http请求的Request。
Response的函数和参数也不多,也只有一些基本的http响应的参数。主要包括:
- 响应码:StatusCode
- 响应说明:Status
- 响应头:Header
- ContentLength:响应长度
- Body:最重要的服务器返回的内容
func Request() {
resp, err := http.DefaultClient.Get("https://www.baidu.com")
if err != nil {
panic(err)
}
fmt.Println(resp.StatusCode, resp.Status, resp.Header, resp.ContentLength)
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
panic(err)
}
fmt.Println(string(body))
}
上面的代码是使用http发送一个Get请求,访问baidu首页
服务端http
go的http服务端也是在http包中,go sdk提供了一套http server的实现。
func Server() {
err := http.ListenAndServe(":8080", http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
writer.WriteHeader(http.StatusOK)
_, _ = writer.Write([]byte(fmt.Sprintf("hello %s\n", request.URL.Path)))
}))
if err != nil {
panic(err)
}
}
上面的代码用http包实现了一个最简单的http server,监听8080端口,对所有的请求都返回200,并返回body为hello + 请求的path
查看http.ListenAndServe的源码不难发现,其是创建了一个http.Server,然后调用server#ListenAndServe函数。其中http.Server的创建需要传入一个addr和一个Handler,这个Handler就是我们传入的http.HandleFunc函数,这表明这个Server只能有一个处理函数,那么如果我们需要为每个path添加一个Handler呢?
这时就需要使用http包提供的ServeMux,其Handle函数签名为Handle(pattern string, handler Handler)
,pattern表示path的正则,handler就是path的处理函数。
https的支持
现在的http服务器,基本上都被要求使用https协议来保证数据传输的安全,go的http包当然也提供了对https协议的支持。还是以一个最简单的https server举例:
func HttpsServer() {
fmt.Println(os.Executable())
err := http.ListenAndServeTLS(":8080", "./conf/server.crt", "./conf/server.key", http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
writer.WriteHeader(http.StatusOK)
_, _ = writer.Write([]byte(fmt.Sprintf("hello %s\n", request.URL.Path)))
}))
if err != nil {
panic(err)
}
}