From f0327d0c931a2d343b772d95d3b8c6d104c3165c Mon Sep 17 00:00:00 2001 From: = <428192774@qq.com> Date: Sat, 10 Dec 2022 02:06:12 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9Ebodyentry=E8=A7=A3=E6=9E=90?= =?UTF-8?q?=E6=A8=A1=E5=9D=97=EF=BC=8C=E5=8F=AF=E8=87=AA=E5=AE=9A=E4=B9=89?= =?UTF-8?q?=E8=A7=A3=E6=9E=90=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.MD | 4 +- body.go | 37 ++++++++-- excample/simpleRequest_test.go | 2 +- go.mod | 2 +- headers.go | 10 +-- options.go | 17 +++++ param.go | 4 +- parser.go | 111 ++++++++++++++++++++++++++++++ simpleRequest.go | 122 ++++++++++++++++++--------------- simpleRequest_test.go | 2 +- 10 files changed, 232 insertions(+), 79 deletions(-) create mode 100644 options.go create mode 100644 parser.go diff --git a/README.MD b/README.MD index 78f45f6..158af9f 100644 --- a/README.MD +++ b/README.MD @@ -90,7 +90,7 @@ r.QueryParams().Set("user", "dorlolo") #### 2.4.2 map赋值 不会覆盖上面之前填充过的参数 ```go -pamarsBulid := make(map[string]interface{}) +pamarsBulid := make(map[string]any) pamarsBulid["passwd"] = "123456" pamarsBulid["action"] = "login" r.QueryParams().Sets(pamarsBulid) @@ -118,7 +118,7 @@ r.Body().Set("beginDate", "2022-03-01").Set("endDate", "2022-03-03") #### 2.5.2 map赋值 ```go -bodyBulid := map[string]interface{}{ +bodyBulid := map[string]any{ "beginDate":"2022-03-01", "endDate":"2022-03-03", } diff --git a/body.go b/body.go index b3397f9..cc60aed 100644 --- a/body.go +++ b/body.go @@ -7,25 +7,48 @@ package simpleRequest -var ( - stringBodyType = "__STRING_BODY__" +type EntryMark string + +func (b EntryMark) string() string { + return string(b) +} + +const ( + StringEntryType EntryMark = "__STRING_ENTRY__" + BytesEntryType EntryMark = "__BYTES_ENTRY__" + ModelEntryType EntryMark = "__MODEL_ENTRY__" + MapEntryType EntryMark = "__MAP_ENTRY__" ) type BodyConf struct { simpleReq *SimpleRequest } -func (s *BodyConf) Set(key string, value interface{}) *BodyConf { - s.simpleReq.tempBody[key] = value +func (s *BodyConf) Set(key string, value any) *BodyConf { + s.simpleReq.BodyEntries[key] = value return s } -func (s *BodyConf) Sets(data map[string]interface{}) *BodyConf { +func (s *BodyConf) Sets(data map[string]any) *BodyConf { + s.simpleReq.BodyEntryMark = MapEntryType for k, v := range data { - s.simpleReq.tempBody[k] = v + s.simpleReq.BodyEntries[k] = v } return s } func (s *BodyConf) SetString(strData string) *BodyConf { - s.simpleReq.tempBody[stringBodyType] = strData + s.simpleReq.BodyEntryMark = StringEntryType + s.simpleReq.BodyEntries[StringEntryType.string()] = strData + return s +} + +func (s *BodyConf) SetBytes(byteData []byte) *BodyConf { + s.simpleReq.BodyEntryMark = BytesEntryType + s.simpleReq.BodyEntries[BytesEntryType.string()] = byteData + return s +} + +func (s *BodyConf) SetModel(model any) *BodyConf { + s.simpleReq.BodyEntryMark = ModelEntryType + s.simpleReq.BodyEntries[ModelEntryType.string()] = model return s } diff --git a/excample/simpleRequest_test.go b/excample/simpleRequest_test.go index 101390f..fca8b2d 100644 --- a/excample/simpleRequest_test.go +++ b/excample/simpleRequest_test.go @@ -26,7 +26,7 @@ func TestRequest(t *testing.T) { //设置params r.QueryParams().Set("user", "dorlolo") //批量添加,不会覆盖上面user - pamarsBulid := map[string]interface{}{ + pamarsBulid := map[string]any{ "passwd": "123456", "action": "login", } diff --git a/go.mod b/go.mod index 7fae1aa..9bdd457 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,3 @@ module github.com/dorlolo/simpleRequest -go 1.17 +go 1.18 diff --git a/headers.go b/headers.go index 2dd0247..567ffeb 100644 --- a/headers.go +++ b/headers.go @@ -9,7 +9,6 @@ package simpleRequest import ( "bytes" - "encoding/json" "math/rand" "net/http" "regexp" @@ -36,7 +35,7 @@ var ( 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{} }} + bufPool = &sync.Pool{New: func() any { return &bytes.Buffer{} }} ) var userAgentList = [...]string{ @@ -101,11 +100,6 @@ func (s *HeadersConf) SetConentType(value string) *HeadersConf { } func (s *HeadersConf) ConentType_json() *HeadersConf { - jsonData, err := json.Marshal(s.simpleReq.tempBody) - if err == nil { - s.simpleReq.body = bytes.NewReader([]byte("{}")) - } - s.simpleReq.body = bytes.NewReader(jsonData) s.simpleReq.headers.Set(hdrContentTypeKey, jsonContentType) return s } @@ -118,7 +112,7 @@ func (s *HeadersConf) ConentType_charsetUtf8() *HeadersConf { func (s *HeadersConf) ConentType_formData() *HeadersConf { //tmp := url.Values{} - //for k, v := range s.simpleReq.tempBody { + //for k, v := range s.simpleReq.BodyEntry { // tmp.Add(k, fmt.Sprintf("%v", v)) //} s.simpleReq.headers.Set(hdrContentTypeKey, formDataType) diff --git a/options.go b/options.go new file mode 100644 index 0000000..8a2becc --- /dev/null +++ b/options.go @@ -0,0 +1,17 @@ +// Package simpleRequest ----------------------------- +// @file : options.go +// @author : JJXu +// @contact : wavingBear@163.com +// @time : 2022/12/10 01:45:37 +// ------------------------------------------- +package simpleRequest + +type OPTION func(r *SimpleRequest) *SimpleRequest + +//OptionNewBodyEntryParser 新增或覆盖BodyEntryParser +func OptionNewBodyEntryParser(contentType string, parser IBodyEntryParser) OPTION { + return func(r *SimpleRequest) *SimpleRequest { + r.bodyEntryParsers[contentType] = parser + return r + } +} diff --git a/param.go b/param.go index 551a6d2..6e8425f 100644 --- a/param.go +++ b/param.go @@ -17,7 +17,7 @@ type QueryParams struct { } //batch settings -func (s *QueryParams) Sets(data map[string]interface{}) *QueryParams { +func (s *QueryParams) Sets(data map[string]any) *QueryParams { for k, v := range data { s.simpleReq.queryParams.Set(k, fmt.Sprintf("%v", v)) } @@ -25,7 +25,7 @@ func (s *QueryParams) Sets(data map[string]interface{}) *QueryParams { } //single settings -func (s *QueryParams) Set(key string, value interface{}) *QueryParams { +func (s *QueryParams) Set(key string, value any) *QueryParams { s.simpleReq.queryParams.Set(key, fmt.Sprintf("%v", value)) return s } diff --git a/parser.go b/parser.go new file mode 100644 index 0000000..b35b2a3 --- /dev/null +++ b/parser.go @@ -0,0 +1,111 @@ +// Package simpleRequest ----------------------------- +// @file : parser.go +// @author : JJXu +// @contact : wavingBear@163.com +// @time : 2022/12/10 00:48:45 +// ------------------------------------------- +package simpleRequest + +import ( + "bytes" + "encoding/json" + "io" + "mime/multipart" + "strings" +) + +var bodyEntryParsers = map[string]IBodyEntryParser{ + jsonContentType: new(JsonParser), + formDataType: new(FormDataParser), +} + +type IBodyEntryParser interface { + Unmarshal(bodyType EntryMark, BodyEntry map[string]any) io.Reader +} + +type JsonParser struct{} + +func (JsonParser) Unmarshal(bodyType EntryMark, BodyEntry map[string]any) io.Reader { + switch bodyType { + case StringEntryType: + return strings.NewReader(BodyEntry[StringEntryType.string()].(string)) + case BytesEntryType: + return bytes.NewReader(BodyEntry[BytesEntryType.string()].([]byte)) + case ModelEntryType: + jsonData, err := json.Marshal(BodyEntry) + if err == nil { + return bytes.NewReader(jsonData) + } else { + return strings.NewReader("{}") + } + case MapEntryType: + jsonData, err := json.Marshal(BodyEntry) + if err == nil { + return bytes.NewReader(jsonData) + } else { + return strings.NewReader("{}") + } + default: + if len(BodyEntry) > 0 { + jsonData, err := json.Marshal(BodyEntry) + if err == nil { + return bytes.NewReader(jsonData) + } + } + return strings.NewReader("{}") + } +} + +type FormDataParser struct { + ContentType string +} + +func (f *FormDataParser) Unmarshal(bodyType EntryMark, BodyEntry map[string]any) (body io.Reader) { + switch bodyType { + case MapEntryType: + body, f.ContentType = multipartCommonParse(BodyEntry) + case ModelEntryType: + tb := BodyEntry[ModelEntryType.string()] + buffer, err := json.Marshal(tb) + if err != nil { + panic(err.Error()) + } + var mapper map[string]any + err = json.Unmarshal(buffer, &mapper) + if err != nil { + panic(err.Error()) + } + body, f.ContentType = multipartCommonParse(mapper) + case StringEntryType: + f.ContentType = formDataType + return strings.NewReader(BodyEntry[StringEntryType.string()].(string)) + case BytesEntryType: + f.ContentType = formDataType + return bytes.NewReader(BodyEntry[StringEntryType.string()].([]byte)) + default: + body, f.ContentType = multipartCommonParse(BodyEntry) + } + f.ContentType = formDataType + return nil +} +func multipartCommonParse(BodyEntry map[string]any) (reader io.Reader, contentType string) { + body := &bytes.Buffer{} + writer := multipart.NewWriter(body) + for k, sv := range BodyEntry { + switch sv.(type) { + case string: + strSv, _ := sv.(string) + _ = writer.WriteField(k, strSv) + case []string: + sss, _ := sv.([]string) + for _, v := range sss { + _ = writer.WriteField(k, v) + } + } + } + err := writer.Close() + if err != nil { + panic(err) + } + return body, writer.FormDataContentType() +} diff --git a/simpleRequest.go b/simpleRequest.go index 4eab00e..b47b9ef 100644 --- a/simpleRequest.go +++ b/simpleRequest.go @@ -8,33 +8,37 @@ package simpleRequest import ( - "bytes" "crypto/tls" - "encoding/json" "fmt" "io" "io/ioutil" - "mime/multipart" "net/http" "net/url" "strings" "time" ) -func NewRequest() *SimpleRequest { +func NewRequest(opts ...OPTION) *SimpleRequest { var ( hd = http.Header{} qp = url.Values{} ) - return &SimpleRequest{ + var r = &SimpleRequest{ //headers: make(map[string]string), //cookies: make(map[string]string), - timeout: time.Second * 7, - queryParams: qp, - headers: hd, - tempBody: make(map[string]interface{}), + timeout: time.Second * 7, + queryParams: qp, + headers: hd, + BodyEntries: make(map[string]any), + bodyEntryParsers: bodyEntryParsers, } + if len(opts) > 0 { + for _, o := range opts { + r = o(r) + } + } + return r } type SimpleRequest struct { @@ -44,13 +48,16 @@ type SimpleRequest struct { headers http.Header transport *http.Transport - tempBody map[string]interface{} - timeout time.Duration + BodyEntryMark EntryMark + BodyEntries map[string]any + bodyEntryParsers map[string]IBodyEntryParser + + timeout time.Duration Response http.Response //用于获取完整的返回内容。请注意要在请求之后才能获取 Request http.Request //用于获取完整的请求内容。请注意要在请求之后才能获取 //cookies map[string]string - //data interface{} + //data any //cli *http.Client //debug bool //method string @@ -62,16 +69,16 @@ type SimpleRequest struct { //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, - tempBody: make(map[string]interface{}), - } -} +//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, +// BodyEntries: make(map[string]any), +// } +//} //------------------------------------------------------ // @@ -258,49 +265,50 @@ func (s *SimpleRequest) initBody() { contentTypeData := s.headers.Get(hdrContentTypeKey) switch { case IsJSONType(contentTypeData): - jsonData, err := json.Marshal(s.tempBody) - if err == nil { - s.body = bytes.NewReader(jsonData) - } else { - s.body = bytes.NewReader([]byte("{}")) + var parser, ok = s.bodyEntryParsers[jsonContentType] + if !ok { + panic(fmt.Sprintf("cannot find %s type parser", contentTypeData)) } - case strings.Contains(contentTypeData, "multipart/form-data"): - body := &bytes.Buffer{} - writer := multipart.NewWriter(body) - //data := url.Values{} - for k, sv := range s.tempBody { - switch sv.(type) { - case string: - strSv, _ := sv.(string) - _ = writer.WriteField(k, strSv) - case []string: - sss, _ := sv.([]string) - for _, v := range sss { - _ = writer.WriteField(k, v) - } - } - } - err := writer.Close() - if err != nil { - panic(err) + s.body = parser.Unmarshal(s.BodyEntryMark, s.BodyEntries) + + case strings.Contains(contentTypeData, formDataType): + var parser, ok = s.bodyEntryParsers[formDataType] + if !ok { + panic(fmt.Sprintf("cannot find %s type parser", contentTypeData)) } - s.headers.Set("Content-Type", writer.FormDataContentType()) - s.body = body + s.body = parser.Unmarshal(s.BodyEntryMark, s.BodyEntries) + fdParser := parser.(*FormDataParser) + s.headers.Set("Content-Type", fdParser.ContentType) + case IsXMLType(contentTypeData): //application/soap+xml ,application/xml - data, _ := s.tempBody[stringBodyType].(string) - s.body = strings.NewReader(data) + var parser, ok = s.bodyEntryParsers[xmlDataType] + if !ok { + data, _ := s.BodyEntries[StringEntryType.string()].(string) + s.body = strings.NewReader(data) + } + s.body = parser.Unmarshal(s.BodyEntryMark, s.BodyEntries) + case strings.Contains(contentTypeData, "text") || strings.Contains(contentTypeData, javaScriptType): - data, _ := s.tempBody[stringBodyType].(string) - s.body = strings.NewReader(data) + var parser, ok = s.bodyEntryParsers[textPlainType] + if !ok { + data, _ := s.BodyEntries[StringEntryType.string()].(string) + s.body = strings.NewReader(data) + } + s.body = parser.Unmarshal(s.BodyEntryMark, s.BodyEntries) + case contentTypeData == "" || strings.Contains(contentTypeData, "form-urlencoded"): //默认为x-www-form-urlencoded格式 - tmpData := url.Values{} - for k, v := range s.tempBody { - tmpData.Set(k, fmt.Sprintf("%v", v)) + var parser, ok = s.bodyEntryParsers["form-urlencoded"] + if !ok { + tmpData := url.Values{} + for k, v := range s.BodyEntries { + tmpData.Set(k, fmt.Sprintf("%v", v)) + } + s.body = strings.NewReader(tmpData.Encode()) + s.Headers().ConentType_formUrlencoded() } - s.body = strings.NewReader(tmpData.Encode()) - s.Headers().ConentType_formUrlencoded() + s.body = parser.Unmarshal(s.BodyEntryMark, s.BodyEntries) default: //todo 自动判断数据类型 tmpData := url.Values{} diff --git a/simpleRequest_test.go b/simpleRequest_test.go index eece469..40648b2 100644 --- a/simpleRequest_test.go +++ b/simpleRequest_test.go @@ -57,7 +57,7 @@ func TestPost_withSets(t *testing.T) { var r = NewRequest() r.Headers().ConentType_json() - r.Body().Sets(map[string]interface{}{ + r.Body().Sets(map[string]any{ "name": "JJXu", }) result, err := r.POST("http://localhost:8989/")