golang造輪子,封裝一個簡單的http client | 🏆 技術專題第二期徵文

近來無事,本着愛折騰的原則,在go原生 http client 的基礎上,本身封裝了一個go的http client。因爲才疏學淺,再加是第一次造輪子,在各位大佬面前獻醜了,寫的爛的地方,請輕噴。還請各位不吝賜教。git

先放地址github

gethub: github.com/bruce12397/…web

Gitee: gitee.com/bruce_le/ea…服務器

簡單介紹一下功能

  1. 使用 構造器模式,提供了鏈式調用和方便使用的接口
  2. 支持https自定義服務器證書校驗和雙向證書校驗
  3. 支持代理,能夠方便的設置代理
  4. 封裝了multipart 協議, 能夠方便的上傳文件
  5. 具備很強的拓展性,能夠在基礎上很是方便的定製本身http請求
  6. 支持http的 返回結果 異步回調
  7. 能夠方便的自定義Response

安裝庫

可使用github的庫,也可以使用Gitee的庫,兩個庫的代碼都是同樣的,由於github網速的緣由,因此在gitee上也傳了一份markdown

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

  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的客戶端oop

固然,上面的例子是設置了全部配置的,也能夠所有使用默認配置post

使用默認配置
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)設置就能夠了

最後

整個庫的基本功能就是這些了。第一造輪子,寫的很爛。寫這篇文章時,還發現了好幾個由於首字母小寫致使的問題。

有問題的地方,還請不吝賜教

相關文章
相關標籤/搜索