request_windows.go 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588
  1. //go:build windows
  2. package yu_curl
  3. import (
  4. yu_http "gogs.qqck.cn/s/tools/http"
  5. yu_strings "gogs.qqck.cn/s/tools/strings"
  6. yu_sys "gogs.qqck.cn/s/tools/sys"
  7. "runtime"
  8. "strings"
  9. "unsafe"
  10. )
  11. // Request
  12. // @Description: 请求对象
  13. type Request struct {
  14. curl uintptr
  15. perform uintptr
  16. headers map[string]string
  17. headers_setopt bool
  18. headers_list uintptr
  19. useragent string
  20. referer string
  21. cookies map[string]string
  22. cookies_setopt bool
  23. cookies_updata bool
  24. connect_to map[string]string
  25. connect_to_setopt bool
  26. connect_to_list uintptr
  27. // -------------------------------------------------------------------resp
  28. resp_body []byte
  29. resp_headers_raw []byte
  30. resp_headers map[string]string
  31. resp_cookies map[string]string
  32. }
  33. // NewRequest
  34. //
  35. // @Description: 创建请求对象
  36. func NewRequest() (t *Request) {
  37. t = &Request{}
  38. runtime.SetFinalizer(t, _finalizer)
  39. t.curl, _, _ = curl_easy_init.Call()
  40. curl_easy_setopt.Call(t.curl, OPT_NOSIGNAL, 1)
  41. curl_easy_setopt.Call(t.curl, OPT_SUPPRESS_CONNECT_HEADERS, 1)
  42. curl_easy_setopt.Call(t.curl, OPT_PREREQFUNCTION, callback_PREREQFUNCTION_ptr)
  43. curl_easy_setopt.Call(t.curl, OPT_PREREQDATA, unsafe.Pointer(t))
  44. curl_easy_setopt.Call(t.curl, OPT_HEADERFUNCTION, callback_HEADERFUNCTION_ptr)
  45. curl_easy_setopt.Call(t.curl, OPT_HEADERDATA, unsafe.Pointer(t))
  46. curl_easy_setopt.Call(t.curl, OPT_WRITEFUNCTION, callback_WRITEFUNCTION_ptr)
  47. curl_easy_setopt.Call(t.curl, OPT_WRITEDATA, unsafe.Pointer(t))
  48. // ------------------------------------------------init
  49. t.SetRdirect(true)
  50. t.SetSslVerifyPeer(false)
  51. t.SetTimeout(60000)
  52. return
  53. }
  54. func _finalizer(t *Request) {
  55. t.Close()
  56. }
  57. // Close
  58. //
  59. // @Description: 关闭并销毁请求对象
  60. func (t *Request) Close() {
  61. if t.curl != 0 {
  62. curl_easy_cleanup.Call(t.curl)
  63. t.curl = 0
  64. }
  65. t.headers = nil
  66. if t.headers_list != 0 {
  67. curl_slist_free_all.Call(t.headers_list)
  68. t.headers_list = 0
  69. }
  70. t.cookies = nil
  71. t.connect_to = nil
  72. if t.connect_to_list != 0 {
  73. curl_slist_free_all.Call(t.connect_to_list)
  74. t.connect_to_list = 0
  75. }
  76. t.resp_body = nil
  77. t.resp_headers_raw = nil
  78. t.resp_headers = nil
  79. t.resp_cookies = nil
  80. }
  81. func (t *Request) opt() {
  82. if t.headers_setopt {
  83. if t.headers_list != 0 {
  84. curl_slist_free_all.Call(t.headers_list)
  85. t.headers_list = 0
  86. curl_easy_setopt.Call(t.curl, OPT_HTTPHEADER, 0)
  87. }
  88. for j_key, j_val := range t.headers {
  89. t.headers_list, _, _ = curl_slist_append.Call(t.headers_list, yu_sys.S{yu_sys.Gbk, j_key + ":" + j_val})
  90. }
  91. curl_easy_setopt.Call(t.curl, OPT_HTTPHEADER, t.headers_list)
  92. t.headers_setopt = false
  93. }
  94. if t.cookies_setopt {
  95. curl_easy_setopt.Call(t.curl, OPT_COOKIE, yu_sys.S{yu_sys.Gbk, t.GetCookies()})
  96. t.cookies_setopt = false
  97. }
  98. if t.connect_to_setopt {
  99. if t.connect_to_list != 0 {
  100. curl_slist_free_all.Call(t.connect_to_list)
  101. t.connect_to_list = 0
  102. }
  103. for j_host, j_to := range t.connect_to {
  104. t.connect_to_list, _, _ = curl_slist_append.Call(t.connect_to_list, yu_sys.S{yu_sys.Gbk, j_host + ":" + j_to})
  105. }
  106. curl_easy_setopt.Call(t.curl, OPT_CONNECT_TO, t.connect_to_list)
  107. t.connect_to_setopt = false
  108. }
  109. }
  110. // -----------------------------------------------------------------------------------------------------------------------------------------------Headers
  111. // SetHeader
  112. //
  113. // @Description: 设置单个协议头
  114. func (t *Request) SetHeader(name, value string) *Request {
  115. name = yu_http.Normalize(name)
  116. if name == "Cookie" {
  117. t.SetCookies(value)
  118. } else if name == "User-Agent" {
  119. t.SetUserAgent(value)
  120. } else if name == "Referer" {
  121. t.SetReferer(value)
  122. } else {
  123. if t.headers == nil {
  124. t.headers = make(map[string]string)
  125. }
  126. if value == "" {
  127. t.headers[name] = " " // " " 才可以删除
  128. } else {
  129. t.headers[name] = value
  130. }
  131. t.headers_setopt = true
  132. }
  133. return t
  134. }
  135. // SetHeaders
  136. //
  137. // @Description: 清空之前的协议头并设置新的协议头
  138. func (t *Request) SetHeaders(headers string) *Request {
  139. if headers == "" {
  140. t.headers = nil
  141. t.headers_setopt = true
  142. } else {
  143. t.headers = make(map[string]string)
  144. t.AddHeaders(headers)
  145. }
  146. return t
  147. }
  148. // AddHeaders
  149. //
  150. // @Description: 保留之前的协议头并添加新的协议头
  151. func (t *Request) AddHeaders(headers string) *Request {
  152. if headers != "" {
  153. var j_headers []string
  154. if strings.Index(headers, "\r\n") > -1 {
  155. j_headers = strings.Split(headers, "\r\n")
  156. } else if strings.Index(headers, "\n") > -1 {
  157. j_headers = strings.Split(headers, "\n")
  158. }
  159. for j_i := 0; j_i < len(j_headers); j_i++ {
  160. j_key, j_value := yu_strings.Left(j_headers[j_i], ":"), yu_strings.EmptyLeft(yu_strings.Right(j_headers[j_i], ":"))
  161. if j_key == "" && j_value == "" {
  162. if j_header := yu_strings.EmptyRight(j_headers[j_i]); strings.HasSuffix(j_header, ";") {
  163. t.SetHeader(j_header, "")
  164. }
  165. } else if j_key != "" {
  166. t.SetHeader(j_key, j_value)
  167. }
  168. }
  169. }
  170. return t
  171. }
  172. // GetHeader
  173. //
  174. // @Description: 获取单个协议头
  175. func (t *Request) GetHeader(name string) string {
  176. name = yu_http.Normalize(name)
  177. if name == "Cookie" {
  178. return t.GetCookies()
  179. } else if name == "User-Agent" {
  180. return t.GetUserAgent()
  181. } else if name == "Referer" {
  182. return t.GetReferer()
  183. } else {
  184. if t.headers[name] == " " {
  185. return ""
  186. }
  187. return t.headers[name]
  188. }
  189. }
  190. // GetHeaders
  191. //
  192. // @Description: 获取全部协议头
  193. func (t *Request) GetHeaders() string {
  194. if len(t.headers) == 0 {
  195. return ""
  196. }
  197. j_headers := make([]byte, 0, 4096)
  198. for j_name, j_value := range t.headers {
  199. j_headers = append(j_headers, j_name...)
  200. j_headers = append(j_headers, ':')
  201. j_headers = append(j_headers, ' ')
  202. j_headers = append(j_headers, j_value...)
  203. j_headers = append(j_headers, 13, 10)
  204. }
  205. return string(j_headers)
  206. }
  207. // -----------------------------------------------------------------------------------------------------------------------------------------------Content-Type
  208. // SetContentType
  209. //
  210. // @Description: 设置提交的"ContentType"类型
  211. func (t *Request) SetContentType(value string) *Request {
  212. t.SetHeader("Content-Type", value)
  213. return t
  214. }
  215. // -----------------------------------------------------------------------------------------------------------------------------------------------Headers-Utils
  216. // SetUserAgent
  217. //
  218. // @Description: 设置请求的 UserAgent
  219. func (t *Request) SetUserAgent(value string) *Request {
  220. t.useragent = value
  221. curl_easy_setopt.Call(t.curl, OPT_USERAGENT, yu_sys.S{yu_sys.Gbk, t.useragent})
  222. return t
  223. }
  224. // GetUserAgent
  225. //
  226. // @Description: 获取请求的 UserAgent
  227. func (t *Request) GetUserAgent() string {
  228. return t.useragent
  229. }
  230. // SetReferer
  231. //
  232. // @Description: 设置来路地址
  233. func (t *Request) SetReferer(value string) *Request {
  234. t.referer = value
  235. curl_easy_setopt.Call(t.curl, OPT_REFERER, yu_sys.S{yu_sys.Gbk, t.referer})
  236. return t
  237. }
  238. // GetReferer
  239. //
  240. // @Description: 获取来路地址
  241. func (t *Request) GetReferer() string {
  242. return t.referer
  243. }
  244. // SetAutoReferer
  245. //
  246. // @Description: 自动更新引用标头,启用后,会自动将 HTTP 请求中的 Referer: 标头字段设置为完整的 URL,它位于 Location: 重定向之后。默认为:false, 禁用
  247. func (t *Request) SetAutoReferer(enable bool) *Request {
  248. curl_easy_setopt.Call(t.curl, OPT_AUTOREFERER, enable)
  249. return t
  250. }
  251. // -----------------------------------------------------------------------------------------------------------------------------------------------Cookies
  252. // SetCookie
  253. //
  254. // @Description: 设置单个 Cookie
  255. func (t *Request) SetCookie(name, value string) *Request {
  256. if value == "" {
  257. delete(t.cookies, name)
  258. } else {
  259. if t.cookies == nil {
  260. t.cookies = make(map[string]string)
  261. }
  262. t.cookies[name] = value
  263. }
  264. t.cookies_setopt = true
  265. return t
  266. }
  267. // SetCookies
  268. //
  269. // @Description: 清空之前的 Cookies 并设置新的 Cookies
  270. func (t *Request) SetCookies(value string) *Request {
  271. if value == "" {
  272. t.cookies = nil
  273. t.cookies_setopt = true
  274. } else {
  275. t.cookies = make(map[string]string)
  276. t.AddCookies(value)
  277. }
  278. return t
  279. }
  280. // AddCookies
  281. //
  282. // @Description: 保留之前的 Cookies 并增加新的 Cookies
  283. func (t *Request) AddCookies(val string) *Request {
  284. if val != "" {
  285. for _, j_cookie := range strings.Split(val, ";") {
  286. if j_key, j_val := yu_strings.Left(j_cookie, "="), yu_strings.Empty(yu_strings.Right(j_cookie, "=")); j_key != "" {
  287. t.SetCookie(j_key, j_val)
  288. }
  289. }
  290. }
  291. return t
  292. }
  293. // GetCookie
  294. //
  295. // @Description: 获取单个 Cookie
  296. func (t *Request) GetCookie(name string) string {
  297. return t.cookies[name]
  298. }
  299. // GetCookies
  300. //
  301. // @Description: 获取全部 Cookie
  302. func (t *Request) GetCookies() string {
  303. if len(t.cookies) == 0 {
  304. return ""
  305. }
  306. j_cookies := make([]byte, 0, 1024)
  307. for j_name, j_value := range t.cookies {
  308. j_cookies = append(j_cookies, j_name...)
  309. j_cookies = append(j_cookies, '=')
  310. j_cookies = append(j_cookies, j_value...)
  311. j_cookies = append(j_cookies, ';')
  312. j_cookies = append(j_cookies, ' ')
  313. }
  314. return string(j_cookies)
  315. }
  316. // SetAutoCookies
  317. //
  318. // @Description: 设置自动合并更新Cookies,初始值为"false"
  319. func (t *Request) SetAutoCookies(enable bool) *Request {
  320. t.cookies_updata = enable
  321. return t
  322. }
  323. // -----------------------------------------------------------------------------------------------------------------------------------------------Utils
  324. // SetTimeout
  325. //
  326. // @Description: 设置整个请求的超时,单位:毫秒,默认超时为 60000(60秒),设置为零这意味着它在传输过程中永远不会超时。
  327. func (t *Request) SetTimeout(s int) *Request {
  328. if s < 0 {
  329. s = 0
  330. }
  331. curl_easy_setopt.Call(t.curl, OPT_TIMEOUT_MS, s)
  332. return t
  333. }
  334. // SetRdirect
  335. //
  336. // @Description: 是否遵循 HTTP 3xx 重定向,默认:true
  337. func (t *Request) SetRdirect(enable bool) *Request {
  338. curl_easy_setopt.Call(t.curl, OPT_FOLLOWLOCATION, enable)
  339. return t
  340. }
  341. // SetProxy 设置代理
  342. //
  343. // @Description:
  344. // @param proxy 格式 ProxyType://user:pass@host:port,ProxyType: http, socks4, socks4a, socks5, socks5h,设置为""以取消代理
  345. func (t *Request) SetProxy(proxy string) *Request {
  346. curl_easy_setopt.Call(t.curl, OPT_PROXY, yu_sys.S{yu_sys.Gbk, proxy})
  347. return t
  348. }
  349. // SetMaxConnects
  350. //
  351. // @Description: 设置的数量将是 libcurl 可以在与此句柄关联的池中缓存的同时打开的最大持久连接数。默认值为 5,更改此值没有多大意义,
  352. // 除非您完全了解它的工作原理并更改 libcurl 的行为。这涉及使用任何支持持久连接的协议的连接。
  353. // 当达到最大限制时,curl 会关闭缓存中最早的一个,以防止增加打开的连接数。
  354. // 如果您已经使用此 curl 句柄执行传输,则设置比以前更小的CURLOPT_MAXCONNECTS可能会导致打开的连接不必要地关闭。
  355. // 如果将此简单句柄添加到多句柄,则不会确认此设置,您必须改为使用curl_multi_setopt和CURLMOPT_MAXCONNECTS选项。
  356. // 默认5个
  357. // @param s
  358. func (t *Request) SetMaxConnects(s int) *Request {
  359. if s < 0 {
  360. s = 0
  361. }
  362. curl_easy_setopt.Call(t.curl, OPT_MAXCONNECTS, s)
  363. return t
  364. }
  365. // SetSslVerifyPeer
  366. //
  367. // @Description: 验证 SSL 证书,默认为:false
  368. func (t *Request) SetSslVerifyPeer(enable bool) *Request {
  369. curl_easy_setopt.Call(t.curl, OPT_SSL_VERIFYPEER, enable)
  370. return t
  371. }
  372. // SetSslVerifyHost
  373. //
  374. // @Description: 验证 SSL 证书中的主机名
  375. // 指定要验证的内容。
  376. // 此选项确定是否验证服务器证书是否适用于已知的服务器。
  377. // 在协商TLS和SSL连接时,服务器会发送一个表明其身份的证书。
  378. // 当为2时,该证书必须表明服务器是您要连接的服务器,否则连接失败。简单地说,这意味着它必须在证书中与您操作的URL中具有相同的名称。
  379. // 当证书中的“通用名称”字段或“使用者备用名称”字段与您要求Curl连接的URL中的主机名匹配时,Curl认为服务器是预期的服务器。
  380. // 如果验证值设置为1:
  381. // 在7.28.0及更早版本中:被视为某种调试选项,由于经常导致程序员错误而不再受支持。
  382. // 从7.28.1到7.65.3:将其设置为1则无效,并保持标志不变。
  383. // 从7.66.0开始:对1和2进行相同处理。
  384. // 当验证值为0时,无论证书中的名称如何,连接都会成功。小心使用这个能力!
  385. // 此选项的默认值为 2。
  386. // 此选项控制检查服务器证书声明的身份。服务器可能在撒谎。要控制说谎,请参见 "SetSslVerifyPeer"。
  387. func (t *Request) SetSslVerifyHost(verify uintptr) *Request {
  388. curl_easy_setopt.Call(t.curl, OPT_SSL_VERIFYHOST, verify)
  389. return t
  390. }
  391. // SetHttplVersion
  392. //
  393. // @Description: 传递一个长版本,设置为下面描述的值之一。他们要求 libcurl 使用特定的 HTTP 版本。
  394. // HTTP_VERSION_NONE
  395. // 我们不关心库使用什么版本。libcurl 将使用它认为合适的任何内容。
  396. //
  397. // HTTP_VERSION_1_0
  398. // 强制执行 HTTP 1.0 请求。
  399. //
  400. // HTTP_VERSION_1_1
  401. // 执行 HTTP 1.1 请求。
  402. //
  403. // HTTP_VERSION_2_0
  404. // 尝试 HTTP 2 请求。如果无法与服务器协商 HTTP 2,libcurl 将退回到 HTTP 1.1。(在 7.33.0 中添加)
  405. //
  406. // 当 libcurl 在 HTTPS 上使用 HTTP/2 时,它本身并不坚持使用 TLS 1.2 或更高版本,即使这是规范所要求的。用户可以使用CURLOPT_SSLVERSION添加此版本要求。
  407. // 在 7.43.0 中添加了别名CURL_HTTP_VERSION_2以更好地反映实际的协议名称。
  408. //
  409. // HTTP_VERSION_2TLS
  410. // 仅尝试通过 TLS (HTTPS) 的 HTTP 2。如果无法与 HTTPS 服务器协商 HTTP 2,libcurl 将回退到 HTTP 1.1。对于明文 HTTP 服务器,libcurl 将使用 1.1。(在 7.47.0 中添加)
  411. //
  412. // HTTP_VERSION_2_PRIOR_KNOWLEDGE
  413. // 在没有 HTTP/1.1 升级的情况下使用 HTTP/2 发出非 TLS HTTP 请求。它需要事先知道服务器直接支持 HTTP/2。HTTPS 请求仍将以标准方式执行 HTTP/2,并在 TLS 握手中协商协议版本。(在 7.49.0 中添加)
  414. //
  415. // HTTP_VERSION_3
  416. // (在 7.66.0 中添加)此选项使 libcurl 尝试对 URL 中给定的主机使用 HTTP/3,并在需要时回退到早期的 HTTP 版本。
  417. func (t *Request) SetHttplVersion(ver uintptr) *Request {
  418. curl_easy_setopt.Call(t.curl, OPT_HTTP_VERSION, ver)
  419. return t
  420. }
  421. // SetConnectTo
  422. //
  423. // @Description: 设置DNS转向
  424. // @param old 要拦截的 域名:端口,数字IPv6地址必须写在[括号]内,例如:"example.com"、"example.com:443"、"17.59.98.164:"、"17.59.98.164:80"、"[240e:e9:6002:189:0:ff:b06d:69df]"、"[240e:e9:6002:189:0:ff:b06d:69df]:443"
  425. // @param new 目标 域名:端口,数字IPv6地址必须写在[括号]内,例如:"example.com"、"example.com:443"、"17.59.98.164:"、"17.59.98.164:80"、"[240e:e9:6002:189:0:ff:b06d:69df]"、"[240e:e9:6002:189:0:ff:b06d:69df]:443"
  426. func (t *Request) SetConnectTo(old, new string) *Request {
  427. if t.connect_to == nil {
  428. t.connect_to = make(map[string]string)
  429. }
  430. if new == "" {
  431. delete(t.connect_to, old)
  432. } else {
  433. t.connect_to[old] = new
  434. }
  435. t.connect_to_setopt = true
  436. return t
  437. }
  438. // CleanConnectTo
  439. //
  440. // @Description: 清空DNS转向
  441. func (t *Request) CleanConnectTo() *Request {
  442. t.connect_to = nil
  443. t.connect_to_setopt = true
  444. return t
  445. }
  446. // SetSSLVersion
  447. //
  448. // @Description:传递一个长参数来控制要使用的 SSL/TLS 版本的版本范围。
  449. // SSL 和 TLS 版本通常从最不安全的版本发展到越来越安全的顺序:SSL v2、SSLv3、TLS v1.0、TLS v1.1、TLS v1.2 和最新的 TLS v1 .3.
  450. // 为此目的使用可用的定义之一。可用的选项是:
  451. //
  452. // SSLVERSION_DEFAULT
  453. // 默认可接受的版本范围。自 7.39.0 起,最低可接受版本默认为 TLS v1.0(除非 TLS 库有更严格的规则)。
  454. //
  455. // SSLVERSION_TLSv1
  456. // # TLS v1.0 或更高版本
  457. //
  458. // SSLVERSION_SSLv2
  459. // # SSL v2 - 拒绝
  460. //
  461. // SSLVERSION_SSLv3
  462. // # SSL v3 - 拒绝
  463. //
  464. // SSLVERSION_TLSv1_0
  465. // TLS v1.0 或更高版本(在 7.34.0 中添加)
  466. //
  467. // SSLVERSION_TLSv1_1
  468. // TLS v1.1 或更高版本(在 7.34.0 中添加)
  469. //
  470. // SSLVERSION_TLSv1_2
  471. // TLS v1.2 或更高版本(在 7.34.0 中添加)
  472. //
  473. // SSLVERSION_TLSv1_3
  474. // TLS v1.3 或更高版本(在 7.52.0 中添加)
  475. func (t *Request) SetSSLVersion(ver uintptr) *Request {
  476. curl_easy_setopt.Call(t.curl, OPT_SSLVERSION, ver)
  477. return t
  478. }
  479. // -----------------------------------------------------------------------------------------------------------------------------------------------Send
  480. // Get
  481. //
  482. // @Description: 发起Get请求
  483. func (t *Request) Get(url string) *Request {
  484. t.SetContentType("")
  485. t.SetHeader("Content-Encoding", "")
  486. curl_easy_setopt.Call(t.curl, OPT_URL, yu_sys.S{yu_sys.Gbk, url})
  487. curl_easy_setopt.Call(t.curl, OPT_HTTPGET, 1)
  488. t.opt()
  489. t.perform, _, _ = curl_easy_perform.Call(t.curl)
  490. return t
  491. }
  492. // Post
  493. //
  494. // @Description: 发起Post请求
  495. func (t *Request) Post(url string, data []byte) *Request {
  496. curl_easy_setopt.Call(t.curl, OPT_URL, yu_sys.S{yu_sys.Gbk, url})
  497. curl_easy_setopt.Call(t.curl, OPT_POST, 1)
  498. curl_easy_setopt.Call(t.curl, OPT_POSTFIELDSIZE, len(data))
  499. if len(data) > 0 {
  500. curl_easy_setopt.Call(t.curl, OPT_COPYPOSTFIELDS, data)
  501. }
  502. t.opt()
  503. t.perform, _, _ = curl_easy_perform.Call(t.curl)
  504. return t
  505. }
  506. // PostS
  507. //
  508. // @Description: 发起Post请求
  509. func (t *Request) PostS(url string, data string) *Request {
  510. curl_easy_setopt.Call(t.curl, OPT_URL, yu_sys.S{yu_sys.Gbk, url})
  511. curl_easy_setopt.Call(t.curl, OPT_POST, 1)
  512. curl_easy_setopt.Call(t.curl, OPT_POSTFIELDSIZE, len(data))
  513. if len(data) > 0 {
  514. curl_easy_setopt.Call(t.curl, OPT_COPYPOSTFIELDS, data)
  515. }
  516. t.opt()
  517. t.perform, _, _ = curl_easy_perform.Call(t.curl)
  518. return t
  519. }
  520. // // OpenWs
  521. // //
  522. // // @Description: 发起 Ws 请求
  523. // func (t *Request) OpenWs(url string) *Request {
  524. // t.SetContentType("")
  525. // t.SetHeader("Content-Encoding", "")
  526. // curl_easy_setopt.Call(t.curl, OPT_URL, yu_sys.S{yu_sys.Gbk, url})
  527. // curl_easy_setopt.Call(t.curl, OPT_CONNECT_ONLY, 2)
  528. // t.opt()
  529. // t.perform, _, _ = curl_easy_perform.Call(t.curl)
  530. // return t
  531. // }