update docs info

This commit is contained in:
bxd
2023-11-10 18:02:22 +08:00
parent c9e1784e06
commit 81c174810f
9 changed files with 379 additions and 172 deletions

View File

@@ -12,28 +12,29 @@ import (
"github.com/gospider007/ja3"
)
// Connection Management Options
type ClientOption struct {
ForceHttp1 bool //force use http1 send requests
OrderHeaders []string //order headers with http1
Ja3 bool //enable ja3 fingerprint
Ja3Spec ja3.Ja3Spec //custom ja3Spec,use ja3.CreateSpecWithStr or ja3.CreateSpecWithId create
H2Ja3Spec ja3.H2Ja3Spec //h2 fingerprint
Proxy string //proxy,support https,http,socks5
DisCookie bool //disable cookies
DisDecode bool //disable auto decode
DisUnZip bool //disable auto zip decode
DisAlive bool //disable keepalive
Bar bool ////enable bar display
Timeout time.Duration //request timeout
OptionCallBack func(context.Context, *Client, *RequestOption) error //option callback,if error is returnd, break request
ResultCallBack func(context.Context, *Client, *Response) error //result callback,if error is returnd,next errCallback
ErrCallBack func(context.Context, *Client, error) error //error callback,if error is returnd,break request
RequestCallBack func(context.Context, *http.Request, *http.Response) error //request and response callback,if error is returnd,reponse is error
TryNum int //try num
MaxRedirectNum int //redirect num ,<0 no redirect,==0 no limit
Headers any //default headers
ResponseHeaderTimeout time.Duration //ResponseHeaderTimeout ,default:30
TlsHandshakeTimeout time.Duration //tls timeout,default:15
ForceHttp1 bool //force use http1 send requests
OrderHeaders []string //order headers with http1
Ja3 bool //enable ja3 fingerprint
Ja3Spec ja3.Ja3Spec //custom ja3Spec,use ja3.CreateSpecWithStr or ja3.CreateSpecWithId create
H2Ja3Spec ja3.H2Ja3Spec //h2 fingerprint
Proxy string //proxy,support https,http,socks5
DisCookie bool //disable cookies
DisDecode bool //disable auto decode
DisUnZip bool //disable auto zip decode
DisAlive bool //disable keepalive
Bar bool ////enable bar display
Timeout time.Duration //request timeout
OptionCallBack func(ctx context.Context, client *Client, option *RequestOption) error //option callback,if error is returnd, break request
ResultCallBack func(ctx context.Context, client *Client, response *Response) error //result callback,if error is returnd,next errCallback
ErrCallBack func(ctx context.Context, client *Client, err error) error //error callback,if error is returnd,break request
RequestCallBack func(ctx context.Context, request *http.Request, response *http.Response) error //request and response callback,if error is returnd,reponse is error
TryNum int //try num
MaxRedirectNum int //redirect num ,<0 no redirect,==0 no limit
Headers any //default headers
ResponseHeaderTimeout time.Duration //ResponseHeaderTimeout ,default:30
TlsHandshakeTimeout time.Duration //tls timeout,default:15
//network card ip
DialTimeout time.Duration //dial tcp timeout,default:15
@@ -44,8 +45,10 @@ type ClientOption struct {
Jar *Jar //custom cookies
GetProxy func(ctx context.Context, url *url.URL) (string, error) //proxy callback:support https,http,socks5 proxy
GetAddrType func(string) gtls.AddrType
GetAddrType func(host string) gtls.AddrType
}
// Connection Management
type Client struct {
forceHttp1 bool
orderHeaders []string
@@ -61,7 +64,7 @@ type Client struct {
requestCallBack func(context.Context, *http.Request, *http.Response) error
optionCallBack func(context.Context, *Client, *RequestOption) error
resultCallBack func(context.Context, *Client, *Response) error
resultCallBack func(ctx context.Context, client *Client, response *Response) error
errCallBack func(context.Context, *Client, error) error
timeout time.Duration
@@ -85,6 +88,9 @@ type Client struct {
addrType gtls.AddrType
}
var defaultClient, _ = NewClient(nil)
// New Connection Management
func NewClient(preCtx context.Context, options ...ClientOption) (*Client, error) {
if preCtx == nil {
preCtx = context.TODO()
@@ -160,21 +166,29 @@ func NewClient(preCtx context.Context, options ...ClientOption) (*Client, error)
result.h2Ja3Spec = option.H2Ja3Spec
return result, err
}
// Modifying the client's proxy
func (obj *Client) SetProxy(proxyUrl string) (err error) {
obj.proxy, err = gtls.VerifyProxy(proxyUrl)
return
}
// Modify the proxy method of the client
func (obj *Client) SetGetProxy(getProxy func(ctx context.Context, url *url.URL) (string, error)) {
obj.transport.setGetProxy(getProxy)
}
// Close idle connections. If the connection is in use, wait until it ends before closing
func (obj *Client) CloseIdleConnections() {
obj.transport.closeIdleConnections()
}
// Close the connection, even if it is in use, it will be closed
func (obj *Client) CloseConnections() {
obj.transport.closeConnections()
}
// Close the client and cannot be used again after shutdown
func (obj *Client) Close() {
obj.CloseConnections()
obj.cnl()

View File

@@ -2,12 +2,68 @@ package requests
import (
"errors"
"fmt"
"net/http"
"strings"
"github.com/gospider007/gson"
)
// 支持json,map,[]string,http.Header,string
// cookies
type Cookies []*http.Cookie
// return cookies with string,join with '; '
func (obj Cookies) String() string {
cooks := []string{}
for _, cook := range obj {
cooks = append(cooks, fmt.Sprintf("%s=%s", cook.Name, cook.Value))
}
return strings.Join(cooks, "; ")
}
// get cookies by name
func (obj Cookies) Gets(name string) Cookies {
var result Cookies
for _, cook := range obj {
if cook.Name == name {
result = append(result, cook)
}
}
return result
}
// get cookie by name
func (obj Cookies) Get(name string) *http.Cookie {
vals := obj.Gets(name)
if i := len(vals); i == 0 {
return nil
} else {
return vals[i-1]
}
}
// get cookie values by name, return []string
func (obj Cookies) GetVals(name string) []string {
var result []string
for _, cook := range obj {
if cook.Name == name {
result = append(result, cook.Value)
}
}
return result
}
// get cookie value by name,return string
func (obj Cookies) GetVal(name string) string {
vals := obj.GetVals(name)
if i := len(vals); i == 0 {
return ""
} else {
return vals[i-1]
}
}
// read cookies or parse cookies,support json,map,[]string,http.Header,string
func ReadCookies(val any) (Cookies, error) {
switch cook := val.(type) {
case *http.Cookie:
@@ -33,6 +89,7 @@ func ReadCookies(val any) (Cookies, error) {
}
}
// read set cookies or parse set cookies,support json,map,[]string,http.Header,string
func ReadSetCookies(val any) (Cookies, error) {
switch cook := val.(type) {
case Cookies:

View File

@@ -25,7 +25,7 @@ type DialClient struct {
dnsIpData sync.Map
dns *net.UDPAddr
localAddr *net.TCPAddr
getAddrType func(string) gtls.AddrType
getAddrType func(host string) gtls.AddrType
}
type msgClient struct {
time time.Time
@@ -38,7 +38,7 @@ type DialOption struct {
LocalAddr *net.TCPAddr //network card ip
AddrType gtls.AddrType //first ip type
Dns *net.UDPAddr
GetAddrType func(string) gtls.AddrType
GetAddrType func(host string) gtls.AddrType
}
type DialerOption struct {
DialTimeout time.Duration
@@ -46,7 +46,7 @@ type DialerOption struct {
LocalAddr *net.TCPAddr //network card ip
AddrType gtls.AddrType //first ip type
Dns *net.UDPAddr
GetAddrType func(string) gtls.AddrType
GetAddrType func(host string) gtls.AddrType
}
func NewDialer(option DialerOption) *net.Dialer {

12
jar.go
View File

@@ -9,10 +9,12 @@ import (
"golang.org/x/net/publicsuffix"
)
// cookies jar
type Jar struct {
jar *cookiejar.Jar
}
// new cookies jar
func NewJar() *Jar {
jar, _ := cookiejar.New(nil)
return &Jar{
@@ -20,19 +22,25 @@ func NewJar() *Jar {
}
}
// get cookies
func (obj *Client) GetCookies(href string) (Cookies, error) {
return obj.jar.GetCookies(href)
}
// set cookies
func (obj *Client) SetCookies(href string, cookies ...any) error {
return obj.jar.SetCookies(href, cookies...)
}
// clear cookies
func (obj *Client) ClearCookies() {
if obj.client.Jar != nil {
obj.jar.ClearCookies()
obj.client.Jar = obj.jar.jar
}
}
// Get cookies
func (obj *Jar) GetCookies(href string) (Cookies, error) {
if obj.jar == nil {
return nil, errors.New("jar is nil")
@@ -43,6 +51,8 @@ func (obj *Jar) GetCookies(href string) (Cookies, error) {
}
return obj.jar.Cookies(u), nil
}
// Set cookies
func (obj *Jar) SetCookies(href string, cookies ...any) error {
if obj.jar == nil {
return errors.New("jar is nil")
@@ -74,6 +84,8 @@ func (obj *Jar) SetCookies(href string, cookies ...any) error {
}
return nil
}
// Clear cookies
func (obj *Jar) ClearCookies() {
jar, _ := cookiejar.New(nil)
obj.jar = jar

View File

@@ -17,27 +17,28 @@ import (
"github.com/gospider007/websocket"
)
// Options for sending requests
type RequestOption struct {
ForceHttp1 bool //force use http1 send requests
OrderHeaders []string //order headers with http1
Ja3 bool //enable ja3 fingerprint
Ja3Spec ja3.Ja3Spec //custom ja3Spec,use ja3.CreateSpecWithStr or ja3.CreateSpecWithId create
H2Ja3Spec ja3.H2Ja3Spec //custom h2 fingerprint
Proxy string //proxy,support http,https,socks5,examplehttp://127.0.0.1:7005
DisCookie bool //disable cookies,not use cookies
DisDecode bool //disable auto decode
DisUnZip bool //disable auto zip decode
DisAlive bool //disable keepalive
Bar bool //enable bar display
Timeout time.Duration //request timeout
OptionCallBack func(context.Context, *Client, *RequestOption) error //option callback,if error is returnd, break request
ResultCallBack func(context.Context, *Client, *Response) error //result callback,if error is returnd,next errCallback
ErrCallBack func(context.Context, *Client, error) error //error callback,if error is returnd,break request
RequestCallBack func(context.Context, *http.Request, *http.Response) error //request and response callback,if error is returnd,reponse is error
TryNum int //try num
MaxRedirectNum int //redirect num ,<0 no redirect,==0 no limit
Headers any //request headersjson,mapheader
ResponseHeaderTimeout time.Duration //ResponseHeaderTimeout ,default:30
ForceHttp1 bool //force use http1 send requests
OrderHeaders []string //order headers with http1
Ja3 bool //enable ja3 fingerprint
Ja3Spec ja3.Ja3Spec //custom ja3Spec,use ja3.CreateSpecWithStr or ja3.CreateSpecWithId create
H2Ja3Spec ja3.H2Ja3Spec //custom h2 fingerprint
Proxy string //proxy,support http,https,socks5,examplehttp://127.0.0.1:7005
DisCookie bool //disable cookies,not use cookies
DisDecode bool //disable auto decode
DisUnZip bool //disable auto zip decode
DisAlive bool //disable keepalive
Bar bool //enable bar display
Timeout time.Duration //request timeout
OptionCallBack func(ctx context.Context, client *Client, option *RequestOption) error //option callback,if error is returnd, break request
ResultCallBack func(ctx context.Context, client *Client, response *Response) error //result callback,if error is returnd,next errCallback
ErrCallBack func(ctx context.Context, client *Client, err error) error //error callback,if error is returnd,break request
RequestCallBack func(ctx context.Context, request *http.Request, response *http.Response) error //request and response callback,if error is returnd,reponse is error
TryNum int //try num
MaxRedirectNum int //redirect num ,<0 no redirect,==0 no limit
Headers any //request headersjson,mapheader
ResponseHeaderTimeout time.Duration //ResponseHeaderTimeout ,default:30
TlsHandshakeTimeout time.Duration
//network card ip
@@ -71,6 +72,8 @@ type RequestOption struct {
// body io.Reader
once bool
}
// Upload files with form-data
type File struct {
Key string
Val []byte

View File

@@ -49,116 +49,230 @@ type reqCtxData struct {
localAddr *net.TCPAddr //network card ip
addrType gtls.AddrType //first ip type
dns *net.UDPAddr
isNewConn bool
}
func Get(preCtx context.Context, href string, options ...RequestOption) (resp *Response, err error) {
client, _ := NewClient(preCtx, ClientOption{DisAlive: true})
resp, err = client.Request(preCtx, http.MethodGet, href, options...)
if err != nil || resp == nil || !resp.oneceAlive() {
client.Close()
}
return
// sends a GET request and returns the response.
// It takes the following parameters:
// - preCtx: A context object used to control the timeout and cancellation of the request.
// - href: The URL to be requested.
// - options: A variadic parameter for optional request options.
//
// The function returns a tuple of the response object and an error object (if any).
func Get(ctx context.Context, href string, options ...RequestOption) (resp *Response, err error) {
return defaultClient.Request(ctx, http.MethodGet, href, options...)
}
func Head(preCtx context.Context, href string, options ...RequestOption) (resp *Response, err error) {
client, _ := NewClient(preCtx, ClientOption{DisAlive: true})
resp, err = client.Request(preCtx, http.MethodHead, href, options...)
if err != nil || resp == nil || !resp.oneceAlive() {
client.Close()
}
return
// sends a Head request and returns the response.
// It takes the following parameters:
// - preCtx: A context object used to control the timeout and cancellation of the request.
// - href: The URL to be requested.
// - options: A variadic parameter for optional request options.
//
// The function returns a tuple of the response object and an error object (if any).
func Head(ctx context.Context, href string, options ...RequestOption) (resp *Response, err error) {
return defaultClient.Request(ctx, http.MethodHead, href, options...)
}
func Post(preCtx context.Context, href string, options ...RequestOption) (resp *Response, err error) {
client, _ := NewClient(preCtx, ClientOption{DisAlive: true})
resp, err = client.Request(preCtx, http.MethodPost, href, options...)
if err != nil || resp == nil || !resp.oneceAlive() {
client.Close()
}
return
// sends a Post request and returns the response.
// It takes the following parameters:
// - preCtx: A context object used to control the timeout and cancellation of the request.
// - href: The URL to be requested.
// - options: A variadic parameter for optional request options.
//
// The function returns a tuple of the response object and an error object (if any).
func Post(ctx context.Context, href string, options ...RequestOption) (resp *Response, err error) {
return defaultClient.Request(ctx, http.MethodPost, href, options...)
}
func Put(preCtx context.Context, href string, options ...RequestOption) (resp *Response, err error) {
client, _ := NewClient(preCtx, ClientOption{DisAlive: true})
resp, err = client.Request(preCtx, http.MethodPut, href, options...)
if err != nil || resp == nil || !resp.oneceAlive() {
client.Close()
}
return
// sends a Put request and returns the response.
// It takes the following parameters:
// - preCtx: A context object used to control the timeout and cancellation of the request.
// - href: The URL to be requested.
// - options: A variadic parameter for optional request options.
//
// The function returns a tuple of the response object and an error object (if any).
func Put(ctx context.Context, href string, options ...RequestOption) (resp *Response, err error) {
return defaultClient.Request(ctx, http.MethodPut, href, options...)
}
func Patch(preCtx context.Context, href string, options ...RequestOption) (resp *Response, err error) {
client, _ := NewClient(preCtx, ClientOption{DisAlive: true})
resp, err = client.Request(preCtx, http.MethodPatch, href, options...)
if err != nil || resp == nil || !resp.oneceAlive() {
client.Close()
}
return
// sends a Patch request and returns the response.
// It takes the following parameters:
// - preCtx: A context object used to control the timeout and cancellation of the request.
// - href: The URL to be requested.
// - options: A variadic parameter for optional request options.
//
// The function returns a tuple of the response object and an error object (if any).
func Patch(ctx context.Context, href string, options ...RequestOption) (resp *Response, err error) {
return defaultClient.Request(ctx, http.MethodPatch, href, options...)
}
func Delete(preCtx context.Context, href string, options ...RequestOption) (resp *Response, err error) {
client, _ := NewClient(preCtx, ClientOption{DisAlive: true})
resp, err = client.Request(preCtx, http.MethodDelete, href, options...)
if err != nil || resp == nil || !resp.oneceAlive() {
client.Close()
}
return
// sends a Delete request and returns the response.
// It takes the following parameters:
// - preCtx: A context object used to control the timeout and cancellation of the request.
// - href: The URL to be requested.
// - options: A variadic parameter for optional request options.
//
// The function returns a tuple of the response object and an error object (if any).
func Delete(ctx context.Context, href string, options ...RequestOption) (resp *Response, err error) {
return defaultClient.Request(ctx, http.MethodDelete, href, options...)
}
func Connect(preCtx context.Context, href string, options ...RequestOption) (resp *Response, err error) {
client, _ := NewClient(preCtx, ClientOption{DisAlive: true})
resp, err = client.Request(preCtx, http.MethodConnect, href, options...)
if err != nil || resp == nil || !resp.oneceAlive() {
client.Close()
}
return
// sends a Connect request and returns the response.
// It takes the following parameters:
// - preCtx: A context object used to control the timeout and cancellation of the request.
// - href: The URL to be requested.
// - options: A variadic parameter for optional request options.
//
// The function returns a tuple of the response object and an error object (if any).
func Connect(ctx context.Context, href string, options ...RequestOption) (resp *Response, err error) {
return defaultClient.Request(ctx, http.MethodConnect, href, options...)
}
func Options(preCtx context.Context, href string, options ...RequestOption) (resp *Response, err error) {
client, _ := NewClient(preCtx, ClientOption{DisAlive: true})
resp, err = client.Request(preCtx, http.MethodOptions, href, options...)
if err != nil || resp == nil || !resp.oneceAlive() {
client.Close()
}
return
// sends a Options request and returns the response.
// It takes the following parameters:
// - preCtx: A context object used to control the timeout and cancellation of the request.
// - href: The URL to be requested.
// - options: A variadic parameter for optional request options.
//
// The function returns a tuple of the response object and an error object (if any).
func Options(ctx context.Context, href string, options ...RequestOption) (resp *Response, err error) {
return defaultClient.Request(ctx, http.MethodOptions, href, options...)
}
func Trace(preCtx context.Context, href string, options ...RequestOption) (resp *Response, err error) {
client, _ := NewClient(preCtx, ClientOption{DisAlive: true})
resp, err = client.Request(preCtx, http.MethodTrace, href, options...)
if err != nil || resp == nil || !resp.oneceAlive() {
client.Close()
}
return
// sends a Trace request and returns the response.
// It takes the following parameters:
// - preCtx: A context object used to control the timeout and cancellation of the request.
// - href: The URL to be requested.
// - options: A variadic parameter for optional request options.
//
// The function returns a tuple of the response object and an error object (if any).
func Trace(ctx context.Context, href string, options ...RequestOption) (resp *Response, err error) {
return defaultClient.Request(ctx, http.MethodTrace, href, options...)
}
//Define a function named Request that takes in four parameters:
//- preCtx: a context.Context object for setting request-related context information
//- method: a string representing the request method (e.g., GET, POST)
//- href: a string representing the URL link for the request
//- options: a variadic parameter of type RequestOptions for setting specific options for the request
// Return a tuple of two values:
// - resp: a pointer to a Response object containing information about the response of the request
// - err: an error encountered during the request, which is nil if no error occurred
func Request(preCtx context.Context, method string, href string, options ...RequestOption) (resp *Response, err error) {
client, _ := NewClient(preCtx, ClientOption{DisAlive: true})
resp, err = client.Request(preCtx, method, href, options...)
if err != nil || resp == nil || !resp.oneceAlive() {
client.Close()
}
return
return defaultClient.Request(preCtx, method, href, options...)
}
// sends a Get request and returns the response.
// It takes the following parameters:
// - preCtx: A context object used to control the timeout and cancellation of the request.
// - href: The URL to be requested.
// - options: A variadic parameter for optional request options.
//
// The function returns a tuple of the response object and an error object (if any).
func (obj *Client) Get(preCtx context.Context, href string, options ...RequestOption) (*Response, error) {
return obj.Request(preCtx, http.MethodGet, href, options...)
}
// sends a Head request and returns the response.
// It takes the following parameters:
// - preCtx: A context object used to control the timeout and cancellation of the request.
// - href: The URL to be requested.
// - options: A variadic parameter for optional request options.
//
// The function returns a tuple of the response object and an error object (if any).
func (obj *Client) Head(preCtx context.Context, href string, options ...RequestOption) (*Response, error) {
return obj.Request(preCtx, http.MethodHead, href, options...)
}
// sends a Post request and returns the response.
// It takes the following parameters:
// - preCtx: A context object used to control the timeout and cancellation of the request.
// - href: The URL to be requested.
// - options: A variadic parameter for optional request options.
//
// The function returns a tuple of the response object and an error object (if any).
func (obj *Client) Post(preCtx context.Context, href string, options ...RequestOption) (*Response, error) {
return obj.Request(preCtx, http.MethodPost, href, options...)
}
// sends a Put request and returns the response.
// It takes the following parameters:
// - preCtx: A context object used to control the timeout and cancellation of the request.
// - href: The URL to be requested.
// - options: A variadic parameter for optional request options.
//
// The function returns a tuple of the response object and an error object (if any).
func (obj *Client) Put(preCtx context.Context, href string, options ...RequestOption) (*Response, error) {
return obj.Request(preCtx, http.MethodPut, href, options...)
}
// sends a Patch request and returns the response.
// It takes the following parameters:
// - preCtx: A context object used to control the timeout and cancellation of the request.
// - href: The URL to be requested.
// - options: A variadic parameter for optional request options.
//
// The function returns a tuple of the response object and an error object (if any).
func (obj *Client) Patch(preCtx context.Context, href string, options ...RequestOption) (*Response, error) {
return obj.Request(preCtx, http.MethodPatch, href, options...)
}
// sends a Delete request and returns the response.
// It takes the following parameters:
// - preCtx: A context object used to control the timeout and cancellation of the request.
// - href: The URL to be requested.
// - options: A variadic parameter for optional request options.
//
// The function returns a tuple of the response object and an error object (if any).
func (obj *Client) Delete(preCtx context.Context, href string, options ...RequestOption) (*Response, error) {
return obj.Request(preCtx, http.MethodDelete, href, options...)
}
// sends a Connect request and returns the response.
// It takes the following parameters:
// - preCtx: A context object used to control the timeout and cancellation of the request.
// - href: The URL to be requested.
// - options: A variadic parameter for optional request options.
//
// The function returns a tuple of the response object and an error object (if any).
func (obj *Client) Connect(preCtx context.Context, href string, options ...RequestOption) (*Response, error) {
return obj.Request(preCtx, http.MethodConnect, href, options...)
}
// sends a Options request and returns the response.
// It takes the following parameters:
// - preCtx: A context object used to control the timeout and cancellation of the request.
// - href: The URL to be requested.
// - options: A variadic parameter for optional request options.
//
// The function returns a tuple of the response object and an error object (if any).
func (obj *Client) Options(preCtx context.Context, href string, options ...RequestOption) (*Response, error) {
return obj.Request(preCtx, http.MethodOptions, href, options...)
}
// sends a Trace request and returns the response.
// It takes the following parameters:
// - preCtx: A context object used to control the timeout and cancellation of the request.
// - href: The URL to be requested.
// - options: A variadic parameter for optional request options.
//
// The function returns a tuple of the response object and an error object (if any).
func (obj *Client) Trace(preCtx context.Context, href string, options ...RequestOption) (*Response, error) {
return obj.Request(preCtx, http.MethodTrace, href, options...)
}
//Define a function named Request that takes in four parameters:
//- preCtx: a context.Context object for setting request-related context information
//- method: a string representing the request method (e.g., GET, POST)
//- href: a string representing the URL link for the request
//- options: a variadic parameter of type RequestOptions for setting specific options for the request
// Return a tuple of two values:
// - resp: a pointer to a Response object containing information about the response of the request
// - err: an error encountered during the request, which is nil if no error occurred
func (obj *Client) Request(preCtx context.Context, method string, href string, options ...RequestOption) (resp *Response, err error) {
if obj == nil {
return nil, errors.New("client is nil")
@@ -380,7 +494,9 @@ func (obj *Client) request(preCtx context.Context, option *RequestOption) (respo
}
}
//send req
if response.response, err = obj.getClient(option).Do(reqs); err != nil {
response.response, err = obj.getClient(option).Do(reqs)
response.isNewConn = ctxData.isNewConn
if err != nil {
err = tools.WrapError(err, "roundTripper error")
return
} else if response.response == nil {

View File

@@ -5,7 +5,6 @@ import (
"bytes"
"context"
"errors"
"fmt"
"io"
"net/url"
"strconv"
@@ -34,22 +33,25 @@ type Response struct {
disUnzip bool
filePath string
bar bool
isNewConn bool
}
type SseClient struct {
reader *bufio.Reader
}
type Event struct {
Data string
Event string
Id string
Retry int
Comment string
Data string //data
Event string //event
Id string //id
Retry int //retry num
Comment string //comment info
}
func newSseClient(rd io.Reader) *SseClient {
return &SseClient{reader: bufio.NewReader(rd)}
}
// recv sse envent data
func (obj *SseClient) Recv() (Event, error) {
var event Event
for {
@@ -75,66 +77,22 @@ func (obj *SseClient) Recv() (Event, error) {
}
}
type Cookies []*http.Cookie
func (obj Cookies) String() string {
cooks := []string{}
for _, cook := range obj {
cooks = append(cooks, fmt.Sprintf("%s=%s", cook.Name, cook.Value))
}
return strings.Join(cooks, "; ")
}
func (obj Cookies) Gets(name string) Cookies {
var result Cookies
for _, cook := range obj {
if cook.Name == name {
result = append(result, cook)
}
}
return result
}
func (obj Cookies) Get(name string) *http.Cookie {
vals := obj.Gets(name)
if i := len(vals); i == 0 {
return nil
} else {
return vals[i-1]
}
}
func (obj Cookies) GetVals(name string) []string {
var result []string
for _, cook := range obj {
if cook.Name == name {
result = append(result, cook.Value)
}
}
return result
}
func (obj Cookies) GetVal(name string) string {
vals := obj.GetVals(name)
if i := len(vals); i == 0 {
return ""
} else {
return vals[i-1]
}
}
// return websocket client
func (obj *Response) WebSocket() *websocket.Conn {
return obj.webSocket
}
// return sse client
func (obj *Response) SseClient() *SseClient {
return obj.sseClient
}
// return URL redirected address
func (obj *Response) Location() (*url.URL, error) {
return obj.response.Location()
}
// return response cookies
func (obj *Response) Cookies() Cookies {
if obj.filePath != "" {
return nil
@@ -142,6 +100,7 @@ func (obj *Response) Cookies() Cookies {
return obj.response.Cookies()
}
// return response status code
func (obj *Response) StatusCode() int {
if obj.filePath != "" {
return 200
@@ -149,6 +108,7 @@ func (obj *Response) StatusCode() int {
return obj.response.StatusCode
}
// return response status
func (obj *Response) Status() string {
if obj.filePath != "" {
return "200 OK"
@@ -156,6 +116,7 @@ func (obj *Response) Status() string {
return obj.response.Status
}
// return response url
func (obj *Response) Url() *url.URL {
if obj.filePath != "" {
return nil
@@ -163,6 +124,7 @@ func (obj *Response) Url() *url.URL {
return obj.response.Request.URL
}
// return response headers
func (obj *Response) Headers() http.Header {
if obj.filePath != "" {
return http.Header{
@@ -172,6 +134,7 @@ func (obj *Response) Headers() http.Header {
return obj.response.Header
}
// change decoding with content
func (obj *Response) Decode(encoding string) {
if obj.encoding != encoding {
obj.encoding = encoding
@@ -179,30 +142,38 @@ func (obj *Response) Decode(encoding string) {
}
}
// return content with map[string]any
func (obj *Response) Map() (data map[string]any, err error) {
_, err = gson.Decode(obj.Content(), &data)
return
}
// return content with json and you can parse struct
func (obj *Response) Json(vals ...any) (*gson.Client, error) {
return gson.Decode(obj.Content(), vals...)
}
// return content with string
func (obj *Response) Text() string {
return tools.BytesToString(obj.Content())
}
// set response content with []byte
func (obj *Response) SetContent(val []byte) {
obj.content = val
}
// return content with []byte
func (obj *Response) Content() []byte {
return obj.content
}
// return content with parse html
func (obj *Response) Html() *bs4.Client {
return bs4.NewClient(obj.Text(), obj.Url().String())
}
// return content type
func (obj *Response) ContentType() string {
if obj.filePath != "" {
return http.DetectContentType(obj.content)
@@ -214,6 +185,7 @@ func (obj *Response) ContentType() string {
return contentType
}
// return content encoding
func (obj *Response) ContentEncoding() string {
if obj.filePath != "" {
return ""
@@ -221,6 +193,7 @@ func (obj *Response) ContentEncoding() string {
return obj.response.Header.Get("Content-Encoding")
}
// return content length
func (obj *Response) ContentLength() int64 {
if obj.filePath != "" {
return int64(len(obj.content))
@@ -334,6 +307,11 @@ func (obj *Response) InPool() bool {
return obj.response.Body.(interface{ InPool() bool }).InPool()
}
// conn is new conn
func (obj *Response) IsNewConn() bool {
return obj.isNewConn
}
// conn ja3
func (obj *Response) Ja3() string {
return obj.response.Body.(interface{ Ja3() string }).Ja3()

View File

@@ -79,7 +79,7 @@ type roundTripperOption struct {
KeepAlive time.Duration
LocalAddr *net.TCPAddr //network card ip
AddrType gtls.AddrType //first ip type
GetAddrType func(string) gtls.AddrType
GetAddrType func(host string) gtls.AddrType
Dns *net.UDPAddr
GetProxy func(ctx context.Context, url *url.URL) (string, error)
}
@@ -292,6 +292,7 @@ func (obj *RoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
return task.res, task.err
}
}
ctxData.isNewConn = true
newConn:
ckey := key
conn, err := obj.dial(ctxData, &ckey, req)

26
test/request_test.go Normal file
View File

@@ -0,0 +1,26 @@
package main
import (
"testing"
"github.com/gospider007/requests"
)
func TestDefaultClient(t *testing.T) {
for i := 0; i < 2; i++ {
resp, err := requests.Get(nil, "https://myip.top")
if err != nil {
t.Error(err)
} else {
if i == 0 {
if !resp.IsNewConn() {
t.Error("new conn")
}
} else {
if resp.IsNewConn() {
t.Error("not new conn")
}
}
}
}
}