新增bodyentry解析模块,可自定义解析函数

master
徐俊杰 2 years ago
parent 9bff109127
commit f0327d0c93

@ -90,7 +90,7 @@ r.QueryParams().Set("user", "dorlolo")
#### 2.4.2 map赋值 #### 2.4.2 map赋值
不会覆盖上面之前填充过的参数 不会覆盖上面之前填充过的参数
```go ```go
pamarsBulid := make(map[string]interface{}) pamarsBulid := make(map[string]any)
pamarsBulid["passwd"] = "123456" pamarsBulid["passwd"] = "123456"
pamarsBulid["action"] = "login" pamarsBulid["action"] = "login"
r.QueryParams().Sets(pamarsBulid) r.QueryParams().Sets(pamarsBulid)
@ -118,7 +118,7 @@ r.Body().Set("beginDate", "2022-03-01").Set("endDate", "2022-03-03")
#### 2.5.2 map赋值 #### 2.5.2 map赋值
```go ```go
bodyBulid := map[string]interface{}{ bodyBulid := map[string]any{
"beginDate":"2022-03-01", "beginDate":"2022-03-01",
"endDate":"2022-03-03", "endDate":"2022-03-03",
} }

@ -7,25 +7,48 @@
package simpleRequest package simpleRequest
var ( type EntryMark string
stringBodyType = "__STRING_BODY__"
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 { type BodyConf struct {
simpleReq *SimpleRequest simpleReq *SimpleRequest
} }
func (s *BodyConf) Set(key string, value interface{}) *BodyConf { func (s *BodyConf) Set(key string, value any) *BodyConf {
s.simpleReq.tempBody[key] = value s.simpleReq.BodyEntries[key] = value
return s 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 { for k, v := range data {
s.simpleReq.tempBody[k] = v s.simpleReq.BodyEntries[k] = v
} }
return s return s
} }
func (s *BodyConf) SetString(strData string) *BodyConf { 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 return s
} }

@ -26,7 +26,7 @@ func TestRequest(t *testing.T) {
//设置params //设置params
r.QueryParams().Set("user", "dorlolo") r.QueryParams().Set("user", "dorlolo")
//批量添加,不会覆盖上面user //批量添加,不会覆盖上面user
pamarsBulid := map[string]interface{}{ pamarsBulid := map[string]any{
"passwd": "123456", "passwd": "123456",
"action": "login", "action": "login",
} }

@ -1,3 +1,3 @@
module github.com/dorlolo/simpleRequest module github.com/dorlolo/simpleRequest
go 1.17 go 1.18

@ -9,7 +9,6 @@ package simpleRequest
import ( import (
"bytes" "bytes"
"encoding/json"
"math/rand" "math/rand"
"net/http" "net/http"
"regexp" "regexp"
@ -36,7 +35,7 @@ var (
jsonCheck = regexp.MustCompile(`(?i:(application|text)/(json|.*\+json|json\-.*)(;|$))`) jsonCheck = regexp.MustCompile(`(?i:(application|text)/(json|.*\+json|json\-.*)(;|$))`)
xmlCheck = regexp.MustCompile(`(?i:(application|text)/(xml|.*\+xml)(;|$))`) 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{ var userAgentList = [...]string{
@ -101,11 +100,6 @@ func (s *HeadersConf) SetConentType(value string) *HeadersConf {
} }
func (s *HeadersConf) ConentType_json() *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) s.simpleReq.headers.Set(hdrContentTypeKey, jsonContentType)
return s return s
} }
@ -118,7 +112,7 @@ func (s *HeadersConf) ConentType_charsetUtf8() *HeadersConf {
func (s *HeadersConf) ConentType_formData() *HeadersConf { func (s *HeadersConf) ConentType_formData() *HeadersConf {
//tmp := url.Values{} //tmp := url.Values{}
//for k, v := range s.simpleReq.tempBody { //for k, v := range s.simpleReq.BodyEntry {
// tmp.Add(k, fmt.Sprintf("%v", v)) // tmp.Add(k, fmt.Sprintf("%v", v))
//} //}
s.simpleReq.headers.Set(hdrContentTypeKey, formDataType) s.simpleReq.headers.Set(hdrContentTypeKey, formDataType)

@ -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
}
}

@ -17,7 +17,7 @@ type QueryParams struct {
} }
//batch settings //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 { for k, v := range data {
s.simpleReq.queryParams.Set(k, fmt.Sprintf("%v", v)) s.simpleReq.queryParams.Set(k, fmt.Sprintf("%v", v))
} }
@ -25,7 +25,7 @@ func (s *QueryParams) Sets(data map[string]interface{}) *QueryParams {
} }
//single settings //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)) s.simpleReq.queryParams.Set(key, fmt.Sprintf("%v", value))
return s return s
} }

@ -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()
}

