golang造轮子 封装一个简单的http client

近来无事,本着爱折腾的原则,在go原生 http client 的基础上,自己封装了一个go的http client。由于才疏学浅,再加是第一次造轮子,在各位大佬面前献丑了,写的烂的地方,请轻喷。还请各位不吝赐教。

先放地址

gethub: https://github.com/lqxhub/easy_http

Gitee: https://gitee.com/lqxlucky/easy_http

简单介绍一下功能

  1. 使用 构造器模式,提供了链式调用和方便使用的接口
  2. 支持https自定义服务器证书校验和双向证书校验
  3. 支持代理,可以方便的设置代理
  4. 封装了multipart 协议, 可以方便的上传文件
  5. 具有很强的拓展性,可以在基础上非常方便的定制自己http请求
  6. 支持http的 返回结果 异步回调
  7. 可以方便的自定义Response

安装库

可以使用github的库,也可使用Gitee的库,两个库的代码都是一样的,因为github网速的原因,所以在gitee上也传了一份

  1. github:go get -u https://github.com/lqxhub/easy_http

  2. gitee: go get -u https://gitee.com/lqxlucky/easy_http

使用

引入库

因为github和gitee拉下来的库目录不同,所以以github的为准

1import "github.com/lqxhub/easy_http"

具体使用

全部配置

 1func main() {
 2	//得到一个http client的构造器
 3	builder := easy_http.NewClientBuilder()
 4
 5	//是否跳过服务器证书校验
 6	builder.SkipVerify(false)
 7
 8	//设置超时时间
 9	builder.TimeOut(time.Second * 5)
10
11	//设置代理
12	builder.ProxyUrl("http://127.0.0.1:10809")
13
14	//设置根证书
15	var certPool [1]string
16	certPool[0] = "D:\\server.pem"
17	builder.Cert(certPool[:])
18	
19	//设置双向校验证书
20	var tlsPath [1]*easy_http.TlsPath
21	tlsPath[0] = &easy_http.TlsPath{
22		CertFile: "D:\\client.pem",
23		KeyFile:  "D:\\client.key",
24	}
25	builder.Tls(tlsPath[:])
26
27	//设置http请求header
28	header := make(map[string]string)
29	header["Accept-Language"] = "Accept-Language: en,zh"
30	builder.Header(header)
31
32	//设置http请求cookie
33	cookie := make(map[string]string)
34	cookie["name"] = "value"
35	builder.Cookie(easy_http.EasyCookie(cookie))
36
37	//开启cookie jar
38	builder.Jar(nil)
39
40	//设置 Response 处理函数
41	builder.BuildResponse(easy_http.EasyBuildResponse)
42
43	//构造client
44	client, err := builder.Build()
45	if err != nil {
46		fmt.Println("aa", err)
47		return
48	}
49}

这样就初始化一个http的客户端

当然,上面的例子是设置了所有配置的,也可以全部使用默认配置

使用默认配置

1func DefaultClient() {
2	builder := easy_http.NewClientBuilder()
3	client, err := builder.Build()
4	if err != nil {
5		fmt.Println(err)
6		return
7	}
8	client.Get("http://baidu.com")
9}

这样同样是可以的

easy 函数 使用

库中提供了一些函数,可以方便的构造http请求相关的结构

 1func EasyFunction() {
 2
 3	url := "http://baidu.com"
 4
 5	//合成http get的url和参数 
 6	values := make(map[string]string)
 7	values["v"] = "123456"
 8	easy_http.EasyGet(url, values)
 9
10	//构造cookie
11	cookie := make(map[string]string)
12	cookie["name"] = "value"
13	easy_http.EasyCookie(cookie)
14
15	//合成 http post 的参数
16	easy_http.EasyPost(values)
17
18	//构造 上传文件的multipart
19	multipartBuilder := easy_http.NewMultipartBuilder()
20	multipartBuilder.AddFile("file1","D:\\a.txt")
21	multipartBuilder.AddFromDate("name","value")
22	multipartBuilder.AddBytes("name2",[]byte("aaaaa"))
23	multipart, err := multipartBuilder.Builder()
24	
25}

异步回调使用

