Go

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

2021-03-13  本文已影响0人  QxQx

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

先放地址

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

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

简单介绍一下功能

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

安装库

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

  1. github:go get -u github.com/bruce12397/easy_http

  2. gitee: go get -u gitee.com/bruce_le/easy_http

使用

引入库

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

import "github.com/bruce12397/easy_http"

具体使用

全部配置
func main() {
    //得到一个http client的构造器
    builder := easy_http.NewClientBuilder()

    //是否跳过服务器证书校验
    builder.SkipVerify(false)

    //设置超时时间
    builder.TimeOut(time.Second * 5)

    //设置代理
    builder.ProxyUrl("http://127.0.0.1:10809")

    //设置根证书
    var certPool [1]string
    certPool[0] = "D:\\server.pem"
    builder.Cert(certPool[:])
    
    //设置双向校验证书
    var tlsPath [1]*easy_http.TlsPath
    tlsPath[0] = &easy_http.TlsPath{
        CertFile: "D:\\client.pem",
        KeyFile:  "D:\\client.key",
    }
    builder.Tls(tlsPath[:])

    //设置http请求header
    header := make(map[string]string)
    header["Accept-Language"] = "Accept-Language: en,zh"
    builder.Header(header)

    //设置http请求cookie
    cookie := make(map[string]string)
    cookie["name"] = "value"
    builder.Cookie(easy_http.EasyCookie(cookie))

    //开启cookie jar
    builder.Jar(nil)

    //设置 Response 处理函数
    builder.BuildResponse(easy_http.EasyBuildResponse)

    //构造client
    client, err := builder.Build()
    if err != nil {
        fmt.Println("aa", err)
        return
    }
}

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

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

使用默认配置
func DefaultClient() {
    builder := easy_http.NewClientBuilder()
    client, err := builder.Build()
    if err != nil {
        fmt.Println(err)
        return
    }
    client.Get("http://baidu.com")
}

这样同样是可以的

easy 函数 使用

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

func EasyFunction() {

    url := "http://baidu.com"

    //合成http get的url和参数 
    values := make(map[string]string)
    values["v"] = "123456"
    easy_http.EasyGet(url, values)

    //构造cookie
    cookie := make(map[string]string)
    cookie["name"] = "value"
    easy_http.EasyCookie(cookie)

    //合成 http post 的参数
    easy_http.EasyPost(values)

    //构造 上传文件的multipart
    multipartBuilder := easy_http.NewMultipartBuilder()
    multipartBuilder.AddFile("file1","D:\\a.txt")
    multipartBuilder.AddFromDate("name","value")
    multipartBuilder.AddBytes("name2",[]byte("aaaaa"))
    multipart, err := multipartBuilder.Builder()
    
}
异步回调使用

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


func Call(response easy_http.IResponse) {
    fmt.Println(response.Error())
    fmt.Println(response.StatusCode())
    fmt.Println(string(response.Content()))
}

type Get struct {
}

func (g Get) EasyResponseCallback(response easy_http.IResponse) {
    fmt.Println(response.Error())
    fmt.Println(response.StatusCode())
    fmt.Println(string(response.Content()))
}

func AsynchronousRequest() {
    url := "http://baidu.com"
    client, err := easy_http.NewClientBuilder().Build()
    if err != nil {
        fmt.Println(err)
        return
    }

    //函数异步回调
    client.GetAsyn(url, Call)

    //接口异步回调
    client.GetAsynWithCallback(url, &Get{})
}
自定义请求

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

func Call(response easy_http.IResponse) {
    fmt.Println(response.Error())
    fmt.Println(response.StatusCode())
    fmt.Println(string(response.Content()))
}

func CustomizeRequest() {
    url := "http://baidu.com"
    client, err := easy_http.NewClientBuilder().Build()
    if err != nil {
        fmt.Println(err)
        return
    }
    response := client.SendWithMethod(url, http.MethodPut, nil, func(request *http.Request) {
        //修改Request
    })
    fmt.Println(response.Error())
    fmt.Println(response.StatusCode())

    //异步方式
    client.SendWithMethodCallBack(url, http.MethodPut, nil, func(request *http.Request) {
        //习惯Request
    }, Call)
}
使用go http默认的函数请求

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

func Primitive() {
    url := "http://baidu.com"
    client, err := easy_http.NewClientBuilder().Build()
    if err != nil {
        fmt.Println(err)
        return
    }
    //获取Request
    request, err := http.NewRequest(http.MethodGet, url, nil)
    if err != nil {
        fmt.Println(err)
        return
    }
    //得到http的原生Response
    response, err := client.DoRequest(request)
    if err != nil {
        fmt.Println(err)
        return
    }
    fmt.Println(response)
}
自定义Response

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

type MyResponse struct {
}

func (m MyResponse) Error() error {
    return nil
}

func (m MyResponse) StatusCode() int {
    return 0
}

func (m MyResponse) Header() http.Header {
    return nil
}

func (m MyResponse) ContentLength() int64 {
    return 0
}

func (m MyResponse) Content() []byte {
    return nil
}

func (m MyResponse) Resp() *http.Response {
    return nil
}

func (m MyResponse) Request() *http.Request {
    return nil
}

func (m MyResponse) Cookie(name string) *http.Cookie {
    return nil
}

//构造HTTP response的函数
func MyBuildResponse(resp *http.Response, err error) easy_http.IResponse {
    response := new(MyResponse)
    //做处理
    return response
}
func CustomizeResponse() {
    client, err := easy_http.NewClientBuilder().
        BuildResponse(MyBuildResponse).
        Build()
    if err != nil {
        fmt.Println(err)
        return
    }
}

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

最后

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

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

上一篇下一篇

猜你喜欢

热点阅读