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

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

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

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

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

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

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

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

@ -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
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{}),
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{}
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("{}"))
}
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)
var parser, ok = s.bodyEntryParsers[jsonContentType]
if !ok {
panic(fmt.Sprintf("cannot find %s type parser", contentTypeData))
}
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)
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)
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格式
var parser, ok = s.bodyEntryParsers["form-urlencoded"]
if !ok {
tmpData := url.Values{}
for k, v := range s.tempBody {
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 = parser.Unmarshal(s.BodyEntryMark, s.BodyEntries)
default:
//todo 自动判断数据类型
tmpData := url.Values{}

@ -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/")

Loading…
Cancel
Save