You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
simpleRequest/simpleRequest.go

313 lines
7.6 KiB
Go

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/*
* @FileName: simpleRequest.go
* @Author: JJXu
* @CreateTime: 2022/3/2 上午12:33
* @Description:
*/
package simpleRequest
import (
"bytes"
"crypto/tls"
"encoding/json"
"fmt"
"io"
"io/ioutil"
"mime/multipart"
"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,
tempBody: make(map[string]interface{}),
}
}
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,
tempBody: make(map[string]interface{}),
}
}
//------------------------------------------------------
//
// 数据准备
//Authorization 添加令牌的方法集合
func (s *SimpleRequest) Authorization() *Authorization {
return &Authorization{
simpleReq: s,
}
}
//Headers 添加请求头
func (s *SimpleRequest) Headers() *HeadersConf {
return &HeadersConf{
simpleReq: s,
}
}
//Body 添加请求体
func (s *SimpleRequest) Body() *BodyConf {
return &BodyConf{
simpleReq: s,
}
}
//QueryParams 添加url后面的参数
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 发送数据
resp, err := client.Do(request)
if err != nil {
fmt.Println("【Request Error】:", err.Error())
return
}
//v0.0.2更新将request和response内容返回便于用户进行分析 JJXu 03-11-2022
if resp != nil {
s.Response = *resp
}
if request != nil {
s.Request = *request
}
defer resp.Body.Close()
//3.2 获取数据
body, err = ioutil.ReadAll(resp.Body)
return
}
// POST method does POST HTTP request. It's defined in section 2 of RFC5789.
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 {
r.Header[k] = append(r.Header[k], s.headers[k]...)
s.headers.Del(k)
}
//queryParams
r.URL.RawQuery = s.queryParams.Encode()
body, err = s.do(r)
return
}
// GET method does GET HTTP request. It's defined in section 2 of RFC5789.
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 {
r.Header[k] = append(r.Header[k], s.headers[k]...)
s.headers.Del(k)
}
//queryParams
r.URL.RawQuery = s.queryParams.Encode()
body, err = s.do(r)
return
}
//通用的请求方法
func (s *SimpleRequest) LaunchTo(urls, method string) (body []byte, err error) {
// body
s.initBody()
r, err := http.NewRequest(method, urls, s.body)
if err != nil {
return nil, err
}
//headers
for k := range s.headers {
r.Header[k] = append(r.Header[k], s.headers[k]...)
s.headers.Del(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) (body []byte, err error) {
return s.LaunchTo(url, http.MethodPut)
}
// DELETE method does DELETE HTTP request. It's defined in section 2 of RFC5789.
func (s *SimpleRequest) DELETE(url string) (body []byte, err error) {
return s.LaunchTo(url, http.MethodDelete)
}
// Patch method does Patch HTTP request. It's defined in section 2 of RFC5789.
func (s *SimpleRequest) PATCH(url string) (body []byte, err error) {
return s.LaunchTo(url, http.MethodPatch)
}
// HEAD method does HEAD HTTP request. It's defined in section 2 of RFC5789.
func (s *SimpleRequest) HEAD(url string) (body []byte, err error) {
return s.LaunchTo(url, http.MethodHead)
}
// CONNECT method does CONNECT HTTP request. It's defined in section 2 of RFC5789.
func (s *SimpleRequest) CONNECT(url string) (body []byte, err error) {
return s.LaunchTo(url, http.MethodConnect)
}
// OPTIONS method does OPTIONS HTTP request. It's defined in section 2 of RFC5789.
func (s *SimpleRequest) OPTIONS(url string) (body []byte, err error) {
return s.LaunchTo(url, http.MethodOptions)
}
// TRACE method does TRACE HTTP request. It's defined in section 2 of RFC5789.
func (s *SimpleRequest) TRACE(url string) (body []byte, err error) {
return s.LaunchTo(url, http.MethodTrace)
}
//------------------------------------------------------
//
// 这里数据
//
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)
}
s.headers.Set("Content-Type", writer.FormDataContentType())
s.body = body
case IsXMLType(contentTypeData):
//application/soap+xml ,application/xml
data, _ := s.tempBody[stringBodyType].(string)
s.body = strings.NewReader(data)
case strings.Contains(contentTypeData, "text") || strings.Contains(contentTypeData, javaScriptType):
data, _ := s.tempBody[stringBodyType].(string)
s.body = strings.NewReader(data)
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))
}
s.body = strings.NewReader(tmpData.Encode())
s.Headers().ConentType_formUrlencoded()
default:
//todo 自动判断数据类型
tmpData := url.Values{}
for k, v := range tmpData {
tmpData.Set(k, fmt.Sprintf("%v", v))
}
s.body = strings.NewReader(tmpData.Encode())
}
}