@ -8,33 +8,37 @@
package simpleRequest package simpleRequest
import ( import (
"bytes"
"crypto/tls" "crypto/tls"
"encoding/json"
"fmt" "fmt"
"io" "io"
"io/ioutil" "io/ioutil"
"mime/multipart"
"net/http" "net/http"
"net/url" "net/url"
"strings" "strings"
"time" "time"
) )
func NewRequest() *SimpleRequest { func NewRequest(opts ...OPTION) *SimpleRequest {
var ( var (
hd = http.Header{} hd = http.Header{}
qp = url.Values{} qp = url.Values{}
) )
return &SimpleRequest{ var r = &SimpleRequest{
//headers: make(map[string]string), //headers: make(map[string]string),
//cookies: make(map[string]string), //cookies: make(map[string]string),
timeout: time.Second * 7, timeout: time.Second * 7,
queryParams: qp, queryParams: qp,
headers: hd, headers: hd,
tempBody: make(map[string]interface{}), BodyEntries: make(map[string]any),
bodyEntryParsers: bodyEntryParsers,
} }
if len(opts) > 0 {
for _, o := range opts {
r = o(r)
}
}
return r
} }
type SimpleRequest struct { type SimpleRequest struct {
@ -44,13 +48,16 @@ type SimpleRequest struct {
headers http.Header headers http.Header
transport *http.Transport transport *http.Transport
tempBody map[string]interface{} BodyEntryMark EntryMark
BodyEntries map[string]any
bodyEntryParsers map[string]IBodyEntryParser
timeout time.Duration timeout time.Duration
Response http.Response //用于获取完整的返回内容。请注意要在请求之后才能获取 Response http.Response //用于获取完整的返回内容。请注意要在请求之后才能获取
Request http.Request //用于获取完整的请求内容。请注意要在请求之后才能获取 Request http.Request //用于获取完整的请求内容。请注意要在请求之后才能获取
//cookies map[string]string //cookies map[string]string
//data interface{} //data any
//cli *http.Client //cli *http.Client
//debug bool //debug bool
//method string //method string
@ -62,16 +69,16 @@ type SimpleRequest struct {
//checkRedirect func(req *http.Request, via []*http.Request) error //checkRedirect func(req *http.Request, via []*http.Request) error
} }
func (s *SimpleRequest) NewRequest() *SimpleRequest { //func (s *SimpleRequest) NewRequest() *SimpleRequest {
var qp = url.Values{} // var qp = url.Values{}
return &SimpleRequest{ // return &SimpleRequest{
//headers: make(map[string]string), // //headers: make(map[string]string),
//cookies: make(map[string]string), // //cookies: make(map[string]string),
timeout: time.Second * 7, // timeout: time.Second * 7,
queryParams: qp, // queryParams: qp,
tempBody: make(map[string]interface{}), // BodyEntries: make(map[string]any),
} // }
} //}
//------------------------------------------------------ //------------------------------------------------------
// //
@ -258,49 +265,50 @@ func (s *SimpleRequest) initBody() {
contentTypeData := s.headers.Get(hdrContentTypeKey) contentTypeData := s.headers.Get(hdrContentTypeKey)
switch { switch {
case IsJSONType(contentTypeData): case IsJSONType(contentTypeData):
jsonData, err := json.Marshal(s.tempBody) var parser, ok = s.bodyEntryParsers[jsonContentType]
if err == nil { if !ok {
s.body = bytes.NewReader(jsonData) panic(fmt.Sprintf("cannot find %s type parser", contentTypeData))
} else {
s.body = bytes.NewReader([]byte("{}"))
}
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)
} }
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.body = parser.Unmarshal(s.BodyEntryMark, s.BodyEntries)
err := writer.Close() fdParser := parser.(*FormDataParser)
if err != nil { s.headers.Set("Content-Type", fdParser.ContentType)
panic(err)
}
s.headers.Set("Content-Type", writer.FormDataContentType())
s.body = body
case IsXMLType(contentTypeData): case IsXMLType(contentTypeData):
//application/soap+xml ,application/xml //application/soap+xml ,application/xml
data, _ := s.tempBody[stringBodyType].(string) var parser, ok = s.bodyEntryParsers[xmlDataType]
if !ok {
data, _ := s.BodyEntries[StringEntryType.string()].(string)
s.body = strings.NewReader(data) s.body = strings.NewReader(data)
}
s.body = parser.Unmarshal(s.BodyEntryMark, s.BodyEntries)
case strings.Contains(contentTypeData, "text") || strings.Contains(contentTypeData, javaScriptType): case strings.Contains(contentTypeData, "text") || strings.Contains(contentTypeData, javaScriptType):
data, _ := s.tempBody[stringBodyType].(string) var parser, ok = s.bodyEntryParsers[textPlainType]
if !ok {
data, _ := s.BodyEntries[StringEntryType.string()].(string)
s.body = strings.NewReader(data) s.body = strings.NewReader(data)
}
s.body = parser.Unmarshal(s.BodyEntryMark, s.BodyEntries)
case contentTypeData == "" || strings.Contains(contentTypeData, "form-urlencoded"): case contentTypeData == "" || strings.Contains(contentTypeData, "form-urlencoded"):
//默认为x-www-form-urlencoded格式 //默认为x-www-form-urlencoded格式
var parser, ok = s.bodyEntryParsers["form-urlencoded"]
if !ok {
tmpData := url.Values{} tmpData := url.Values{}
for k, v := range s.tempBody { for k, v := range s.BodyEntries {
tmpData.Set(k, fmt.Sprintf("%v", v)) tmpData.Set(k, fmt.Sprintf("%v", v))
} }
s.body = strings.NewReader(tmpData.Encode()) s.body = strings.NewReader(tmpData.Encode())
s.Headers().ConentType_formUrlencoded() s.Headers().ConentType_formUrlencoded()
}
s.body = parser.Unmarshal(s.BodyEntryMark, s.BodyEntries)
default: default:
//todo 自动判断数据类型 //todo 自动判断数据类型
tmpData := url.Values{} tmpData := url.Values{}

@ -57,7 +57,7 @@ func TestPost_withSets(t *testing.T) {
var r = NewRequest() var r = NewRequest()
r.Headers().ConentType_json() r.Headers().ConentType_json()
r.Body().Sets(map[string]interface{}{ r.Body().Sets(map[string]any{
"name": "JJXu", "name": "JJXu",
}) })
result, err := r.POST("http://localhost:8989/") result, err := r.POST("http://localhost:8989/")

Loading…
Cancel
Save