From de94805d34bdfe846de1b6d7dfbaa85baa868bdf Mon Sep 17 00:00:00 2001 From: dorlolo <428192774@qq.com> Date: Sun, 13 Mar 2022 21:24:29 +0800 Subject: [PATCH] first commit --- .idea/.gitignore | 8 ++ .idea/modules.xml | 8 ++ .idea/simpleRequest.iml | 9 ++ .idea/vcs.xml | 6 + CHANGELOG.MD | 2 + README.MD | 174 ++++++++++++++++++++++++++++ body.go | 31 +++++ go.mod | 3 + headers.go | 161 ++++++++++++++++++++++++++ param.go | 36 ++++++ simpleRequest.go | 226 +++++++++++++++++++++++++++++++++++++ test/simpleRequest_test.go | 48 ++++++++ 12 files changed, 712 insertions(+) create mode 100644 .idea/.gitignore create mode 100644 .idea/modules.xml create mode 100644 .idea/simpleRequest.iml create mode 100644 .idea/vcs.xml create mode 100644 CHANGELOG.MD create mode 100644 README.MD create mode 100644 body.go create mode 100644 go.mod create mode 100644 headers.go create mode 100644 param.go create mode 100644 simpleRequest.go create mode 100644 test/simpleRequest_test.go diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..8e5f925 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/simpleRequest.iml b/.idea/simpleRequest.iml new file mode 100644 index 0000000..5e764c4 --- /dev/null +++ b/.idea/simpleRequest.iml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/CHANGELOG.MD b/CHANGELOG.MD new file mode 100644 index 0000000..154a5df --- /dev/null +++ b/CHANGELOG.MD @@ -0,0 +1,2 @@ +v1.0.1 完成请求后,可以获取request and respnse +v1.0.0 完成v2方法,使https请求更简单 \ No newline at end of file diff --git a/README.MD b/README.MD new file mode 100644 index 0000000..36664ff --- /dev/null +++ b/README.MD @@ -0,0 +1,174 @@ +# simpleRequest -- 基于http库封装的request请求方案 +## 特点 +适用于基于http协议的iot数据采集。 功能简介、易于上手。只要了解postman工具,就能使用这个库。极大地减少了代码量。 + +## 如何使用? + +### 模块导入 + +```go +import simpleReuqest2 "go-simple/simpleRequest/v2" +``` + +### 实例化 + +```go +var r = simpleReuqest2.NewRequest() +``` + +### 添加请求头 + +#### 单个赋值 +```go +r.Headers().Set("token", "d+jfdji*D%1=") +r.Headers().Set("Content-Type", "application/json") +``` + +#### map赋值 +```go +mapHeaders:= map[string]string{ + "token": "d+jfdji*D%1=", + "Content-Type": "application/json", +} +r.Headers().Sets(mapHeaders) +``` + +#### 链式赋值 +```go +r.Headers().Set("token", "d+jfdji*D%1=").Set("Content-Type", "application/json") +``` +#### 使用预设的key +```go +r.Headers().SetConentLength("2") +//r.Headers().Set("Content-Length", "2") + +r.Headers().SetConentEncoding("gzip, deflate, br") +//r.Headers().Set("Content-Encoding", "gzip, deflate, br") + +r.Headers().SetUserAgent("Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.163 Safari/535.1"") +//r.Headers().Set("User-Agent",Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.163 Safari/535.1") +``` +#### 使用预设的key-value +```go +//随机user-agent +r.Headers().SetRandomUerAgent() +//r.Headers().Set("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.163 Safari/535.1") + +r.Headers().ConentType_json() +//r.Headers().Set("Content-Type", "application/json") + +r.Headers()ConentType_formData() +//r.Headers().Set("Content-Type","multipart/form-data") + +r.Headers()ConentType_formUrlencoded() +//r.Headers().Set("Content-Type","application/x-www-form-urlencoded") + +r.Headers()ConentType_textPlain() +//r.Headers().Set("Content-Type","text/plain; charset=utf-8") +``` + +### 添加queryParams +#### 单个赋值 +```go +r.QueryParams().Set("user", "dorlolo") +``` +#### map赋值 +不会覆盖上面之前填充过的参数 +```go +pamarsBulid := make(map[string]interface{}) +pamarsBulid["passwd"] = "123456" +pamarsBulid["action"] = "login" +r.QueryParams().Sets(pamarsBulid) +``` + +#### 链式赋值 +```go +r.QueryParams().Set("user", "dorlolo").Set("passwd","123456") +``` + +#### 获取url.Values对象进行赋值 +对象类型为`*url.Values`,取到地址后,可以使用`url.Values`中的方法继续进行赋值 +```go +qpData:=r.QueryParams().Gets() +qpData.Add("age","18") +``` + +### 添加请求体body + +#### 单个赋值 +```go +r.Body().Set("beginDate", "2022-03-01").Set("endDate", "2022-03-03") + +``` + +#### map赋值 +```go +bodyBulid := map[string]interface{ + "beginDate":"2022-03-01", + "endDate":"2022-03-03", +} +r.Body().Sets(bodyBulid) +``` + +#### 链式赋值 +```go +r.Body().Set("beginDate", "2022-03-01").Set("endDate", "2022-03-03") +``` + +#### 字符串赋值 +通过此方法直接赋值json数据 +```go +bodydata:=`{"devSn":"230000000008","type":"day"}` +r.Body().SetString(bodydata) +``` + +### 其它请求参数 + +#### 设置超时时间 +```go +r.TimeOut(time.Second * 30) +``` + +#### 跳过证书验证 +```go +r.SkipCertVerify() +``` + +### 发送请求 +#### post请求 +```go +res, err :=r.Post("https://127.0.0.1:80/excample") +if err != nil { + ftm.Println( "error occured", err) +} else { + fmt.Println(res) +} +``` + +#### get请求 +```go +res, err :=r.Get("https://127.0.0.1:80/excample") +if err != nil { +ftm.Println( "error occured", err) +} else { +fmt.Println(res) +} +``` +#### 其它请求 +后续支持...敬请期待 + + +### 获取上下文 +请注意,需要完成请求后才能获得上下文数据! +#### 获取请求的上下文 +```go +requestContext:=r.Request +``` + +#### 获取返回的上下文 +```go +responseContext:=r.Response +``` + +## 使用示例 +[simpleRequest_test.go](./test/simpleRequest_test.go) \ No newline at end of file diff --git a/body.go b/body.go new file mode 100644 index 0000000..faaa11a --- /dev/null +++ b/body.go @@ -0,0 +1,31 @@ +/* + * @FileName: body.go + * @Author: JuneXu + * @CreateTime: 2022/3/2 上午1:23 + * @Description: + */ + +package simpleRequest + +var ( + stringBodyType = "__STRING_BODY__" +) + +type BodyConf struct { + simpleReq *SimpleRequest +} + +func (s *BodyConf) Set(key string, value interface{}) *BodyConf { + s.simpleReq.tempBody[key] = value + return s +} +func (s *BodyConf) Sets(data map[string]interface{}) *BodyConf { + for k, v := range data { + s.simpleReq.tempBody[k] = v + } + return s +} +func (s *BodyConf) SetString(strData string) *BodyConf { + s.simpleReq.tempBody[stringBodyType] = strData + return s +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..7fae1aa --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module github.com/dorlolo/simpleRequest + +go 1.17 diff --git a/headers.go b/headers.go new file mode 100644 index 0000000..11acb49 --- /dev/null +++ b/headers.go @@ -0,0 +1,161 @@ +/* + * @FileName: header.go + * @Author: JuneXu + * @CreateTime: 2022/3/1 下午9:44 + * @Description: + */ + +package simpleRequest + +import ( + "bytes" + "encoding/json" + "math/rand" + "net/http" + "regexp" + "sync" + "time" +) + +var ( + hdrUserAgentKey = http.CanonicalHeaderKey("User-Agent") + hdrAcceptKey = http.CanonicalHeaderKey("Accept") + hdrContentTypeKey = http.CanonicalHeaderKey("Content-Type") + hdrContentLengthKey = http.CanonicalHeaderKey("Content-Length") + hdrContentEncodingKey = http.CanonicalHeaderKey("Content-Encoding") + hdrLocationKey = http.CanonicalHeaderKey("Location") + + plainTextType = "text/plain; charset=utf-8" + jsonContentType = "application/json" + formUrlencodedType = "application/x-www-form-urlencoded" + formDataType = "multipart/form-data" + xmlDataType = "application/xml" + textPlainType = "text/plain" + javaScriptType = "javascript" + + jsonCheck = regexp.MustCompile(`(?i:(application|text)/(json|.*\+json|json\-.*)(;|$))`) + xmlCheck = regexp.MustCompile(`(?i:(application|text)/(xml|.*\+xml)(;|$))`) + bufPool = &sync.Pool{New: func() interface{} { return &bytes.Buffer{} }} +) + +var userAgentList = [...]string{ + "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0;", + "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; InfoPath.2; .NET4.0C; .NET4.0E; .NET CLR 2.0.50727; 360SE)", + "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.163 Safari/535.1", +} + +type HeadersConf struct { + simpleReq *SimpleRequest +} + +//------------------------------------------------------------- +// Common key settings + +//batch settings +func (s *HeadersConf) Sets(headers map[string]string) *HeadersConf { + for k, v := range headers { + s.simpleReq.headers.Set(k, v) + } + return s +} + +//single setting +func (s *HeadersConf) Set(header, value string) *HeadersConf { + s.simpleReq.headers.Set(header, value) + return s +} + +func (s *HeadersConf) Add(header, value string) *HeadersConf { + s.simpleReq.headers.Add(header, value) + return s +} + +//一般用不到 +//func (s *HeadersConf) Values(keys string) *HeadersConf { +// s.simpleReq.headers.Values(keys) +// return s +//} + +// SetHeaderMultiValues 支持多值传入,一般用不到 +//func (s *HeadersConf) SetMultiValues(headers map[string][]string) *HeadersConf { +// for key, values := range headers { +// s.simpleReq.headers.Set(key, strings.Join(values, ", ")) +// } +// return s +//} + +//------------------------------------------------------------- +// base Key settings +func (s *HeadersConf) SetUserAgent(value string) *HeadersConf { + s.simpleReq.headers.Set(hdrUserAgentKey, value) + return s +} + +//set ContentType-------------------------------------------------- +//func (s *HeadersConf) SetConentType(value string) *HeadersConf { +// s.simpleReq.headers.Set(hdrContentTypeKey, value) +// return s +//} + +func (s *HeadersConf) ConentType_json() *HeadersConf { + jsonData, err := json.Marshal(s.simpleReq.tempBody) + if err == nil { + s.simpleReq.body = bytes.NewReader(jsonData) + } + s.simpleReq.body = bytes.NewReader(jsonData) + s.simpleReq.headers.Set(hdrContentTypeKey, jsonContentType) + return s +} + +func (s *HeadersConf) ConentType_formData() *HeadersConf { + //tmp := url.Values{} + + //for k, v := range s.simpleReq.tempBody { + // tmp.Add(k, fmt.Sprintf("%v", v)) + //} + s.simpleReq.headers.Set(hdrContentTypeKey, formDataType) + return s +} +func (s *HeadersConf) ConentType_formUrlencoded() *HeadersConf { + s.simpleReq.headers.Set(hdrContentTypeKey, formUrlencodedType) + return s +} +func (s *HeadersConf) ConentType_textPlain() *HeadersConf { + s.simpleReq.headers.Set(hdrContentTypeKey, plainTextType) + return s +} + +// +func (s *HeadersConf) SetConentLength(value string) *HeadersConf { + s.simpleReq.headers.Set(hdrContentLengthKey, value) + return s +} +func (s *HeadersConf) SetConentEncoding(value string) *HeadersConf { + s.simpleReq.headers.Set(hdrContentEncodingKey, value) + return s +} +func (s *HeadersConf) SetConentLocation(value string) *HeadersConf { + s.simpleReq.headers.Set(hdrLocationKey, value) + return s +} + +//------------------------------------------------------------- +// Extended settings +//随机请求头的User-Agent参数 +func (s *HeadersConf) getRandomUerAgent() string { + rand.Seed(time.Now().UnixNano()) + index := rand.Intn(len(userAgentList)) + return userAgentList[index] +} + +//设置为随机 User-Agent +func (s *HeadersConf) SetRandomUerAgent() *HeadersConf { + s.simpleReq.headers.Set(hdrUserAgentKey, s.getRandomUerAgent()) + return s +} + +//set Authorization +func (s *HeadersConf) SetAuthorization(value string) *HeadersConf { + s.simpleReq.headers.Set("Authorization", value) + return s +} diff --git a/param.go b/param.go new file mode 100644 index 0000000..d7e9581 --- /dev/null +++ b/param.go @@ -0,0 +1,36 @@ +/* + * @FileName: param.go + * @Author: JuneXu + * @CreateTime: 2022/3/1 下午9:07 + * @Description: + */ + +package simpleRequest + +import ( + "fmt" + "net/url" +) + +type QueryParams struct { + simpleReq *SimpleRequest +} + +//batch settings +func (s *QueryParams) Sets(data map[string]interface{}) *QueryParams { + for k, v := range data { + s.simpleReq.queryParams.Set(k, fmt.Sprintf("%v", v)) + } + return s +} + +//single settings +func (s *QueryParams) Set(key string, value interface{}) *QueryParams { + s.simpleReq.queryParams.Set(key, fmt.Sprintf("%v", value)) + return s +} + +//get all queryParams +func (s *QueryParams) Gets() *url.Values { + return &s.simpleReq.queryParams +} diff --git a/simpleRequest.go b/simpleRequest.go new file mode 100644 index 0000000..31a0579 --- /dev/null +++ b/simpleRequest.go @@ -0,0 +1,226 @@ +/* + * @FileName: simpleRequest.go + * @Author: JuneXu + * @CreateTime: 2022/3/2 上午12:33 + * @Description: + */ + +package simpleRequest + +import ( + "bytes" + "crypto/tls" + "encoding/json" + "fmt" + "io" + "io/ioutil" + "net/http" + "net/url" + "strings" + "time" +) + +func NewRequest() *SimpleRequest { + var ( + hd = http.Header{} + qp = url.Values{} + ) + + return &SimpleRequest{ + //headers: make(map[string]string), + //cookies: make(map[string]string), + timeout: time.Second * 7, + queryParams: qp, + headers: hd, + } +} + +type SimpleRequest struct { + url string + queryParams url.Values + body io.Reader + headers http.Header + transport *http.Transport + + tempBody map[string]interface{} + timeout time.Duration + + Response http.Response //用于获取完整的返回内容。请注意要在请求之后才能获取 + Request http.Request //用于获取完整的请求内容。请注意要在请求之后才能获取 + //cookies map[string]string + //data interface{} + //cli *http.Client + //debug bool + //method string + //time int64 + //disableKeepAlives bool + //tlsClientConfig *tls.Config + //jar http.CookieJar + //proxy func(*http.Request) (*url.URL, error) + //checkRedirect func(req *http.Request, via []*http.Request) error +} + +func (s *SimpleRequest) NewRequest() *SimpleRequest { + var qp = url.Values{} + return &SimpleRequest{ + //headers: make(map[string]string), + //cookies: make(map[string]string), + timeout: time.Second * 7, + queryParams: qp, + } +} + +//------------------------------------------------------ +// +// 数据准备 +// +func (s *SimpleRequest) Headers() *HeadersConf { + return &HeadersConf{ + simpleReq: s, + } +} +func (s *SimpleRequest) Body() *BodyConf { + return &BodyConf{ + simpleReq: s, + } +} + +func (s *SimpleRequest) QueryParams() *QueryParams { + return &QueryParams{ + simpleReq: s, + } +} + +//跳过证书验证 +func (s *SimpleRequest) SkipCertVerify() *SimpleRequest { + + s.transport = &http.Transport{ + TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, + } + return s +} + +//设置超时时间 +func (s *SimpleRequest) TimeOut(t time.Duration) *SimpleRequest { + s.timeout = t + return s +} + +//------------------------------------------------------ +// +// 发送请求 +// +//发送postt请求 +func (s *SimpleRequest) do(request *http.Request) (body []byte, err error) { + //3. 建立http客户端 + client := &http.Client{ + Timeout: s.timeout, + } + if s.transport != nil { + client.Transport = s.transport + } + //3.1 发送数据 + //todo resp的上下文返回一下 + resp, err := client.Do(request) + if err != nil { + fmt.Println("error:", err.Error()) + } + + //v1.0.1更新,将request和response内容返回,便于用户进行分析 JuneXu 03-11-2022 + s.Response = *resp + s.Request = *request + defer resp.Body.Close() + //3.2 获取数据 + body, err = ioutil.ReadAll(resp.Body) + return +} + +func (s *SimpleRequest) Post(urls string) (body []byte, err error) { + s.initBody() + r, err := http.NewRequest(http.MethodPost, urls, s.body) + if err != nil { + return nil, err + } + //headers + for k := range s.headers { + s.headers.Del(k) + r.Header[k] = append(s.headers[k], s.headers[k]...) + } + + //queryParams + r.URL.RawQuery = s.queryParams.Encode() + + body, err = s.do(r) + + return +} + +func (s *SimpleRequest) Get(urls string) (body []byte, err error) { + // body + s.initBody() + r, err := http.NewRequest(http.MethodGet, urls, s.body) + if err != nil { + return nil, err + } + //headers + for k := range s.headers { + s.headers.Del(k) + r.Header[k] = append(s.headers[k], s.headers[k]...) + } + //queryParams + r.URL.RawQuery = s.queryParams.Encode() + + body, err = s.do(r) + return +} + +// Put method does PUT HTTP request. It's defined in section 4.3.4 of RFC7231. +//func (s *SimpleRequest) Put(url string) (*Response, error) { +// return r.Execute(MethodPut, url) +//} + +// Delete method does DELETE HTTP request. It's defined in section 4.3.5 of RFC7231. +//func (s *SimpleRequest) Delete(url string) (*Response, error) { +// return r.Execute(MethodDelete, url) +//} + +// Options method does OPTIONS HTTP request. It's defined in section 4.3.7 of RFC7231. +//func (s *SimpleRequest) Options(url string) (*Response, error) { +// return r.Execute(MethodOptions, url) +//} + +// Patch method does PATCH HTTP request. It's defined in section 2 of RFC5789. +//func (s *SimpleRequest) Patch(url string) (*Response, error) { +// return r.Execute(MethodPatch, url) +//} +//------------------------------------------------------ +// +// 这里数据 +// +func (s *SimpleRequest) initBody() { + contentTypeData := s.headers.Get(hdrContentTypeKey) + switch { + case contentTypeData == jsonContentType: + jsonData, err := json.Marshal(s.tempBody) + if err == nil { + s.body = bytes.NewReader(jsonData) + } + s.body = bytes.NewReader(jsonData) + case contentTypeData == xmlDataType || contentTypeData == textPlainType || contentTypeData == javaScriptType: + data, _ := s.tempBody[stringBodyType].(string) + s.body = strings.NewReader(data) + case contentTypeData == "": + tmpData := url.Values{} + for k, v := range tmpData { + tmpData.Set(k, fmt.Sprintf("%v", v)) + } + s.body = strings.NewReader(tmpData.Encode()) + s.Headers().ConentType_formUrlencoded() + default: //x-www-form-urlencoded ,multipart/form-data .. + tmpData := url.Values{} + for k, v := range tmpData { + tmpData.Set(k, fmt.Sprintf("%v", v)) + } + s.body = strings.NewReader(tmpData.Encode()) + } +} diff --git a/test/simpleRequest_test.go b/test/simpleRequest_test.go new file mode 100644 index 0000000..d8dff20 --- /dev/null +++ b/test/simpleRequest_test.go @@ -0,0 +1,48 @@ +/* + * @FileName: simpleRequest_test.go + * @Author: JuneXu + * @CreateTime: 2022/3/3 下午11:34 + * @Description: + */ + +package test + +import ( + "fmt" + "github.com/dorlolo/simpleRequest" + + "testing" + "time" +) + +func TestRequest(t *testing.T) { + var r = simpleRequest.NewRequest() + //---设置请求头 + r.Headers().Set("token", "d+jfdji*D%1=") + //串联使用示例:设置Conent-Type为applicaiton/json 并且 随机user-agent + r.Headers().ConentType_json().SetRandomUerAgent() + + //设置params + r.QueryParams().Set("user", "dorlolo") + //支持一次性添加,不会覆盖上面user + pamarsBulid := make(map[string]interface{}) + pamarsBulid["passwd"] = "123456" + pamarsBulid["action"] = "login" + r.QueryParams().Sets(pamarsBulid) + + //--添加body + r.Body().Set("beginDate", "2022-03-01").Set("endDate", "2022-03-03") + + //--其它请求参数 + r.TimeOut(time.Second * 30) //请求超时,默认7秒 + r.SkipCertVerify() //跳过证书验证 + + //--发送请求,这里返回的直接是body中的数据,等后续增加功能 + res, err := r.Get("www.webSite.com/end/point") + if err != nil { + t.Error(err) + } else { + fmt.Println(res) + } + +}