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
-