HTTP协议应该大家并不陌生吧,这是现有互联网中应用最为广泛的一种网络协议。
在Go中,标准库中内建提供了net/http
包,基本上涵盖了HTTP客户端的具体实现的基本内容,因此,使用net/http
包可以很容易的编写HTTP客户端或服务器端的程序。
HTTP客户端
我们在使用Go来建立HTTP客户端之后,无需借助第三方网络通信就可以直接使用HTTP中用得最多的GET和POST方式请求数据。
1.基本用法
1)http.Get()
方法定义:
func (c *Client) Get(url string) (r *Response, err error)
我们要请求一个资源时,只需要调用http.Get()
方法即可:
resp, err := http.Get("http://example.com/")
if err != nil {
// 处理错误
return
}
defer resp.Body.close()
io.Copy(os.Stdout, resp.Body)
上面这个例子的功能是对`http://example.com/进行请求,并将请求得到的结果(即网页的内容)打印到标准输出流中。
2)http.Post()
方法定义:
func (c *Client) Post(url string, bodyType string, body io.Reader) (r *Response, err error)
函数中的三个参数分别代表的是:请求的目标URL,将要POST数据的资源类型和数据的比特流([]byte
格式)。
resp, err := http.Post("http://example.com", "image/jpeg". &imageDataBuf)
if err != nil {
// 处理错误
return
}
if resp.StatusCode != http.StatusOK {
// 处理错误
return
}
上面这个例子实现了上传一张照片的功能。
3)http.PostForm()
方法定义:
func (c *Client) PostForm(url string, data url.Values) (r *Response, err error)
PostForm
向指定的URL发出一个POST请求,url.Values
类型的data
会被编码为请求的主体。POST数据的类型一般会设为application/x-www-form-urlencoded
。如果返回值err
为nil
,resp.Body
总是非nil
的,调用者应该在读取完resp.Body
后关闭它。
resp, err := http.PostForm("http://example.com", {"article title"}, "content":{"article body"})
if err != nil {
// 处理错误
return
}
上面这个例子模拟了HTML表单提交一篇新文章的功能。
4)http.Head()
方法定义:
func (c *Client) Head(url string) (r *Response, err error)
Head向指定的URL发出一个HEAD请求,如果回应的状态码如下,Head会在调用c.CheckRedirect
后执行重定向:
301 (Moved Permanently)
302 (Found)
303 (See Other)
307 (Temporary Redirect)
resp, err := http.Head("http://example.com/")
上面的例子实现了请求一个网站首页的HTTP的Header信息的功能。
2.封装
1)自定义http.Client
前面所介绍的几个函数其实都是在http.DefaultClient
函数的基础上进行调用的,比如http.Get()
其实是等价于http.DefaultClient.Get()
的,
首先我们来看一下http.Client
类型的结构:
type Client struct {
Transport RoundTripper
CheckRedirect func(req *Request, via []*Request) error
Jar CookieJar
}
我们来着重介绍一下CheckRedirect
函数类型,它指定的是处理重定向的策略,正如前面所说,当使用HTTP Client
的Get()
或者Head()
方法发送HTTP请求时,若响应返回的状态码为30x,HTTPClient
会在遵循跳转规则之前先调用这个CheckRedirect
函数。
2)http.Transport
在刚才的Client
中,第一个成员就是一个http.Transport
对象,该对象指定一个HTTP请求时的运行规则。我们分别来看看http.Transport
里面有什么对象。
Proxy func(*Request) (*url.URL, error)
该方法接收一个 *Request
类型的请求实例作为参数并返回一个最终的HTTP代理。如果Proxy
未指定或者返回的*URL
为零值,将不会有代理被启用。
Dial func(net, addr string) (c net.Conn, err error)
该函数指定具体的dial()
方法来创建TCP连接。
TLSClientConfig *tls.Config
SSL连接专用,TLSClientConfig
指定tls.Client
所用的TLS配置信息。
DisableKeepAlives bool
是否取消长连接,默认值为false
。
DisableCompression bool
是否取消压缩(GZip),默认值为false
。
MaxIdleConnsPerHost int
指定与每个请求的目标主机之间的最大非活跃连接数量(keep-alive)。默认是与DefaultMaxIdleConnsPerHost
值相同的。
HTTP服务器端
1.处理HTTP请求
使用net/http
包中的http.ListenAndServe()
方法,可以在指定的地址进行监听,开启一个HTTP:
func ListenAndServe(addr string, handler Handler) error
该方法用于在指定的TCP网络地址addr
进行监听。
具体示例如下:
http.Handle("/foo", fooHandler)
http.HandleFunc("/bar", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, %q", html.EscapeString(r.URL.Path))
})
log.Fatal(http.ListenAndServer(":8000", nil))
当然,我们还可以自定义http.Server
:
s := &http.Server{
Addr: ":8000",
Handler: myHandler,
ReadTimeout: 10 * time.Second,
WriteTimeout: 10 * time.Secont,
MaxHeaderBytes: 1 << 20,
}
log.Fatal(s.ListenAndServer())
处理HTTPS请求
在net/http
包中还提供http.ListenAndServerTLS()
的方法,用于处理HTTPS连接请求:
func ListenAndServerTLS(addr string, certFile string, keyFile string, handler Handler) error
开启SSL监听服务也很简单:
http.Handle("/foo", fooHandler)
http.HandleFunc("/bar", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, %q", html.EscapeString(r.URL.Path))
})
log.Fatal(http.ListenAndServerTLS(":10413", "cert.pem", "key.pem", nil))
或者是对其进行自定义:
s := &http.Server{
Addr: ":10413",
Handler: myHandler,
ReadTimeout: 10 * time.Second,
WriteTimeout: 10 * time.Secont,
MaxHeaderBytes: 1 << 20,
}
log.Fatal(s.ListenAndServerTLS("cert.pem", "key.pem"))
以上是关于HTTP的简单介绍,接下来,我们将讲解RPC的有关内容,敬请期待。