package wfclient import ( "bytes" "crypto/tls" "errors" "fmt" "io" "io/ioutil" "mime/multipart" "net/http" "net/url" "os" "strings" "time" ) type HttpClient struct { reqInterseptor func(r *http.Request) } var httpInstance *HttpClient = nil /** * @brief: single instance */ func HttpClientInstance()*HttpClient{ if httpInstance == nil{ httpInstance = &HttpClient{} } return httpInstance } /** * @brief: set interseptor of request * @param1 interseptor: interseptor */ func (h *HttpClient)setRequestInterseptor(interseptor func(r *http.Request)){ h.reqInterseptor = interseptor } /** * @brief http get * @param1 url: url * @param2 params: param array, key-value * @param3 headers: header array * @return1: content of response * @return2: error */ func (h *HttpClient)get(url string, params map[string]string, headers map[string]string) ([]byte, error) { return h.doRequest("GET", url, params, headers) } // post func (h *HttpClient)post(url string, params map[string]string, headers map[string]string) ([]byte, error) { return h.doRequest("POST", url, params, headers) } // 模拟form提交数据,包含,上传文件 func (h *HttpClient)postFormWithFile(url string, params map[string]string, paramName, path string) ([]byte, error) { file, err := os.Open(path) if err != nil { return nil, err } defer file.Close() return h.postFormWithReader(url, params, paramName, path, file) } // 模拟form提交数据,包含,上传文件 func (h *HttpClient)postFormWithReader(url string, params map[string]string, fileField, fileName string, r io.Reader) ([]byte, error) { body := &bytes.Buffer{} writer := multipart.NewWriter(body) part, err := writer.CreateFormFile(fileField, fileName) if err != nil { return nil, err } _, err = io.Copy(part, r) for key, val := range params { _ = writer.WriteField(key, val) } err = writer.Close() if err != nil { return nil, err } request, err := http.NewRequest("POST", url, body) request.Header.Set("Content-Type", writer.FormDataContentType()) return h.getResponse(request) } func (h *HttpClient)doRequest(method string, url string, params map[string]string, headers map[string]string) ([]byte, error) { bodystr := "" var r http.Request if method == "GET"{ url = h.getUrlWithParams(url, params) }else { bodystr = h.getBobyStr(&r, params) } request, err := http.NewRequest(method, url, strings.NewReader(bodystr)) if err != nil { return []byte(""), err } if headers == nil || len(headers) <= 0 { request.Header.Set("Content-Type", "application/x-www-form-urlencoded") request.Header.Set("Connection", "Keep-Alive") } else { for k, v := range headers { request.Header.Set(k, v) } } if h.reqInterseptor != nil{ h.reqInterseptor(request) } return h.getResponse(request) } func (h *HttpClient)getResponse(request *http.Request) ([]byte, error) { if request == nil { return []byte(""), errors.New("request is nil") } tr := &http.Transport{ TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, ResponseHeaderTimeout: time.Second * 60, DisableKeepAlives: true, } client := http.Client{Transport: tr} var resp *http.Response var err error resp, err = client.Do(request) if err != nil { //log.Println("http.Do failed,[err=%s][url=%s]", err, url) return []byte(""), err } defer resp.Body.Close() b, err := ioutil.ReadAll(resp.Body) if err != nil { return []byte(""), err } return b, err } func (h *HttpClient)getBobyStr(r *http.Request, params map[string]string)string{ r.ParseForm() if params != nil { for k, v := range params { r.Form.Add(k, v) } } return strings.TrimSpace(r.Form.Encode()) } func (h *HttpClient)getUrlWithParams(urlstr string, params map[string]string)string { if params != nil && len(params) > 0 { i := strings.Index(urlstr, "?") if i < 0 { urlstr += "?" } else { urlstr += "&" } for k, v := range params { urlstr += fmt.Sprintf("%s=%s&", k, url.QueryEscape(v)) } urlstr = urlstr[:len(urlstr)-1] } return urlstr }