调整封装的方法

This commit is contained in:
Yun
2025-12-28 15:14:05 +08:00
parent 8bca4cc013
commit 0931539e1c
6 changed files with 151 additions and 153 deletions
+17
View File
@@ -0,0 +1,17 @@
package curlx
import "errors"
type UserAgent string
const (
UserAgentChrome UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 "
UserAgentFirefox UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:61.0) Gecko/20100101 "
UserAgentIE UserAgent = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0; "
UserAgentEdge UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 "
UserAgentWechat UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 "
)
var (
ErrStatusNotOK error = errors.New("Status not ok")
)
+43 -81
View File
@@ -2,10 +2,8 @@ package curlx
import ( import (
"bufio" "bufio"
"compress/gzip"
"context" "context"
"fmt" "fmt"
"io"
"net" "net"
"net/http" "net/http"
"net/url" "net/url"
@@ -122,43 +120,29 @@ func (c *Curlx) WithAddress(ctx context.Context, addr string) {
/** /**
* 简单请求 * 简单请求
*/ */
func (c *Curlx) Send(ctx context.Context, p ...Param) (res []byte, httpcode int, err error) { func (c *Curlx) Send(ctx context.Context, p ...Param) (res []byte, err error) {
_, response, err := c.SendExec(ctx, p...) resp := c.exec(ctx, p...)
if err != nil { if resp.Err != nil {
return nil, -1, err return nil, resp.Err
}
defer resp.Close() // 处理完关闭
status := resp.GetStatusCode()
if status != 200 {
return nil, ErrStatusNotOK
} }
defer response.Body.Close() // 处理完关闭 body, err := resp.GetBody()
if err != nil {
// stdout := os.Stdout // 将结果定位到标准输出,也可以直接打印出来,或定位到其他地方进行相应处理 return nil, err
// _, err = io.Copy(stdout, response.Body) // 将第二个参数拷贝到第一个参数,直到第二参数到达EOF或发生错误,返回拷贝的值
status := response.StatusCode // 获取状态码,正常是200
var body []byte
if response.Header.Get("Content-Encoding") == "gzip" {
reader, err := gzip.NewReader(response.Body)
if err != nil {
return nil, response.StatusCode, err
}
body, err = io.ReadAll(reader)
if err != nil {
return nil, response.StatusCode, err
}
defer reader.Close()
} else {
body, err = io.ReadAll(response.Body)
if err != nil {
return nil, response.StatusCode, err
}
} }
c.opts.Logger.Infof(ctx, "curlx.Send body:%s", string(body)) c.opts.Logger.Infof(ctx, "curlx.Send body:%s", string(body))
return body, status, nil return body, nil
} }
// PostJson 发送JSON数据 // PostJson 发送JSON数据
func (l *Curlx) PostJson(ctx context.Context, url string, jsonStr string) ([]byte, int, error) { func (l *Curlx) PostJson(ctx context.Context, url string, jsonStr string) ([]byte, error) {
return l.Send(ctx, return l.Send(ctx,
SetParamsUrl(url), SetParamsUrl(url),
SetParamsBody([]byte(jsonStr)), SetParamsBody([]byte(jsonStr)),
@@ -168,55 +152,24 @@ func (l *Curlx) PostJson(ctx context.Context, url string, jsonStr string) ([]byt
} }
// Get 简单GET请求 // Get 简单GET请求
func (l *Curlx) Get(ctx context.Context, url string) ([]byte, int, error) { func (l *Curlx) Get(ctx context.Context, url string) ([]byte, error) {
return l.Send(ctx, return l.Send(ctx,
SetParamsUrl(url), SetParamsUrl(url),
SetParamsMethod(MethodGet), SetParamsMethod(MethodGet),
) )
} }
func (c *Curlx) SendWithResponee(ctx context.Context, ps ...Param) Response { func (c *Curlx) SendWithResponse(ctx context.Context, ps ...Param) Response {
r := Response{} return c.exec(ctx, ps...)
req, resp, err := c.SendExec(ctx, ps...)
r.req = req
r.resp = resp
if err != nil {
r.err = err
return r
}
var body []byte
if resp.Header.Get("Content-Encoding") == "gzip" {
reader, err := gzip.NewReader(resp.Body)
if err != nil {
r.err = err
return r
}
body, err = io.ReadAll(reader)
if err != nil {
r.err = err
return r
}
defer reader.Close()
} else {
body, err = io.ReadAll(resp.Body)
if err != nil {
r.err = err
return r
}
}
r.body = body
c.opts.Logger.Infof(ctx, "curlx.Send body:%s", string(body))
return r
} }
/** /**
* 执行发送 * 执行发送
* 注意:外部使用需要加这一句 defer response.Body.Close() * 注意:外部使用需要加这一句 defer response.Body.Close()
*/ */
func (c *Curlx) SendExec(ctx context.Context, ps ...Param) (req *http.Request, resp *http.Response, err error) { func (c *Curlx) exec(ctx context.Context, ps ...Param) Response {
resp := Response{}
client := &http.Client{ client := &http.Client{
Timeout: c.opts.TimeOut, // 整个请求的超时时间 设置该条连接的超时 Timeout: c.opts.TimeOut, // 整个请求的超时时间 设置该条连接的超时
Transport: c.transport, // Transport: c.transport, //
@@ -228,23 +181,27 @@ func (c *Curlx) SendExec(ctx context.Context, ps ...Param) (req *http.Request, r
} }
c.opts.Logger.Infof(ctx, "curlx.sendExec params:%+v", p) c.opts.Logger.Infof(ctx, "curlx.sendExec params:%+v", p)
err = p.parseMethod() err := p.parseMethod()
if err != nil { if err != nil {
return nil, nil, err c.opts.Logger.Errorf(ctx, "curlx.sendExec parseMethod err:%v", err)
resp.Err = err
return resp
} }
// 判断和处理url // 判断和处理url
err = p.parseUrl() err = p.parseUrl()
if err != nil { if err != nil {
c.opts.Logger.Errorf(ctx, "curlx.sendExec parseUrl err:%v", err) c.opts.Logger.Errorf(ctx, "curlx.sendExec parseUrl err:%v", err)
return nil, nil, err resp.Err = err
return resp
} }
// 处理参数 // 处理参数
reqParams, err := p.parseParams() reqParams, err := p.parseParams()
if err != nil { if err != nil {
c.opts.Logger.Errorf(ctx, "curlx.sendExec parseParams err:%v", err) c.opts.Logger.Errorf(ctx, "curlx.sendExec parseParams err:%v", err)
return nil, nil, err resp.Err = err
return resp
} }
// 初始化句柄 // 初始化句柄
@@ -255,9 +212,13 @@ func (c *Curlx) SendExec(ctx context.Context, ps ...Param) (req *http.Request, r
) )
if err != nil { if err != nil {
c.opts.Logger.Errorf(ctx, "curlx.sendExec NewRequest err:%v", err) c.opts.Logger.Errorf(ctx, "curlx.sendExec NewRequest err:%v", err)
return nil, nil, err resp.Err = err
return resp
} }
c.opts.Logger.Infof(ctx, "curlx.sendExec request:%+v", request)
resp.Request = request
// 这里指定要访问的HOST,到时候服务器获取主机是获取到这个 // 这里指定要访问的HOST,到时候服务器获取主机是获取到这个
// request.Host = "api.hk.blueoceantech.co" // request.Host = "api.hk.blueoceantech.co"
@@ -274,10 +235,12 @@ func (c *Curlx) SendExec(ctx context.Context, ps ...Param) (req *http.Request, r
response, err := client.Do(request) response, err := client.Do(request)
if err != nil { if err != nil {
c.opts.Logger.Errorf(ctx, "curlx.sendExec client.Do err:%v", err) c.opts.Logger.Errorf(ctx, "curlx.sendExec client.Do err:%v", err)
return nil, nil, err resp.Err = err
return resp
} }
// response.StatusCode resp.Response = response
return request, response, nil
return resp
} }
/** /**
@@ -293,13 +256,12 @@ func (c *Curlx) SendStream(ctx context.Context, ps ...Param) (<-chan string, err
ctx, cancel := context.WithTimeout(context.Background(), c.opts.TimeOut) ctx, cancel := context.WithTimeout(context.Background(), c.opts.TimeOut)
defer cancel() defer cancel()
_, response, err := c.SendExec(ctx, ps...) response := c.exec(ctx, ps...)
if err != nil { if response.Err != nil {
return return
} }
defer response.Body.Close() // 处理完关闭 defer response.Close() // 处理完关闭
scanner := bufio.NewScanner(response.Response.Body)
scanner := bufio.NewScanner(response.Body)
for scanner.Scan() { for scanner.Scan() {
text := scanner.Text() text := scanner.Text()
if text == "" { if text == "" {
+11 -11
View File
@@ -11,11 +11,11 @@ import (
) )
func TestGet(t *testing.T) { func TestGet(t *testing.T) {
resp, code, err := NewCurlx().Send(context.Background(), resp, err := NewCurlx().Send(context.Background(),
SetParamsUrl("https://www.baidu.com"), SetParamsUrl("https://www.baidu.com"),
SetParamsMethod(MethodGet), SetParamsMethod(MethodGet),
) )
t.Log(resp, code, err) t.Log(string(resp), err)
} }
@@ -41,22 +41,22 @@ func TestForm(t *testing.T) {
by, _ := json.Marshal(s) by, _ := json.Marshal(s)
p := ClientParams{ p := ClientParams{
Url: "http://tech-dev.sealmoo.com/api/material/upload", Url: "http://tech-dev.sealmoo.com/api/material/upload",
Method: "POST", Method: "POST",
Body: by, Body: by,
Headers: http.Header{ Headers: http.Header{
"Content-Type": []string{"application/json"}, "Content-Type": []string{"application/json"},
"Authorization": []string{"Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0ZW5hbnRfaWQiOjAsImNsaWVudF9pZCI6MCwidXNlcl9pZCI6MSwiZXhwIjoxNzAxMzk3NzkxfQ.9_uJ6y8I4JZTwgSenwHC_01nddLuI4zmgpyPhn5M6j8"}, "Authorization": []string{"Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0ZW5hbnRfaWQiOjAsImNsaWVudF9pZCI6MCwidXNlcl9pZCI6MSwiZXhwIjoxNzAxMzk3NzkxfQ.9_uJ6y8I4JZTwgSenwHC_01nddLuI4zmgpyPhn5M6j8"},
}, },
ContentType: ContentTypeForm, ContentType: ContentTypeForm,
} }
resp, code, err := NewCurlx().Send(context.Background(), SetParamsAll(p)) resp, err := NewCurlx().Send(context.Background(), SetParamsAll(p))
fmt.Println(resp, code, err) fmt.Println(resp, err)
} }
func TestProxy(t *testing.T) { func TestProxy(t *testing.T) {
c := NewCurlx() c := NewCurlx()
c.WithProxySocks5("127.0.0.1:1080") c.WithProxySocks5("127.0.0.1:1080")
res, code, err := c.Send(context.Background(), SetParamsUrl("https://www.google.com"), SetParamsMethod(MethodGet)) res, err := c.Send(context.Background(), SetParamsUrl("https://www.google.com"), SetParamsMethod(MethodGet))
t.Log(string(res), code, err) t.Log(string(res), err)
} }
+13 -2
View File
@@ -10,12 +10,14 @@ type clientOptions struct {
TimeOut time.Duration TimeOut time.Duration
InsecureSkipVerify bool InsecureSkipVerify bool
Logger OptionLogger Logger OptionLogger
LoggerLength int // 日志输出长度
} }
func defaultOptions() clientOptions { func defaultOptions() clientOptions {
return clientOptions{ return clientOptions{
TimeOut: time.Second * 120, // 默认超时120 TimeOut: time.Second * 120, // 默认超时120
Logger: defaultLogger{}, Logger: defaultLogger{},
LoggerLength: 100,
} }
} }
@@ -48,6 +50,15 @@ func SetOptionLog(log OptionLogger) Option {
} }
} }
/**
* 设置日志输出长度
*/
func WithLoggerLength(length int) Option {
return func(options *clientOptions) {
options.LoggerLength = length
}
}
type OptionLogger interface { type OptionLogger interface {
Infof(ctx context.Context, format string, args ...interface{}) Infof(ctx context.Context, format string, args ...interface{})
Errorf(ctx context.Context, format string, args ...interface{}) Errorf(ctx context.Context, format string, args ...interface{})
+67 -47
View File
@@ -1,6 +1,8 @@
package curlx package curlx
import ( import (
"compress/gzip"
"io"
"net" "net"
"net/http" "net/http"
"strings" "strings"
@@ -10,70 +12,77 @@ import (
// Response response object // Response response object
type Response struct { type Response struct {
resp *http.Response Response *http.Response
req *http.Request Request *http.Request
body []byte Body []byte
err error Err error
} }
// ResponseBody response body func (l *Response) Close() error {
type ResponseBody []byte if l.Response.Body != nil {
return l.Response.Body.Close()
// String fmt outout
func (r ResponseBody) String() string {
return string(r)
}
// Read get slice of response body
func (r ResponseBody) Read(length int) []byte {
if length > len(r) {
length = len(r)
} }
return nil
return r[:length]
}
// GetContents format response body as string
func (r ResponseBody) GetContents() string {
return string(r)
} }
// GetRequest get request object // GetRequest get request object
func (r *Response) GetRequest() *http.Request { func (r *Response) GetRequest() *http.Request {
return r.req return r.Request
}
func (r *Response) GetResponse() *http.Response {
return r.Response
} }
// GetBody parse response body // GetBody parse response body
func (r *Response) GetBody() (ResponseBody, error) { func (r *Response) GetBody() ([]byte, error) {
return ResponseBody(r.body), r.err if r.Err != nil {
return nil, r.Err
}
if r.Body != nil {
return r.Body, nil
}
if r.Response == nil {
return nil, nil
}
body := []byte{}
var err error
if r.Response.Header.Get("Content-Encoding") == "gzip" {
reader, err := gzip.NewReader(r.Response.Body)
if err != nil {
return nil, err
}
defer reader.Close()
body, err = io.ReadAll(reader)
if err != nil {
return nil, err
}
} else {
body, err = io.ReadAll(r.Response.Body)
if err != nil {
return nil, err
}
}
// close body
r.Response.Body.Close()
r.Body = body
return body, err
} }
// GetParsedBody parse response body with gjson func (r Response) GetStatusCode() int {
func (r *Response) GetParsedBody() (*gjson.Result, error) { if r.Response == nil {
pb := gjson.ParseBytes(r.body) return 0
}
return &pb, nil return r.Response.StatusCode
}
// GetStatusCode get response status code
func (r *Response) GetStatusCode() int {
return r.resp.StatusCode
}
// GetReasonPhrase get response reason phrase
func (r *Response) GetReasonPhrase() string {
status := r.resp.Status
arr := strings.Split(status, " ")
return arr[1]
} }
// IsTimeout get if request is timeout // IsTimeout get if request is timeout
func (r *Response) IsTimeout() bool { func (r *Response) IsTimeout() bool {
if r.err == nil { if r.Err == nil {
return false return false
} }
netErr, ok := r.err.(net.Error) netErr, ok := r.Err.(net.Error)
if !ok { if !ok {
return false return false
} }
@@ -84,9 +93,20 @@ func (r *Response) IsTimeout() bool {
return false return false
} }
// GetParsedBody parse response body with gjson
func (r *Response) GetParsedBody() (*gjson.Result, error) {
body, err := r.GetBody()
if err != nil {
return nil, err
}
pb := gjson.ParseBytes(body)
return &pb, nil
}
// GetHeaders get response headers // GetHeaders get response headers
func (r *Response) GetHeaders() map[string][]string { func (r *Response) GetHeaders() map[string][]string {
return r.resp.Header return r.Response.Header
} }
// GetHeader get response header // GetHeader get response header
-12
View File
@@ -1,12 +0,0 @@
package curlx
type UserAgent string
const(
UserAgentChrome UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 "
UserAgentFirefox UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:61.0) Gecko/20100101 "
UserAgentIE UserAgent = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0; "
UserAgentEdge UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 "
UserAgentWechat UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 "
)