golang 使用http包实现curl命令功能【在不使用exec时】

golang 使用http包实现curl命令功能

背景
  • 直接调用exec包不好控制curl的进程
  • curl执行的协程数量不易管理,在高并发时会出现协程泄漏
实现思路
  • 基于net/http包实现curl功能,由于curl本质上也是一个客户端,用来进行文件的传输,多用于文件的上传下载,在这种场景下,可使用net/http的功能替换,以便于在程序中更好的控制底层的运行情况。
实例应用
  • 采集参数【部分】

    • 文件大小 filesize
    • 建联时间 conntime
    • 响应状态 httpstatus
  • 核心代码

    • 定义结构体存放基本信息

      type Params struct {
      		Url       string          //目标url
      		HttpType  string          //请求方式,默认get
      		Timeout   int             // 超时时间 秒
      		Transport *http.Transport // 请求配置
      		Headers   *http.Header    // 头部信息
      	}
      dUrl := &CurlParams{}	
      
    • 设置代理(-x)

      u, _ := url.Parse("http://" + ip + `:` + strconv.Itoa(int(port)))
      dUrl.Transport.Proxy = http.ProxyURL(u)
      
    • 设置头部

      例如:
      dUrl.Headers.Set("User-Agent", "curl/7.29.0")
      dUrl.Headers.Set("Host", host)
      
    • 设置–referer 跳转查询

      dUrl.Headers.Set("Referer", url)
      
    • 设置SSL跳过检测

      dUrl.Transport.TLSClientConfig = &tls.Config{
      	InsecureSkipVerify: true,
      }
      
  • 参数计算

    • 初始化

      client := &http.Client{}
      
    • http链路跟踪

      var start,dns, connect time.Time
      var connectTime,dNSDoneTime, firstRespByteTime int64
      // 创建客户端请求跟踪
      trace := &httptrace.ClientTrace{
      	DNSStart: func(dsi httptrace.DNSStartInfo) {
      		dns = time.Now()
      	},
      	DNSDone: func(ddi httptrace.DNSDoneInfo) {
      		dNSDoneTime = time.Since(dns).Milliseconds()
      	},
      
      	ConnectStart: func(network, addr string) { connect = time.Now() },
      	ConnectDone: func(network, addr string, err error) {
      		connectTime = time.Since(connect).Milliseconds()
      	}
      }
      req = req.WithContext(httptrace.WithClientTrace(req.Context(), trace))
      
    • 采集计算

      statusCode := resp.StatusCode  // 响应状态码
      dnsTime := dNSDoneTime  //dns
      fileSize := resp.ContentLength // 获取响应内容大小
      connTime:= connectTime
      

你可能感兴趣的:(golang,http,ssl,linux)