golang造轮子,封装一个简单的http client
近来无事,本着爱折腾的原则,在go原生 http client 的基础上,自己封装了一个go的http client。由于才疏学浅,再加是第一次造轮子,在各位大佬面前献丑了,写的烂的地方,请轻喷。还请各位不吝赐教。
先放地址
gethub: https://github.com/bruce12397/easy_http
Gitee: https://gitee.com/bruce_le/easy_http
简单介绍一下功能
- 使用 构造器模式,提供了链式调用和方便使用的接口
- 支持https自定义服务器证书校验和双向证书校验
- 支持代理,可以方便的设置代理
- 封装了multipart 协议, 可以方便的上传文件
- 具有很强的拓展性,可以在基础上非常方便的定制自己http请求
- 支持http的 返回结果 异步回调
- 可以方便的自定义Response
安装库
可以使用github的库,也可使用Gitee的库,两个库的代码都是一样的,因为github网速的原因,所以在gitee上也传了一份
-
github:
go get -u github.com/bruce12397/easy_http
-
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)
设置就可以了
最后
整个库的基本功能就是这些了。第一造轮子,写的很烂。写这篇文章时,还发现了好几个因为首字母小写导致的问题。
有问题的地方,还请不吝赐教