golang-http几种常用内容类型(Content-Type)的客户端开发实例

410 阅读2分钟

在开发过程中,通常会遇到与其他服务做信息交换的情况,大多数情况下会通过http接口实现信息的交换。但是不同的服务接口指定的Content-Type类型是不同的。下文将通过实际的例子展示,常用的集中内容类型的http请求如何开发。

Content-Type(内容类型),一般是指网页中存在的 Content-Type,用于定义网络文件的类型和网页的编码,决定浏览器将以什么形式、什么编码读取这个文件,这就是经常看到一些 PHP 网页点击的结果却是下载一个文件或一张图片的原因。

Content-Type 标头告诉客户端实际返回的内容的内容类型。s

http支持的Content-Type种类很多,但是实际中常用的主要有三种:application/x-www-form-urlencoded,application/form-data,application/json。

1、一个通用的请求方法

var httpTr = &http.Transport{
	//控制主机的最大空闲连接数,0为没有限制
	MaxIdleConns:        100,
	MaxIdleConnsPerHost: 100,
	//长连接在关闭之前,保持空闲的最长时间,0表示没限制。
	IdleConnTimeout: 60 * time.Second,
}

var client = &http.Client{
	Timeout:   20 * time.Second,
	Transport: httpTr,
}

func SendRequest(url string, method string, contentType string, param io.Reader, respData interface{}, headers ...map[string]string) error {
	var err error

	req, err := http.NewRequest(method, url, param)
	if err != nil {
		err = fmt.Errorf("create http request failed: %s", err.Error())
		return err
	}

	req.Header.Set("Content-Type", contentType)

	if headers != nil {
		for _, h := range headers {
			for k, v := range h {
				req.Header.Set(k, v)
			}
		}
	}

	resp, err := client.Do(req)
	if err != nil {
		err = fmt.Errorf("send http request failed: %s", err.Error())
		return err
	}
	defer resp.Body.Close()

	respBytes, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		err = fmt.Errorf("read response data failed: %s", err.Error())
		return err
	}
	logger.Debug("read the response ok:", string(respBytes))

	// 解析响应
	if err = json.Unmarshal(respBytes, respData); err != nil {
		logger.Error(err.Error())
		err = fmt.Errorf("unmarshal response data failed: %s", err.Error())
		return err
	}
	return nil
}

2、application/json格式

func PostJsonRequest(url string, requestData interface{}, responseData interface{}, headers ...map[string]string) error {
	var err error

	logger.Debugf("url: %s, req: %+v", url, requestData)
	jsonParamBytes, err := json.Marshal(requestData)
	if err != nil {
		err = fmt.Errorf("Marshal json error:%s ", err.Error())
		return err
	}
	logger.Debugf("request json:%s", string(jsonParamBytes))

	paramData := bytes.NewBuffer(jsonParamBytes)
	err = SendRequest(url, "POST", "application/json", paramData, responseData, headers...)
	if err != nil {
		return err
	}

	return nil
}

3、application/x-www-form-urlencoded格式

func PostUrlEncodedRequest(urlstr string, requestData map[string]string, responseData interface{}) error {
	var err error
	var body = make(url.Values)

	if requestData != nil {
		for k, v := range requestData {
			body[k] = []string{v}
			logger.Debug("build form data ok.")
		}
	}
	data := strings.NewReader(body.Encode())

	logger.Debugf("url: %s, req: %+v", urlstr, data)

	err = SendRequest(urlstr, "POST", "application/x-www-form-urlencoded", data, responseData)
	if err != nil {
		return err
	}

	return nil
}

4、application/form-data格式

func PostFormDataRequest(urlstr string, requestData map[string]string, responseData interface{}) error {
	var err error
	body := new(bytes.Buffer)
	writer := multipart.NewWriter(body)

	if requestData != nil {
		for k, v := range requestData {
			err = writer.WriteField(k, v)
			if err != nil {
				err = fmt.Errorf("write form field %s:%s failed: %s", k, v, err.Error())
				return err
			}
			logger.Debug("build form data ok.")
		}
	}
	if err = writer.Close(); err != nil {
		err = fmt.Errorf("close multipart form writer failed: %s", err.Error())
	}

	err = SendRequest(urlstr, "POST", writer.FormDataContentType(), body, responseData)
	if err != nil {
		return fmt.Errorf("do sendRequest error with param %s:%s", body, err.Error())
	}

	return nil
}

上述事例默认返回数据为json类型,这也是当前 http接口最常用的信息交互数据格式。开发时可以根据实际的情况修改返回值处理逻辑。此外,请求方法类型也可以根据实际需求进行修改,如果请求方法类型不匹配将无法返回正确结果。