github.com/gospider007/requests@v0.0.0-20240506025355-c73d46169a23/option.go (about)

     1  package requests
     2  
     3  import (
     4  	"context"
     5  	"io"
     6  	"net"
     7  	"net/http"
     8  	"net/url"
     9  	"time"
    10  
    11  	"github.com/gospider007/gtls"
    12  	"github.com/gospider007/ja3"
    13  	"github.com/gospider007/websocket"
    14  )
    15  
    16  // Connection Management Options
    17  type ClientOption struct {
    18  	Ja3Spec               ja3.Ja3Spec                                                                           //custom ja3Spec,use ja3.CreateSpecWithStr or ja3.CreateSpecWithId create
    19  	H2Ja3Spec             ja3.H2Ja3Spec                                                                         //h2 fingerprint
    20  	Proxy                 string                                                                                //proxy,support https,http,socks5
    21  	ForceHttp1            bool                                                                                  //force  use http1 send requests
    22  	Ja3                   bool                                                                                  //enable ja3 fingerprint
    23  	DisCookie             bool                                                                                  //disable cookies
    24  	DisDecode             bool                                                                                  //disable auto decode
    25  	DisUnZip              bool                                                                                  //disable auto zip decode
    26  	DisAlive              bool                                                                                  //disable  keepalive
    27  	Bar                   bool                                                                                  ////enable bar display
    28  	OptionCallBack        func(ctx context.Context, option *RequestOption) error                                //option callback,if error is returnd, break request
    29  	ResultCallBack        func(ctx context.Context, option *RequestOption, response *Response) error            //result callback,if error is returnd,next errCallback
    30  	ErrCallBack           func(ctx context.Context, option *RequestOption, response *Response, err error) error //error callback,if error is returnd,break request
    31  	RequestCallBack       func(ctx context.Context, request *http.Request, response *http.Response) error       //request and response callback,if error is returnd,reponse is error
    32  	MaxRetries            int                                                                                   //try num
    33  	MaxRedirect           int                                                                                   //redirect num ,<0 no redirect,==0 no limit
    34  	Headers               any                                                                                   //default headers
    35  	Timeout               time.Duration                                                                         //request timeout
    36  	ResponseHeaderTimeout time.Duration                                                                         //ResponseHeaderTimeout ,default:300
    37  	TlsHandshakeTimeout   time.Duration                                                                         //tls timeout,default:15
    38  
    39  	//network card ip
    40  	DialTimeout time.Duration //dial tcp timeout,default:15
    41  	KeepAlive   time.Duration //keepalive,default:30
    42  	LocalAddr   *net.TCPAddr
    43  	Dns         *net.UDPAddr  //dns
    44  	AddrType    gtls.AddrType //dns parse addr type
    45  	Jar         *Jar          //custom cookies
    46  
    47  	//other option
    48  	GetProxy    func(ctx context.Context, url *url.URL) (string, error) //proxy callback:support https,http,socks5 proxy
    49  	GetAddrType func(host string) gtls.AddrType
    50  }
    51  
    52  // Options for sending requests
    53  type RequestOption struct {
    54  	Ja3Spec         ja3.Ja3Spec                                                                           //custom ja3Spec,use ja3.CreateSpecWithStr or ja3.CreateSpecWithId create
    55  	H2Ja3Spec       ja3.H2Ja3Spec                                                                         //custom h2 fingerprint
    56  	Proxy           string                                                                                //proxy,support http,https,socks5,example:http://127.0.0.1:7005
    57  	ForceHttp1      bool                                                                                  //force  use http1 send requests
    58  	Ja3             bool                                                                                  //enable ja3 fingerprint
    59  	DisCookie       bool                                                                                  //disable cookies,not use cookies
    60  	DisDecode       bool                                                                                  //disable auto decode
    61  	DisUnZip        bool                                                                                  //disable auto zip decode
    62  	DisAlive        bool                                                                                  //disable  keepalive
    63  	Bar             bool                                                                                  //enable bar display
    64  	OptionCallBack  func(ctx context.Context, option *RequestOption) error                                //option callback,if error is returnd, break request
    65  	ResultCallBack  func(ctx context.Context, option *RequestOption, response *Response) error            //result callback,if error is returnd,next errCallback
    66  	ErrCallBack     func(ctx context.Context, option *RequestOption, response *Response, err error) error //error callback,if error is returnd,break request
    67  	RequestCallBack func(ctx context.Context, request *http.Request, response *http.Response) error       //request and response callback,if error is returnd,reponse is error
    68  
    69  	MaxRetries            int           //try num
    70  	MaxRedirect           int           //redirect num ,<0 no redirect,==0 no limit
    71  	Headers               any           //request headers:json,map,header
    72  	Timeout               time.Duration //request timeout
    73  	ResponseHeaderTimeout time.Duration //ResponseHeaderTimeout ,default:300
    74  	TlsHandshakeTimeout   time.Duration
    75  
    76  	//network card ip
    77  	DialTimeout time.Duration //dial tcp timeout,default:15
    78  	KeepAlive   time.Duration //keepalive,default:30
    79  	LocalAddr   *net.TCPAddr
    80  	Dns         *net.UDPAddr  //dns
    81  	AddrType    gtls.AddrType //dns parse addr type                                             //tls timeout,default:15
    82  	Jar         *Jar          //custom cookies
    83  
    84  	// other option
    85  	Method      string //method
    86  	Url         *url.URL
    87  	Host        string
    88  	Referer     string //set headers referer value
    89  	ContentType string //headers Content-Type value
    90  	Cookies     any    // cookies,support :json,map,str,http.Header
    91  
    92  	Params any //url params,join url query,json,map
    93  	Json   any //send application/json,support io.Reader,:string,[]bytes,json,map
    94  	Data   any //send application/x-www-form-urlencoded, support io.Reader, string,[]bytes,json,map
    95  	Form   any //send multipart/form-data,file upload,support io.Reader, json,map
    96  	Text   any //send text/xml,support: io.Reader, string,[]bytes,json,map
    97  	Body   any //not setting context-type,support io.Reader, string,[]bytes,json,map
    98  
    99  	Stream   bool             //disable auto read
   100  	WsOption websocket.Option //websocket option
   101  	DisProxy bool             //force disable proxy
   102  	once     bool
   103  	client   *Client
   104  }
   105  
   106  func (obj *RequestOption) Client() *Client {
   107  	return obj.client
   108  }
   109  
   110  // Upload files with form-data,
   111  type File struct {
   112  	FileName    string
   113  	ContentType string
   114  	Content     any
   115  }
   116  
   117  func (obj *RequestOption) initBody(ctx context.Context) (io.Reader, error) {
   118  	if obj.Body != nil {
   119  		body, _, _, err := obj.newBody(obj.Body, readType)
   120  		if err != nil || body == nil {
   121  			return nil, err
   122  		}
   123  		return body, err
   124  	} else if obj.Form != nil {
   125  		var orderMap *OrderMap
   126  		_, orderMap, _, err := obj.newBody(obj.Form, mapType)
   127  		if err != nil {
   128  			return nil, err
   129  		}
   130  		if orderMap == nil {
   131  			return nil, nil
   132  		}
   133  		body, contentType, once, err := orderMap.parseForm(ctx)
   134  		if err != nil {
   135  			return nil, err
   136  		}
   137  		obj.once = once
   138  		if obj.ContentType == "" {
   139  			obj.ContentType = contentType
   140  		}
   141  		if body == nil {
   142  			return nil, nil
   143  		}
   144  		return body, nil
   145  	} else if obj.Data != nil {
   146  		body, orderMap, _, err := obj.newBody(obj.Data, mapType)
   147  		if err != nil {
   148  			return body, err
   149  		}
   150  		if obj.ContentType == "" {
   151  			obj.ContentType = "application/x-www-form-urlencoded"
   152  		}
   153  		if body != nil {
   154  			return body, nil
   155  		}
   156  		if orderMap == nil {
   157  			return nil, nil
   158  		}
   159  		body2 := orderMap.parseData()
   160  		if body2 == nil {
   161  			return nil, nil
   162  		}
   163  		return body2, nil
   164  	} else if obj.Json != nil {
   165  		body, _, _, err := obj.newBody(obj.Json, readType)
   166  		if err != nil {
   167  			return nil, err
   168  		}
   169  		if obj.ContentType == "" {
   170  			obj.ContentType = "application/json"
   171  		}
   172  		if body == nil {
   173  			return nil, nil
   174  		}
   175  		return body, nil
   176  	} else if obj.Text != nil {
   177  		body, _, _, err := obj.newBody(obj.Text, readType)
   178  		if err != nil {
   179  			return nil, err
   180  		}
   181  		if obj.ContentType == "" {
   182  			obj.ContentType = "text/plain"
   183  		}
   184  		if body == nil {
   185  			return nil, nil
   186  		}
   187  		return body, nil
   188  	} else {
   189  		return nil, nil
   190  	}
   191  }
   192  func (obj *RequestOption) initParams() (*url.URL, error) {
   193  	baseUrl := cloneUrl(obj.Url)
   194  	if obj.Params == nil {
   195  		return baseUrl, nil
   196  	}
   197  	_, dataMap, _, err := obj.newBody(obj.Params, mapType)
   198  	if err != nil {
   199  		return nil, err
   200  	}
   201  	query := dataMap.parseParams().String()
   202  	if query == "" {
   203  		return baseUrl, nil
   204  	}
   205  	pquery := baseUrl.Query().Encode()
   206  	if pquery == "" {
   207  		baseUrl.RawQuery = query
   208  	} else {
   209  		baseUrl.RawQuery = pquery + "&" + query
   210  	}
   211  	return baseUrl, nil
   212  }
   213  func (obj *Client) newRequestOption(option RequestOption) RequestOption {
   214  	// start
   215  	if !option.Ja3Spec.IsSet() {
   216  		option.Ja3Spec = obj.option.Ja3Spec
   217  	}
   218  	if !option.H2Ja3Spec.IsSet() {
   219  		option.H2Ja3Spec = obj.option.H2Ja3Spec
   220  	}
   221  	if option.Proxy == "" {
   222  		option.Proxy = obj.option.Proxy
   223  	}
   224  	if !option.ForceHttp1 {
   225  		option.ForceHttp1 = obj.option.ForceHttp1
   226  	}
   227  	if !option.Ja3 {
   228  		option.Ja3 = obj.option.Ja3
   229  	}
   230  	if !option.DisCookie {
   231  		option.DisCookie = obj.option.DisCookie
   232  	}
   233  	if !option.DisDecode {
   234  		option.DisDecode = obj.option.DisDecode
   235  	}
   236  	if !option.DisUnZip {
   237  		option.DisUnZip = obj.option.DisUnZip
   238  	}
   239  	if !option.DisAlive {
   240  		option.DisAlive = obj.option.DisAlive
   241  	}
   242  	if !option.Bar {
   243  		option.Bar = obj.option.Bar
   244  	}
   245  	if option.OptionCallBack == nil {
   246  		option.OptionCallBack = obj.option.OptionCallBack
   247  	}
   248  	if option.ResultCallBack == nil {
   249  		option.ResultCallBack = obj.option.ResultCallBack
   250  	}
   251  	if option.ErrCallBack == nil {
   252  		option.ErrCallBack = obj.option.ErrCallBack
   253  	}
   254  	if option.RequestCallBack == nil {
   255  		option.RequestCallBack = obj.option.RequestCallBack
   256  	}
   257  	if option.MaxRetries == 0 {
   258  		option.MaxRetries = obj.option.MaxRetries
   259  	}
   260  	if option.MaxRedirect == 0 {
   261  		option.MaxRedirect = obj.option.MaxRedirect
   262  	}
   263  	if option.Headers == nil {
   264  		option.Headers = obj.option.Headers
   265  	}
   266  	if option.Timeout == 0 {
   267  		option.Timeout = obj.option.Timeout
   268  	}
   269  	if option.ResponseHeaderTimeout == 0 {
   270  		option.ResponseHeaderTimeout = obj.option.ResponseHeaderTimeout
   271  	}
   272  	if option.TlsHandshakeTimeout == 0 {
   273  		option.TlsHandshakeTimeout = obj.option.TlsHandshakeTimeout
   274  	}
   275  	if option.DialTimeout == 0 {
   276  		option.DialTimeout = obj.option.DialTimeout
   277  	}
   278  	if option.KeepAlive == 0 {
   279  		option.KeepAlive = obj.option.KeepAlive
   280  	}
   281  	if option.LocalAddr == nil {
   282  		option.LocalAddr = obj.option.LocalAddr
   283  	}
   284  	if option.Dns == nil {
   285  		option.Dns = obj.option.Dns
   286  	}
   287  	if option.AddrType == 0 {
   288  		option.AddrType = obj.option.AddrType
   289  	}
   290  	if option.Jar == nil {
   291  		option.Jar = obj.option.Jar
   292  	}
   293  	//end
   294  	if option.MaxRetries < 0 {
   295  		option.MaxRetries = 0
   296  	}
   297  	if !option.Ja3Spec.IsSet() && option.Ja3 {
   298  		option.Ja3Spec = ja3.DefaultJa3Spec()
   299  	}
   300  	if option.DisCookie {
   301  		option.Jar = nil
   302  	}
   303  	if option.DisProxy {
   304  		option.Proxy = ""
   305  	}
   306  	return option
   307  }