1 Star 0 Fork 0

Teval/goz

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
request.go 7.29 KB
一键复制 编辑 原始数据 按行查看 历史
package goz
import (
"bytes"
"crypto/tls"
"encoding/json"
"encoding/xml"
"errors"
"fmt"
"io"
"log"
"mime/multipart"
"net/http"
"net/http/httputil"
"net/url"
"os"
"path/filepath"
"strings"
"time"
"github.com/idoubi/goutils"
)
// Request object
type Request struct {
opts Options
cli *http.Client
req *http.Request
body io.Reader
}
// Get send get request
func (r *Request) Get(uri string, opts ...Options) (*Response, error) {
return r.Request("GET", uri, opts...)
}
// Post send post request
func (r *Request) Post(uri string, opts ...Options) (*Response, error) {
return r.Request("POST", uri, opts...)
}
// Put send put request
func (r *Request) Put(uri string, opts ...Options) (*Response, error) {
return r.Request("PUT", uri, opts...)
}
// Patch send patch request
func (r *Request) Patch(uri string, opts ...Options) (*Response, error) {
return r.Request("PATCH", uri, opts...)
}
// Delete send delete request
func (r *Request) Delete(uri string, opts ...Options) (*Response, error) {
return r.Request("DELETE", uri, opts...)
}
// Options send options request
func (r *Request) Options(uri string, opts ...Options) (*Response, error) {
return r.Request("OPTIONS", uri, opts...)
}
// Request send request
func (r *Request) Request(method, uri string, opts ...Options) (*Response, error) {
if len(opts) > 0 {
r.opts = opts[0]
}
if r.opts.Headers == nil {
r.opts.Headers = make(map[string]interface{})
}
switch method {
case http.MethodGet, http.MethodDelete:
req, err := http.NewRequest(method, uri, nil)
if err != nil {
return nil, err
}
r.req = req
case http.MethodPost, http.MethodPut, http.MethodPatch, http.MethodOptions:
// parse body
r.parseBody()
req, err := http.NewRequest(method, uri, r.body)
if err != nil {
return nil, err
}
r.req = req
default:
return nil, errors.New("invalid request method")
}
// r.req.Close = true
// parseOptions
r.parseOptions()
// parseClient
r.parseClient()
// parse query
r.parseQuery()
// parse headers
r.parseHeaders()
// parse cookies
r.parseCookies()
if r.opts.Debug {
// print request object
fmt.Println()
dump, err := httputil.DumpRequest(r.req, true)
if err == nil {
log.Printf("\n%s\n\n", dump)
}
}
_resp, err := r.cli.Do(r.req)
resp := &Response{
resp: _resp,
req: r.req,
err: err,
}
if err == nil {
body, err := io.ReadAll(_resp.Body)
_ = _resp.Body.Close()
if r.opts.ParseBodyFunc != nil {
resp.body = r.opts.ParseBodyFunc(body)
if r.opts.Debug {
fmt.Println(string(body))
fmt.Println()
fmt.Println()
}
} else {
resp.body = body
}
resp.err = err
}
if err != nil {
if r.opts.Debug {
// print response err
fmt.Println(err)
}
return resp, err
}
if r.opts.Debug {
// print response data
body, _ := resp.GetBody()
fmt.Println(string(body))
}
return resp, nil
}
func (r *Request) parseOptions() {
// default timeout 30s
if r.opts.Timeout == 0 {
r.opts.Timeout = 30
}
r.opts.timeout = time.Duration(r.opts.Timeout*1000) * time.Millisecond
}
func (r *Request) parseClient() {
tr := &http.Transport{
// 部分请求的InsecureSkipVerify不能设置为True --By Teval 2023-04-11
// TLSClientConfig: &tls.Config{
// InsecureSkipVerify: !r.opts.NoInsecureSkipVerify,
// },
// 关闭KeepAlive --By Teval 2021-08-18
DisableKeepAlives: !r.opts.NoDisableKeepAlives,
}
if !r.opts.NoInsecureSkipVerify {
if tr.TLSClientConfig == nil {
tr.TLSClientConfig = &tls.Config{
InsecureSkipVerify: true,
}
} else {
tr.TLSClientConfig.InsecureSkipVerify = true
}
}
if r.opts.Proxy != "" {
proxy, err := url.Parse(r.opts.Proxy)
if err == nil {
tr.Proxy = http.ProxyURL(proxy)
}
}
r.cli = &http.Client{
Timeout: r.opts.timeout,
Transport: tr,
}
}
func (r *Request) parseQuery() {
switch r.opts.Query.(type) {
case string:
str := r.opts.Query.(string)
r.req.URL.RawQuery = str
case map[string]interface{}:
q := r.req.URL.Query()
for k, v := range r.opts.Query.(map[string]interface{}) {
if vv, ok := v.(string); ok {
q.Set(k, vv)
continue
}
if vv, ok := v.([]string); ok {
for _, vvv := range vv {
q.Add(k, vvv)
}
}
}
r.req.URL.RawQuery = q.Encode()
}
}
func (r *Request) parseCookies() {
switch r.opts.Cookies.(type) {
case string:
cookies := r.opts.Cookies.(string)
r.req.Header.Add("Cookie", cookies)
case map[string]string:
cookies := r.opts.Cookies.(map[string]string)
for k, v := range cookies {
r.req.AddCookie(&http.Cookie{
Name: k,
Value: v,
})
}
case []*http.Cookie:
cookies := r.opts.Cookies.([]*http.Cookie)
for _, cookie := range cookies {
r.req.AddCookie(cookie)
}
}
}
func (r *Request) parseHeaders() {
if r.opts.Headers != nil {
for k, v := range r.opts.Headers {
if vv, ok := v.(string); ok {
// r.req.Header.Set(k, vv)
r.req.Header[k] = []string{vv}
continue
}
if vv, ok := v.([]string); ok {
for _, vvv := range vv {
// r.req.Header.Add(k, vvv)
// r.req.Header[k] = []string{vvv}
r.req.Header[k] = append(r.req.Header[k], vvv)
}
}
}
}
}
func (r *Request) parseBody() {
// application/octet-stream
if r.opts.ByteData != nil {
r.body = bytes.NewReader(r.opts.ByteData)
if _, ok := r.opts.Headers["Content-Type"]; !ok {
r.opts.Headers["Content-Type"] = "application/octet-stream"
}
}
// multipart/form-data
if r.opts.FormData != nil {
body := new(bytes.Buffer)
w := multipart.NewWriter(body)
for k, v := range r.opts.FormData {
switch val := v.(type) {
case *os.File:
// if w2, err := w.CreateFormFile(k, val.Name()); err != nil {
if w2, err := w.CreateFormFile(k, filepath.Base(val.Name())); err != nil {
return
} else {
if _, err := io.Copy(w2, val); err != nil {
return
}
}
default:
str := fmt.Sprintf("%+v", v)
if str == "<nil>" {
str = ""
}
if err := w.WriteField(k, str); err != nil {
return
}
}
}
_ = w.Close()
r.body = body
if _, ok := r.opts.Headers["Content-Type"]; !ok {
r.opts.Headers["Content-Type"] = w.FormDataContentType()
}
}
// application/x-www-form-urlencoded
if r.opts.FormParams != nil {
if _, ok := r.opts.Headers["Content-Type"]; !ok {
r.opts.Headers["Content-Type"] = "application/x-www-form-urlencoded"
}
values := url.Values{}
for k, v := range r.opts.FormParams {
if vv, ok := v.(string); ok {
values.Set(k, vv)
}
if vv, ok := v.([]string); ok {
for _, vvv := range vv {
values.Add(k, vvv)
}
}
}
r.body = strings.NewReader(values.Encode())
return
}
// application/json
if r.opts.JSON != nil {
if _, ok := r.opts.Headers["Content-Type"]; !ok {
r.opts.Headers["Content-Type"] = "application/json"
}
b, err := json.Marshal(r.opts.JSON)
if err == nil {
r.body = bytes.NewReader(b)
return
}
}
// application/xml
if r.opts.XML != nil {
if _, ok := r.opts.Headers["Content-Type"]; !ok {
r.opts.Headers["Content-Type"] = "application/xml"
}
switch r.opts.XML.(type) {
case map[string]string:
// 请求参数转换成xml结构
b, err := goutils.Map2XML(r.opts.XML.(map[string]string))
if err == nil {
r.body = bytes.NewBuffer(b)
return
}
default:
b, err := xml.Marshal(r.opts.JSON)
if err == nil {
r.body = bytes.NewBuffer(b)
}
}
}
return
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Go
1
https://gitee.com/teval/goz.git
git@gitee.com:teval/goz.git
teval
goz
goz
v1.2.6

搜索帮助

0d507c66 1850385 C8b1a773 1850385