commit de94805d34bdfe846de1b6d7dfbaa85baa868bdf Author: dorlolo <428192774@qq.com> Date: Sun Mar 13 21:24:29 2022 +0800 first commit 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) + } + +}