core.go 31 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172
  1. package dara
  2. import (
  3. "bytes"
  4. "context"
  5. "crypto/tls"
  6. "crypto/x509"
  7. "encoding/base64"
  8. "encoding/hex"
  9. "encoding/json"
  10. "errors"
  11. "fmt"
  12. "io"
  13. "math"
  14. "math/rand"
  15. "net"
  16. "net/http"
  17. "net/url"
  18. "os"
  19. "reflect"
  20. "strconv"
  21. "strings"
  22. "sync"
  23. "time"
  24. "github.com/alibabacloud-go/debug/debug"
  25. util "github.com/alibabacloud-go/tea-utils/v2/service"
  26. "github.com/alibabacloud-go/tea/utils"
  27. "golang.org/x/net/proxy"
  28. )
  29. type RuntimeOptions = util.RuntimeOptions
  30. type ExtendsParameters = util.ExtendsParameters
  31. var debugLog = debug.Init("dara")
  32. type HttpRequest interface {
  33. }
  34. type HttpResponse interface {
  35. }
  36. type HttpClient interface {
  37. Call(request *http.Request, transport *http.Transport) (response *http.Response, err error)
  38. }
  39. type daraClient struct {
  40. sync.Mutex
  41. httpClient *http.Client
  42. ifInit bool
  43. }
  44. func (client *daraClient) Call(request *http.Request, transport *http.Transport) (response *http.Response, err error) {
  45. response, err = client.httpClient.Do(request)
  46. return
  47. }
  48. var hookDo = func(fn func(req *http.Request, transport *http.Transport) (*http.Response, error)) func(req *http.Request, transport *http.Transport) (*http.Response, error) {
  49. return fn
  50. }
  51. var basicTypes = []string{
  52. "int", "int16", "int64", "int32", "float32", "float64", "string", "bool", "uint64", "uint32", "uint16",
  53. }
  54. // Verify whether the parameters meet the requirements
  55. var validateParams = []string{"require", "pattern", "maxLength", "minLength", "maximum", "minimum", "maxItems", "minItems"}
  56. var clientPool = &sync.Map{}
  57. // Request is used wrap http request
  58. type Request struct {
  59. Protocol *string
  60. Port *int
  61. Method *string
  62. Pathname *string
  63. Domain *string
  64. Headers map[string]*string
  65. Query map[string]*string
  66. Body io.Reader
  67. }
  68. // Response is use d wrap http response
  69. type Response struct {
  70. Body io.ReadCloser
  71. StatusCode *int
  72. StatusMessage *string
  73. Headers map[string]*string
  74. }
  75. // RuntimeObject is used for converting http configuration
  76. type RuntimeObject struct {
  77. IgnoreSSL *bool `json:"ignoreSSL" xml:"ignoreSSL"`
  78. ReadTimeout *int `json:"readTimeout" xml:"readTimeout"`
  79. ConnectTimeout *int `json:"connectTimeout" xml:"connectTimeout"`
  80. IdleTimeout *int `json:"idleTimeout" xml:"idleTimeout"`
  81. LocalAddr *string `json:"localAddr" xml:"localAddr"`
  82. HttpProxy *string `json:"httpProxy" xml:"httpProxy"`
  83. HttpsProxy *string `json:"httpsProxy" xml:"httpsProxy"`
  84. NoProxy *string `json:"noProxy" xml:"noProxy"`
  85. MaxIdleConns *int `json:"maxIdleConns" xml:"maxIdleConns"`
  86. Key *string `json:"key" xml:"key"`
  87. Cert *string `json:"cert" xml:"cert"`
  88. Ca *string `json:"ca" xml:"ca"`
  89. Socks5Proxy *string `json:"socks5Proxy" xml:"socks5Proxy"`
  90. Socks5NetWork *string `json:"socks5NetWork" xml:"socks5NetWork"`
  91. Listener utils.ProgressListener `json:"listener" xml:"listener"`
  92. Tracker *utils.ReaderTracker `json:"tracker" xml:"tracker"`
  93. Logger *utils.Logger `json:"logger" xml:"logger"`
  94. RetryOptions *RetryOptions `json:"retryOptions" xml:"retryOptions"`
  95. ExtendsParameters *ExtendsParameters `json:"extendsParameters,omitempty" xml:"extendsParameters,omitempty"`
  96. HttpClient
  97. }
  98. func (r *RuntimeObject) getClientTag(domain string) string {
  99. return strconv.FormatBool(BoolValue(r.IgnoreSSL)) + strconv.Itoa(IntValue(r.ReadTimeout)) +
  100. strconv.Itoa(IntValue(r.ConnectTimeout)) + strconv.Itoa(IntValue(r.IdleTimeout)) + StringValue(r.LocalAddr) + StringValue(r.HttpProxy) +
  101. StringValue(r.HttpsProxy) + StringValue(r.NoProxy) + StringValue(r.Socks5Proxy) + StringValue(r.Socks5NetWork) + domain
  102. }
  103. // NewRuntimeObject is used for shortly create runtime object
  104. func NewRuntimeObject(runtime map[string]interface{}) *RuntimeObject {
  105. if runtime == nil {
  106. return &RuntimeObject{}
  107. }
  108. runtimeObject := &RuntimeObject{
  109. IgnoreSSL: TransInterfaceToBool(runtime["ignoreSSL"]),
  110. ReadTimeout: TransInterfaceToInt(runtime["readTimeout"]),
  111. ConnectTimeout: TransInterfaceToInt(runtime["connectTimeout"]),
  112. IdleTimeout: TransInterfaceToInt(runtime["idleTimeout"]),
  113. LocalAddr: TransInterfaceToString(runtime["localAddr"]),
  114. HttpProxy: TransInterfaceToString(runtime["httpProxy"]),
  115. HttpsProxy: TransInterfaceToString(runtime["httpsProxy"]),
  116. NoProxy: TransInterfaceToString(runtime["noProxy"]),
  117. MaxIdleConns: TransInterfaceToInt(runtime["maxIdleConns"]),
  118. Socks5Proxy: TransInterfaceToString(runtime["socks5Proxy"]),
  119. Socks5NetWork: TransInterfaceToString(runtime["socks5NetWork"]),
  120. Key: TransInterfaceToString(runtime["key"]),
  121. Cert: TransInterfaceToString(runtime["cert"]),
  122. Ca: TransInterfaceToString(runtime["ca"]),
  123. }
  124. if runtime["listener"] != nil {
  125. runtimeObject.Listener = runtime["listener"].(utils.ProgressListener)
  126. }
  127. if runtime["tracker"] != nil {
  128. runtimeObject.Tracker = runtime["tracker"].(*utils.ReaderTracker)
  129. }
  130. if runtime["logger"] != nil {
  131. runtimeObject.Logger = runtime["logger"].(*utils.Logger)
  132. }
  133. if runtime["httpClient"] != nil {
  134. runtimeObject.HttpClient = runtime["httpClient"].(HttpClient)
  135. }
  136. if runtime["retryOptions"] != nil {
  137. runtimeObject.RetryOptions = runtime["retryOptions"].(*RetryOptions)
  138. }
  139. return runtimeObject
  140. }
  141. // NewRequest is used shortly create Request
  142. func NewRequest() (req *Request) {
  143. return &Request{
  144. Headers: map[string]*string{},
  145. Query: map[string]*string{},
  146. }
  147. }
  148. // NewResponse is create response with http response
  149. func NewResponse(httpResponse *http.Response) (res *Response) {
  150. res = &Response{}
  151. res.Body = httpResponse.Body
  152. res.Headers = make(map[string]*string)
  153. res.StatusCode = Int(httpResponse.StatusCode)
  154. res.StatusMessage = String(httpResponse.Status)
  155. return
  156. }
  157. // Convert is use convert map[string]interface object to struct
  158. func Convert(in interface{}, out interface{}) error {
  159. byt, _ := json.Marshal(in)
  160. decoder := jsonParser.NewDecoder(bytes.NewReader(byt))
  161. decoder.UseNumber()
  162. err := decoder.Decode(&out)
  163. return err
  164. }
  165. // ConvertChan converts the source data to the target type and sends it to the specified channel.
  166. // @param src - source data
  167. // @param destChan - target channel
  168. // @return error - error during the conversion process
  169. func ConvertChan(src interface{}, destChan interface{}) error {
  170. destChanValue := reflect.ValueOf(destChan)
  171. if destChanValue.Kind() != reflect.Chan {
  172. return fmt.Errorf("destChan must be a channel")
  173. }
  174. if destChanValue.Type().ChanDir() == reflect.SendDir {
  175. return fmt.Errorf("destChan must be a receive or bidirectional channel")
  176. }
  177. elemType := destChanValue.Type().Elem()
  178. destValue := reflect.New(elemType).Interface()
  179. err := Convert(src, destValue)
  180. if err != nil {
  181. return err
  182. }
  183. destValueElem := reflect.ValueOf(destValue).Elem()
  184. defer func() {
  185. if r := recover(); r != nil {
  186. }
  187. }()
  188. destChanValue.TrySend(destValueElem)
  189. return nil
  190. }
  191. // Recover is used to format error
  192. func Recover(in interface{}) error {
  193. if in == nil {
  194. return nil
  195. }
  196. return errors.New(fmt.Sprint(in))
  197. }
  198. // ReadBody is used read response body
  199. func (response *Response) ReadBody() (body []byte, err error) {
  200. var buffer [512]byte
  201. defer response.Body.Close()
  202. result := bytes.NewBuffer(nil)
  203. for {
  204. n, err := response.Body.Read(buffer[0:])
  205. result.Write(buffer[0:n])
  206. if err != nil && err == io.EOF {
  207. break
  208. } else if err != nil {
  209. return nil, err
  210. }
  211. }
  212. return result.Bytes(), nil
  213. }
  214. func getDaraClient(tag string) *daraClient {
  215. client, ok := clientPool.Load(tag)
  216. if client == nil && !ok {
  217. client = &daraClient{
  218. httpClient: &http.Client{},
  219. ifInit: false,
  220. }
  221. clientPool.Store(tag, client)
  222. }
  223. return client.(*daraClient)
  224. }
  225. // DoRequest is used send request to server
  226. func DoRequest(request *Request, runtimeObject *RuntimeObject) (response *Response, err error) {
  227. if runtimeObject == nil {
  228. runtimeObject = &RuntimeObject{}
  229. }
  230. fieldMap := make(map[string]string)
  231. utils.InitLogMsg(fieldMap)
  232. defer func() {
  233. if runtimeObject.Logger != nil {
  234. runtimeObject.Logger.PrintLog(fieldMap, err)
  235. }
  236. }()
  237. if request.Method == nil {
  238. request.Method = String("GET")
  239. }
  240. if request.Protocol == nil {
  241. request.Protocol = String("http")
  242. } else {
  243. request.Protocol = String(strings.ToLower(StringValue(request.Protocol)))
  244. }
  245. requestURL := ""
  246. request.Domain = request.Headers["host"]
  247. if request.Port != nil {
  248. request.Domain = String(fmt.Sprintf("%s:%d", StringValue(request.Domain), IntValue(request.Port)))
  249. }
  250. requestURL = fmt.Sprintf("%s://%s%s", StringValue(request.Protocol), StringValue(request.Domain), StringValue(request.Pathname))
  251. queryParams := request.Query
  252. // sort QueryParams by key
  253. q := url.Values{}
  254. for key, value := range queryParams {
  255. q.Add(key, StringValue(value))
  256. }
  257. querystring := q.Encode()
  258. if len(querystring) > 0 {
  259. if strings.Contains(requestURL, "?") {
  260. requestURL = fmt.Sprintf("%s&%s", requestURL, querystring)
  261. } else {
  262. requestURL = fmt.Sprintf("%s?%s", requestURL, querystring)
  263. }
  264. }
  265. debugLog("> %s %s", StringValue(request.Method), requestURL)
  266. httpRequest, err := http.NewRequest(StringValue(request.Method), requestURL, request.Body)
  267. if err != nil {
  268. return
  269. }
  270. httpRequest.Host = StringValue(request.Domain)
  271. var client HttpClient
  272. if runtimeObject.HttpClient == nil {
  273. client = getDaraClient(runtimeObject.getClientTag(StringValue(request.Domain)))
  274. } else {
  275. client = runtimeObject.HttpClient
  276. }
  277. trans, err := getHttpTransport(request, runtimeObject)
  278. if err != nil {
  279. return
  280. }
  281. if defaultClient, ok := client.(*daraClient); ok {
  282. defaultClient.Lock()
  283. if !defaultClient.ifInit || defaultClient.httpClient.Transport == nil {
  284. defaultClient.httpClient.Transport = trans
  285. }
  286. defaultClient.httpClient.Timeout = time.Duration(IntValue(runtimeObject.ConnectTimeout)+IntValue(runtimeObject.ReadTimeout)) * time.Millisecond
  287. defaultClient.ifInit = true
  288. defaultClient.Unlock()
  289. }
  290. for key, value := range request.Headers {
  291. if value == nil || key == "content-length" {
  292. continue
  293. } else if key == "host" {
  294. httpRequest.Header["Host"] = []string{*value}
  295. delete(httpRequest.Header, "host")
  296. } else if key == "user-agent" {
  297. httpRequest.Header["User-Agent"] = []string{*value}
  298. delete(httpRequest.Header, "user-agent")
  299. } else {
  300. httpRequest.Header[key] = []string{*value}
  301. }
  302. debugLog("> %s: %s", key, StringValue(value))
  303. }
  304. contentlength, _ := strconv.Atoi(StringValue(request.Headers["content-length"]))
  305. event := utils.NewProgressEvent(utils.TransferStartedEvent, 0, int64(contentlength), 0)
  306. utils.PublishProgress(runtimeObject.Listener, event)
  307. putMsgToMap(fieldMap, httpRequest)
  308. startTime := time.Now()
  309. fieldMap["{start_time}"] = startTime.Format("2006-01-02 15:04:05")
  310. res, err := hookDo(client.Call)(httpRequest, trans)
  311. fieldMap["{cost}"] = time.Since(startTime).String()
  312. completedBytes := int64(0)
  313. if runtimeObject.Tracker != nil {
  314. completedBytes = runtimeObject.Tracker.CompletedBytes
  315. }
  316. if err != nil {
  317. event = utils.NewProgressEvent(utils.TransferFailedEvent, completedBytes, int64(contentlength), 0)
  318. utils.PublishProgress(runtimeObject.Listener, event)
  319. return
  320. }
  321. event = utils.NewProgressEvent(utils.TransferCompletedEvent, completedBytes, int64(contentlength), 0)
  322. utils.PublishProgress(runtimeObject.Listener, event)
  323. response = NewResponse(res)
  324. fieldMap["{code}"] = strconv.Itoa(res.StatusCode)
  325. fieldMap["{res_headers}"] = Stringify(res.Header)
  326. debugLog("< HTTP/1.1 %s", res.Status)
  327. for key, value := range res.Header {
  328. debugLog("< %s: %s", key, strings.Join(value, ""))
  329. if len(value) != 0 {
  330. response.Headers[strings.ToLower(key)] = String(value[0])
  331. }
  332. }
  333. return
  334. }
  335. func DoRequestWithCtx(ctx context.Context, request *Request, runtimeObject *RuntimeObject) (response *Response, err error) {
  336. if runtimeObject == nil {
  337. runtimeObject = &RuntimeObject{}
  338. }
  339. fieldMap := make(map[string]string)
  340. utils.InitLogMsg(fieldMap)
  341. defer func() {
  342. if runtimeObject.Logger != nil {
  343. runtimeObject.Logger.PrintLog(fieldMap, err)
  344. }
  345. }()
  346. if request.Method == nil {
  347. request.Method = String("GET")
  348. }
  349. if request.Protocol == nil {
  350. request.Protocol = String("http")
  351. } else {
  352. request.Protocol = String(strings.ToLower(StringValue(request.Protocol)))
  353. }
  354. requestURL := ""
  355. request.Domain = request.Headers["host"]
  356. if request.Port != nil {
  357. request.Domain = String(fmt.Sprintf("%s:%d", StringValue(request.Domain), IntValue(request.Port)))
  358. }
  359. requestURL = fmt.Sprintf("%s://%s%s", StringValue(request.Protocol), StringValue(request.Domain), StringValue(request.Pathname))
  360. queryParams := request.Query
  361. // sort QueryParams by key
  362. q := url.Values{}
  363. for key, value := range queryParams {
  364. q.Add(key, StringValue(value))
  365. }
  366. querystring := q.Encode()
  367. if len(querystring) > 0 {
  368. if strings.Contains(requestURL, "?") {
  369. requestURL = fmt.Sprintf("%s&%s", requestURL, querystring)
  370. } else {
  371. requestURL = fmt.Sprintf("%s?%s", requestURL, querystring)
  372. }
  373. }
  374. debugLog("> %s %s", StringValue(request.Method), requestURL)
  375. httpRequest, err := http.NewRequestWithContext(ctx, StringValue(request.Method), requestURL, request.Body)
  376. if err != nil {
  377. return
  378. }
  379. httpRequest.Host = StringValue(request.Domain)
  380. var client HttpClient
  381. if runtimeObject.HttpClient == nil {
  382. client = getDaraClient(runtimeObject.getClientTag(StringValue(request.Domain)))
  383. } else {
  384. client = runtimeObject.HttpClient
  385. }
  386. trans, err := getHttpTransport(request, runtimeObject)
  387. if err != nil {
  388. return
  389. }
  390. if defaultClient, ok := client.(*daraClient); ok {
  391. defaultClient.Lock()
  392. if !defaultClient.ifInit || defaultClient.httpClient.Transport == nil {
  393. defaultClient.httpClient.Transport = trans
  394. }
  395. defaultClient.httpClient.Timeout = time.Duration(IntValue(runtimeObject.ConnectTimeout)+IntValue(runtimeObject.ReadTimeout)) * time.Millisecond
  396. defaultClient.ifInit = true
  397. defaultClient.Unlock()
  398. }
  399. for key, value := range request.Headers {
  400. if value == nil || key == "content-length" {
  401. continue
  402. } else if key == "host" {
  403. httpRequest.Header["Host"] = []string{*value}
  404. delete(httpRequest.Header, "host")
  405. } else if key == "user-agent" {
  406. httpRequest.Header["User-Agent"] = []string{*value}
  407. delete(httpRequest.Header, "user-agent")
  408. } else {
  409. httpRequest.Header[key] = []string{*value}
  410. }
  411. debugLog("> %s: %s", key, StringValue(value))
  412. }
  413. contentlength, _ := strconv.Atoi(StringValue(request.Headers["content-length"]))
  414. event := utils.NewProgressEvent(utils.TransferStartedEvent, 0, int64(contentlength), 0)
  415. utils.PublishProgress(runtimeObject.Listener, event)
  416. putMsgToMap(fieldMap, httpRequest)
  417. startTime := time.Now()
  418. fieldMap["{start_time}"] = startTime.Format("2006-01-02 15:04:05")
  419. res, err := hookDo(client.Call)(httpRequest, trans)
  420. fieldMap["{cost}"] = time.Since(startTime).String()
  421. completedBytes := int64(0)
  422. if runtimeObject.Tracker != nil {
  423. completedBytes = runtimeObject.Tracker.CompletedBytes
  424. }
  425. if err != nil {
  426. select {
  427. case <-ctx.Done():
  428. err = TeaSDKError(ctx.Err())
  429. default:
  430. }
  431. event = utils.NewProgressEvent(utils.TransferFailedEvent, completedBytes, int64(contentlength), 0)
  432. utils.PublishProgress(runtimeObject.Listener, event)
  433. return
  434. }
  435. event = utils.NewProgressEvent(utils.TransferCompletedEvent, completedBytes, int64(contentlength), 0)
  436. utils.PublishProgress(runtimeObject.Listener, event)
  437. response = NewResponse(res)
  438. fieldMap["{code}"] = strconv.Itoa(res.StatusCode)
  439. fieldMap["{res_headers}"] = Stringify(res.Header)
  440. debugLog("< HTTP/1.1 %s", res.Status)
  441. for key, value := range res.Header {
  442. debugLog("< %s: %s", key, strings.Join(value, ""))
  443. if len(value) != 0 {
  444. response.Headers[strings.ToLower(key)] = String(value[0])
  445. }
  446. }
  447. return
  448. }
  449. func getHttpTransport(req *Request, runtime *RuntimeObject) (*http.Transport, error) {
  450. trans := new(http.Transport)
  451. trans.ResponseHeaderTimeout = time.Duration(IntValue(runtime.ReadTimeout)) * time.Millisecond
  452. httpProxy, err := getHttpProxy(StringValue(req.Protocol), StringValue(req.Domain), runtime)
  453. if err != nil {
  454. return nil, err
  455. }
  456. if strings.ToLower(*req.Protocol) == "https" {
  457. if BoolValue(runtime.IgnoreSSL) != true {
  458. trans.TLSClientConfig = &tls.Config{
  459. InsecureSkipVerify: false,
  460. }
  461. if runtime.Key != nil && runtime.Cert != nil && StringValue(runtime.Key) != "" && StringValue(runtime.Cert) != "" {
  462. cert, err := tls.X509KeyPair([]byte(StringValue(runtime.Cert)), []byte(StringValue(runtime.Key)))
  463. if err != nil {
  464. return nil, err
  465. }
  466. trans.TLSClientConfig.Certificates = []tls.Certificate{cert}
  467. }
  468. if runtime.Ca != nil && StringValue(runtime.Ca) != "" {
  469. clientCertPool := x509.NewCertPool()
  470. ok := clientCertPool.AppendCertsFromPEM([]byte(StringValue(runtime.Ca)))
  471. if !ok {
  472. return nil, errors.New("Failed to parse root certificate")
  473. }
  474. trans.TLSClientConfig.RootCAs = clientCertPool
  475. }
  476. } else {
  477. trans.TLSClientConfig = &tls.Config{
  478. InsecureSkipVerify: true,
  479. }
  480. }
  481. }
  482. if httpProxy != nil {
  483. trans.Proxy = http.ProxyURL(httpProxy)
  484. if httpProxy.User != nil {
  485. password, _ := httpProxy.User.Password()
  486. auth := httpProxy.User.Username() + ":" + password
  487. basic := "Basic " + base64.StdEncoding.EncodeToString([]byte(auth))
  488. req.Headers["Proxy-Authorization"] = String(basic)
  489. }
  490. }
  491. if runtime.Socks5Proxy != nil && StringValue(runtime.Socks5Proxy) != "" {
  492. socks5Proxy, err := getSocks5Proxy(runtime)
  493. if err != nil {
  494. return nil, err
  495. }
  496. if socks5Proxy != nil {
  497. var auth *proxy.Auth
  498. if socks5Proxy.User != nil {
  499. password, _ := socks5Proxy.User.Password()
  500. auth = &proxy.Auth{
  501. User: socks5Proxy.User.Username(),
  502. Password: password,
  503. }
  504. }
  505. dialer, err := proxy.SOCKS5(strings.ToLower(StringValue(runtime.Socks5NetWork)), socks5Proxy.Host, auth,
  506. &net.Dialer{
  507. Timeout: time.Duration(IntValue(runtime.ConnectTimeout)) * time.Millisecond,
  508. DualStack: true,
  509. LocalAddr: getLocalAddr(StringValue(runtime.LocalAddr)),
  510. })
  511. if err != nil {
  512. return nil, err
  513. }
  514. trans.Dial = dialer.Dial
  515. }
  516. } else {
  517. trans.DialContext = setDialContext(runtime)
  518. }
  519. if runtime.MaxIdleConns != nil && *runtime.MaxIdleConns > 0 {
  520. trans.MaxIdleConns = IntValue(runtime.MaxIdleConns)
  521. trans.MaxIdleConnsPerHost = IntValue(runtime.MaxIdleConns)
  522. }
  523. if runtime.IdleTimeout != nil && *runtime.IdleTimeout > 0 {
  524. trans.IdleConnTimeout = time.Duration(IntValue(runtime.IdleTimeout)) * time.Millisecond
  525. }
  526. return trans, nil
  527. }
  528. func putMsgToMap(fieldMap map[string]string, request *http.Request) {
  529. fieldMap["{host}"] = request.Host
  530. fieldMap["{method}"] = request.Method
  531. fieldMap["{uri}"] = request.URL.RequestURI()
  532. fieldMap["{pid}"] = strconv.Itoa(os.Getpid())
  533. fieldMap["{version}"] = strings.Split(request.Proto, "/")[1]
  534. hostname, _ := os.Hostname()
  535. fieldMap["{hostname}"] = hostname
  536. fieldMap["{req_headers}"] = Stringify(request.Header)
  537. fieldMap["{target}"] = request.URL.Path + request.URL.RawQuery
  538. }
  539. func getNoProxy(protocol string, runtime *RuntimeObject) []string {
  540. var urls []string
  541. if runtime.NoProxy != nil && StringValue(runtime.NoProxy) != "" {
  542. urls = strings.Split(StringValue(runtime.NoProxy), ",")
  543. } else if rawurl := os.Getenv("NO_PROXY"); rawurl != "" {
  544. urls = strings.Split(rawurl, ",")
  545. } else if rawurl := os.Getenv("no_proxy"); rawurl != "" {
  546. urls = strings.Split(rawurl, ",")
  547. }
  548. return urls
  549. }
  550. func ToReader(obj interface{}) io.Reader {
  551. switch obj.(type) {
  552. case string:
  553. tmp := obj.(string)
  554. return strings.NewReader(tmp)
  555. case *string:
  556. tmp := obj.(*string)
  557. return strings.NewReader(StringValue(tmp))
  558. case []byte:
  559. return strings.NewReader(string(obj.([]byte)))
  560. case io.Reader:
  561. return obj.(io.Reader)
  562. default:
  563. panic("Invalid Body. Please set a valid Body.")
  564. }
  565. }
  566. func ToWriter(obj interface{}) io.Writer {
  567. switch obj.(type) {
  568. case string:
  569. var buf bytes.Buffer
  570. buf.WriteString(obj.(string))
  571. return &buf
  572. case *string:
  573. var buf bytes.Buffer
  574. tmp := obj.(*string)
  575. buf.WriteString(*tmp)
  576. return &buf
  577. case []byte:
  578. var buf bytes.Buffer
  579. buf.Write(obj.([]byte))
  580. return &buf
  581. case io.Writer:
  582. return obj.(io.Writer)
  583. case *bytes.Buffer:
  584. return obj.(*bytes.Buffer)
  585. case *os.File:
  586. return obj.(*os.File)
  587. default:
  588. panic("Invalid Writer. Please provide a valid Writer.")
  589. }
  590. }
  591. func ToString(val interface{}) string {
  592. switch v := val.(type) {
  593. case []byte:
  594. return string(v) // 将 []byte 转换为字符串
  595. default:
  596. return fmt.Sprintf("%v", v) // 处理其他类型
  597. }
  598. }
  599. func getHttpProxy(protocol, host string, runtime *RuntimeObject) (proxy *url.URL, err error) {
  600. urls := getNoProxy(protocol, runtime)
  601. for _, url := range urls {
  602. if url == host {
  603. return nil, nil
  604. }
  605. }
  606. if protocol == "https" {
  607. if runtime.HttpsProxy != nil && StringValue(runtime.HttpsProxy) != "" {
  608. proxy, err = url.Parse(StringValue(runtime.HttpsProxy))
  609. } else if rawurl := os.Getenv("HTTPS_PROXY"); rawurl != "" {
  610. proxy, err = url.Parse(rawurl)
  611. } else if rawurl := os.Getenv("https_proxy"); rawurl != "" {
  612. proxy, err = url.Parse(rawurl)
  613. }
  614. } else {
  615. if runtime.HttpProxy != nil && StringValue(runtime.HttpProxy) != "" {
  616. proxy, err = url.Parse(StringValue(runtime.HttpProxy))
  617. } else if rawurl := os.Getenv("HTTP_PROXY"); rawurl != "" {
  618. proxy, err = url.Parse(rawurl)
  619. } else if rawurl := os.Getenv("http_proxy"); rawurl != "" {
  620. proxy, err = url.Parse(rawurl)
  621. }
  622. }
  623. return proxy, err
  624. }
  625. func getSocks5Proxy(runtime *RuntimeObject) (proxy *url.URL, err error) {
  626. if runtime.Socks5Proxy != nil && StringValue(runtime.Socks5Proxy) != "" {
  627. proxy, err = url.Parse(StringValue(runtime.Socks5Proxy))
  628. }
  629. return proxy, err
  630. }
  631. func getLocalAddr(localAddr string) (addr *net.TCPAddr) {
  632. if localAddr != "" {
  633. addr = &net.TCPAddr{
  634. IP: net.ParseIP(localAddr),
  635. }
  636. }
  637. return addr
  638. }
  639. func setDialContext(runtime *RuntimeObject) func(cxt context.Context, net, addr string) (c net.Conn, err error) {
  640. return func(ctx context.Context, network, address string) (net.Conn, error) {
  641. timeout := time.Duration(IntValue(runtime.ConnectTimeout)) * time.Millisecond
  642. dialer := &net.Dialer{
  643. Timeout: timeout,
  644. Resolver: &net.Resolver{
  645. PreferGo: false,
  646. },
  647. }
  648. if runtime.LocalAddr != nil && StringValue(runtime.LocalAddr) != "" {
  649. dialer.LocalAddr = getLocalAddr(StringValue(runtime.LocalAddr))
  650. }
  651. return dialer.DialContext(ctx, network, address)
  652. }
  653. }
  654. func ToObject(obj interface{}) map[string]interface{} {
  655. result := make(map[string]interface{})
  656. byt, _ := json.Marshal(obj)
  657. err := json.Unmarshal(byt, &result)
  658. if err != nil {
  659. return nil
  660. }
  661. return result
  662. }
  663. func AllowRetry(retry interface{}, retryTimes *int) *bool {
  664. if IntValue(retryTimes) == 0 {
  665. return Bool(true)
  666. }
  667. retryMap, ok := retry.(map[string]interface{})
  668. if !ok {
  669. return Bool(false)
  670. }
  671. retryable, ok := retryMap["retryable"].(bool)
  672. if !ok || !retryable {
  673. return Bool(false)
  674. }
  675. maxAttempts, ok := retryMap["maxAttempts"].(int)
  676. if !ok || maxAttempts < IntValue(retryTimes) {
  677. return Bool(false)
  678. }
  679. return Bool(true)
  680. }
  681. func Merge(args ...interface{}) map[string]*string {
  682. finalArg := make(map[string]*string)
  683. for _, obj := range args {
  684. switch obj.(type) {
  685. case map[string]*string:
  686. arg := obj.(map[string]*string)
  687. for key, value := range arg {
  688. if value != nil {
  689. finalArg[key] = value
  690. }
  691. }
  692. default:
  693. byt, _ := json.Marshal(obj)
  694. arg := make(map[string]string)
  695. err := json.Unmarshal(byt, &arg)
  696. if err != nil {
  697. return finalArg
  698. }
  699. for key, value := range arg {
  700. if value != "" {
  701. finalArg[key] = String(value)
  702. }
  703. }
  704. }
  705. }
  706. return finalArg
  707. }
  708. func IsNil(val interface{}) bool {
  709. defer func() {
  710. recover()
  711. }()
  712. if val == nil {
  713. return true
  714. }
  715. v := reflect.ValueOf(val)
  716. if v.Kind() == reflect.Ptr || v.Kind() == reflect.Slice || v.Kind() == reflect.Map {
  717. return v.IsNil()
  718. }
  719. valType := reflect.TypeOf(val)
  720. valZero := reflect.Zero(valType)
  721. return valZero == v
  722. }
  723. func isNil(a interface{}) bool {
  724. defer func() {
  725. recover()
  726. }()
  727. vi := reflect.ValueOf(a)
  728. return vi.IsNil()
  729. }
  730. func isNilOrZero(value interface{}) bool {
  731. if value == nil {
  732. return true
  733. }
  734. v := reflect.ValueOf(value)
  735. switch v.Kind() {
  736. case reflect.Chan, reflect.Func, reflect.Map, reflect.Ptr, reflect.Interface, reflect.Slice:
  737. return v.IsNil()
  738. default:
  739. // Check for zero value
  740. return reflect.DeepEqual(value, reflect.Zero(v.Type()).Interface())
  741. }
  742. }
  743. func Default(inputValue interface{}, defaultValue interface{}) (_result interface{}) {
  744. if isNilOrZero(inputValue) {
  745. _result = defaultValue
  746. return _result
  747. }
  748. _result = inputValue
  749. return _result
  750. }
  751. func ToMap(args ...interface{}) map[string]interface{} {
  752. isNotNil := false
  753. finalArg := make(map[string]interface{})
  754. for _, obj := range args {
  755. if obj == nil {
  756. continue
  757. }
  758. if isNil(obj) {
  759. continue
  760. }
  761. isNotNil = true
  762. switch obj.(type) {
  763. case map[string]*string:
  764. arg := obj.(map[string]*string)
  765. for key, value := range arg {
  766. if value != nil {
  767. finalArg[key] = StringValue(value)
  768. }
  769. }
  770. case map[string]interface{}:
  771. arg := obj.(map[string]interface{})
  772. for key, value := range arg {
  773. if value != nil {
  774. finalArg[key] = value
  775. }
  776. }
  777. case *string:
  778. str := obj.(*string)
  779. arg := make(map[string]interface{})
  780. err := json.Unmarshal([]byte(StringValue(str)), &arg)
  781. if err == nil {
  782. for key, value := range arg {
  783. if value != nil {
  784. finalArg[key] = value
  785. }
  786. }
  787. }
  788. tmp := make(map[string]string)
  789. err = json.Unmarshal([]byte(StringValue(str)), &tmp)
  790. if err == nil {
  791. for key, value := range arg {
  792. if value != "" {
  793. finalArg[key] = value
  794. }
  795. }
  796. }
  797. case []byte:
  798. byt := obj.([]byte)
  799. arg := make(map[string]interface{})
  800. err := json.Unmarshal(byt, &arg)
  801. if err == nil {
  802. for key, value := range arg {
  803. if value != nil {
  804. finalArg[key] = value
  805. }
  806. }
  807. break
  808. }
  809. default:
  810. val := reflect.ValueOf(obj)
  811. if val.Kind().String() == "map" {
  812. tmp := val.MapKeys()
  813. for _, key := range tmp {
  814. finalArg[key.String()] = val.MapIndex(key).Interface()
  815. }
  816. } else {
  817. res := structToMap(val)
  818. for key, value := range res {
  819. if value != nil {
  820. finalArg[key] = value
  821. }
  822. }
  823. }
  824. }
  825. }
  826. if !isNotNil {
  827. return nil
  828. }
  829. return finalArg
  830. }
  831. func structToMap(dataValue reflect.Value) map[string]interface{} {
  832. out := make(map[string]interface{})
  833. if !dataValue.IsValid() {
  834. return out
  835. }
  836. if dataValue.Kind().String() == "ptr" {
  837. if dataValue.IsNil() {
  838. return out
  839. }
  840. dataValue = dataValue.Elem()
  841. }
  842. if !dataValue.IsValid() {
  843. return out
  844. }
  845. dataType := dataValue.Type()
  846. if dataType.Kind().String() != "struct" {
  847. return out
  848. }
  849. for i := 0; i < dataType.NumField(); i++ {
  850. field := dataType.Field(i)
  851. name, containsNameTag := field.Tag.Lookup("json")
  852. if !containsNameTag {
  853. name = field.Name
  854. } else {
  855. strs := strings.Split(name, ",")
  856. name = strs[0]
  857. }
  858. fieldValue := dataValue.FieldByName(field.Name)
  859. if !fieldValue.IsValid() || fieldValue.IsNil() {
  860. continue
  861. }
  862. if field.Type.String() == "io.Reader" || field.Type.String() == "io.Writer" {
  863. continue
  864. } else if field.Type.Kind().String() == "struct" {
  865. out[name] = structToMap(fieldValue)
  866. } else if field.Type.Kind().String() == "ptr" &&
  867. field.Type.Elem().Kind().String() == "struct" {
  868. if fieldValue.Elem().IsValid() {
  869. out[name] = structToMap(fieldValue)
  870. }
  871. } else if field.Type.Kind().String() == "ptr" {
  872. if fieldValue.IsValid() && !fieldValue.IsNil() {
  873. out[name] = fieldValue.Elem().Interface()
  874. }
  875. } else if field.Type.Kind().String() == "slice" {
  876. tmp := make([]interface{}, 0)
  877. num := fieldValue.Len()
  878. for i := 0; i < num; i++ {
  879. value := fieldValue.Index(i)
  880. if !value.IsValid() {
  881. continue
  882. }
  883. if value.Type().Kind().String() == "ptr" &&
  884. value.Type().Elem().Kind().String() == "struct" {
  885. if value.IsValid() && !value.IsNil() {
  886. tmp = append(tmp, structToMap(value))
  887. }
  888. } else if value.Type().Kind().String() == "struct" {
  889. tmp = append(tmp, structToMap(value))
  890. } else if value.Type().Kind().String() == "ptr" {
  891. if value.IsValid() && !value.IsNil() {
  892. tmp = append(tmp, value.Elem().Interface())
  893. }
  894. } else {
  895. tmp = append(tmp, value.Interface())
  896. }
  897. }
  898. if len(tmp) > 0 {
  899. out[name] = tmp
  900. }
  901. } else {
  902. out[name] = fieldValue.Interface()
  903. }
  904. }
  905. return out
  906. }
  907. func GetBackoffTime(backoff interface{}, retrytimes *int) *int {
  908. backoffMap, ok := backoff.(map[string]interface{})
  909. if !ok {
  910. return Int(0)
  911. }
  912. policy, ok := backoffMap["policy"].(string)
  913. if !ok || policy == "no" {
  914. return Int(0)
  915. }
  916. period, ok := backoffMap["period"].(int)
  917. if !ok || period == 0 {
  918. return Int(0)
  919. }
  920. maxTime := math.Pow(2.0, float64(IntValue(retrytimes)))
  921. return Int(rand.Intn(int(maxTime-1)) * period)
  922. }
  923. func Sleep(backoffTime int) {
  924. sleeptime := time.Duration(backoffTime) * time.Second
  925. time.Sleep(sleeptime)
  926. }
  927. // Determines whether realType is in filterTypes
  928. func isFilterType(realType string, filterTypes []string) bool {
  929. for _, value := range filterTypes {
  930. if value == realType {
  931. return true
  932. }
  933. }
  934. return false
  935. }
  936. func TransInterfaceToBool(val interface{}) *bool {
  937. if val == nil {
  938. return nil
  939. }
  940. return Bool(val.(bool))
  941. }
  942. func TransInterfaceToInt(val interface{}) *int {
  943. if val == nil {
  944. return nil
  945. }
  946. return Int(val.(int))
  947. }
  948. func TransInterfaceToString(val interface{}) *string {
  949. if val == nil {
  950. return nil
  951. }
  952. return String(val.(string))
  953. }
  954. func Prettify(i interface{}) string {
  955. resp, _ := json.MarshalIndent(i, "", " ")
  956. return string(resp)
  957. }
  958. func ToInt(a *int32) *int {
  959. return Int(int(Int32Value(a)))
  960. }
  961. func ToInt32(a *int) *int32 {
  962. return Int32(int32(IntValue(a)))
  963. }
  964. func ToBytes(s, encodingType string) []byte {
  965. switch encodingType {
  966. case "utf8":
  967. return []byte(s)
  968. case "base64":
  969. data, err := base64.StdEncoding.DecodeString(s)
  970. if err != nil {
  971. return nil
  972. }
  973. return data
  974. case "hex":
  975. data, err := hex.DecodeString(s)
  976. if err != nil {
  977. return nil
  978. }
  979. return data
  980. default:
  981. return nil
  982. }
  983. }
  984. func BytesFromString(str string, typeStr string) []byte {
  985. switch typeStr {
  986. case "utf8":
  987. return []byte(str)
  988. case "hex":
  989. bytes, err := hex.DecodeString(str)
  990. if err == nil {
  991. return bytes
  992. }
  993. case "base64":
  994. bytes, err := base64.StdEncoding.DecodeString(str)
  995. if err == nil {
  996. return bytes
  997. }
  998. }
  999. // 对于不支持的类型或解码失败,返回 nil
  1000. return nil
  1001. }
  1002. func ForceInt(a interface{}) int {
  1003. num, _ := a.(int)
  1004. return num
  1005. }
  1006. func ForceBoolean(a interface{}) bool {
  1007. b, _ := a.(bool)
  1008. return b
  1009. }
  1010. func ForceInt64(a interface{}) int64 {
  1011. b, _ := a.(int64)
  1012. return b
  1013. }
  1014. func ForceUint64(a interface{}) uint64 {
  1015. b, _ := a.(uint64)
  1016. return b
  1017. }
  1018. // ForceInt32 attempts to assert that a is of type int32.
  1019. func ForceInt32(a interface{}) int32 {
  1020. b, _ := a.(int32)
  1021. return b
  1022. }
  1023. // ForceUInt32 attempts to assert that a is of type uint32.
  1024. func ForceUInt32(a interface{}) uint32 {
  1025. b, _ := a.(uint32)
  1026. return b
  1027. }
  1028. // ForceInt16 attempts to assert that a is of type int16.
  1029. func ForceInt16(a interface{}) int16 {
  1030. b, _ := a.(int16)
  1031. return b
  1032. }
  1033. // ForceUInt16 attempts to assert that a is of type uint16.
  1034. func ForceUInt16(a interface{}) uint16 {
  1035. b, _ := a.(uint16)
  1036. return b
  1037. }
  1038. // ForceInt8 attempts to assert that a is of type int8.
  1039. func ForceInt8(a interface{}) int8 {
  1040. b, _ := a.(int8)
  1041. return b
  1042. }
  1043. // ForceUInt8 attempts to assert that a is of type uint8.
  1044. func ForceUInt8(a interface{}) uint8 {
  1045. b, _ := a.(uint8)
  1046. return b
  1047. }
  1048. // ForceFloat32 attempts to assert that a is of type float32.
  1049. func ForceFloat32(a interface{}) float32 {
  1050. b, _ := a.(float32)
  1051. return b
  1052. }
  1053. // ForceFloat64 attempts to assert that a is of type float64.
  1054. func ForceFloat64(a interface{}) float64 {
  1055. b, _ := a.(float64)
  1056. return b
  1057. }