调整封装的方法
This commit is contained in:
@@ -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")
|
||||||
|
)
|
||||||
@@ -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
@@ -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
@@ -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
@@ -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
|
||||||
|
|||||||
@@ -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 "
|
|
||||||
)
|
|
||||||
Reference in New Issue
Block a user