库封装了 异步回调功能,请求会在一个新的goroutine中进行。当http请求完成时,会回调函数。回调函数可用形参使用传入函数和实现接口两种方式

 1
 2func Call(response easy_http.IResponse) {
 3	fmt.Println(response.Error())
 4	fmt.Println(response.StatusCode())
 5	fmt.Println(string(response.Content()))
 6}
 7
 8type Get struct {
 9}
10
11func (g Get) EasyResponseCallback(response easy_http.IResponse) {
12	fmt.Println(response.Error())
13	fmt.Println(response.StatusCode())
14	fmt.Println(string(response.Content()))
15}
16
17func AsynchronousRequest() {
18	url := "http://baidu.com"
19	client, err := easy_http.NewClientBuilder().Build()
20	if err != nil {
21		fmt.Println(err)
22		return
23	}
24
25	//函数异步回调
26	client.GetAsyn(url, Call)
27
28	//接口异步回调
29	client.GetAsynWithCallback(url, &Get{})
30}

自定义请求

因为库中只封装了 GET和POST这两种方式,向PUT,DELETE等这些方式需要自己去实现。所以,可以使用下面的函数来实现

 1func Call(response easy_http.IResponse) {
 2	fmt.Println(response.Error())
 3	fmt.Println(response.StatusCode())
 4	fmt.Println(string(response.Content()))
 5}
 6
 7func CustomizeRequest() {
 8	url := "http://baidu.com"
 9	client, err := easy_http.NewClientBuilder().Build()
10	if err != nil {
11		fmt.Println(err)
12		return
13	}
14	response := client.SendWithMethod(url, http.MethodPut, nil, func(request *http.Request) {
15		//修改Request
16	})
17	fmt.Println(response.Error())
18	fmt.Println(response.StatusCode())
19
20	//异步方式
21	client.SendWithMethodCallBack(url, http.MethodPut, nil, func(request *http.Request) {
22		//习惯Request
23	}, Call)
24}

使用go http默认的函数请求

当需要有一些特殊的请求,这个库无法满足时,可以使用go http原生的方式来请求

 1func Primitive() {
 2	url := "http://baidu.com"
 3	client, err := easy_http.NewClientBuilder().Build()
 4	if err != nil {
 5		fmt.Println(err)
 6		return
 7	}
 8	//获取Request
 9	request, err := http.NewRequest(http.MethodGet, url, nil)
10	if err != nil {
11		fmt.Println(err)
12		return
13	}
14	//得到http的原生Response
15	response, err := client.DoRequest(request)
16	if err != nil {
17		fmt.Println(err)
18		return
19	}
20	fmt.Println(response)
21}

自定义Response

库中返回的Response是一个接口类型,只要实现了这个接口,都可作为返回值返回,自定义的Response,在构造client的设置就可以了

 1type MyResponse struct {
 2}
 3
 4func (m MyResponse) Error() error {
 5	return nil
 6}
 7
 8func (m MyResponse) StatusCode() int {
 9	return 0
10}
11
12func (m MyResponse) Header() http.Header {
13	return nil
14}
15
16func (m MyResponse) ContentLength() int64 {
17	return 0
18}
19
20func (m MyResponse) Content() []byte {
21	return nil
22}
23
24func (m MyResponse) Resp() *http.Response {
25	return nil
26}
27
28func (m MyResponse) Request() *http.Request {
29	return nil
30}
31
32func (m MyResponse) Cookie(name string) *http.Cookie {
33	return nil
34}
35
36//构造HTTP response的函数
37func MyBuildResponse(resp *http.Response, err error) easy_http.IResponse {
38	response := new(MyResponse)
39    //做处理
40	return response
41}
42func CustomizeResponse() {
43	client, err := easy_http.NewClientBuilder().
44		BuildResponse(MyBuildResponse).
45		Build()
46	if err != nil {
47		fmt.Println(err)
48		return
49	}
50}

结构体 MyResponse 实现了 easy_http.IResponse 这个接口。然后在MyBuildResponse这个函数中,new 一个 MyResponse的对象,再根据自己的需要,做相应的处理就可以了。 在clientBuilder.BuildResponse(MyBuildResponse)设置就可以了

最后

整个库的基本功能就是这些了。第一造轮子,写的很烂。写这篇文章时,还发现了好几个因为首字母小写导致的问题。

有问题的地方,还请不吝赐教

发表了56篇文章 · 总计128.44k字
本博客已稳定运行
© QX
使用 Hugo 构建
主题 StackJimmy 设计