golang http请求封装代码

在GOPATH 中创建 utils 文件夹 放置这两个文件

http.go

package utils
import (
 "crypto/tls"
 "encoding/json"
 "errors"
 "fmt"
 "io/ioutil"
 "net/http"
 "net/url"
 "strings"
 "sync"
)
var (
 GET_METHOD = "GET"
 POST_METHOD = "POST"
 SENDTYPE_FROM = "from"
 SENDTYPE_JSON = "json"
)
type HttpSend struct {
 Link  string
 SendType string
 Header map[string]string
 Body  map[string]string
 sync.RWMutex
}
func NewHttpSend(link string) *HttpSend {
 return &HttpSend{
  Link:  link,
  SendType: SENDTYPE_FROM,
 }
}
func (h *HttpSend) SetBody(body map[string]string) {
 h.Lock()
 defer h.Unlock()
 h.Body = body
}
func (h *HttpSend) SetHeader(header map[string]string) {
 h.Lock()
 defer h.Unlock()
 h.Header = header
}
func (h *HttpSend) SetSendType(send_type string) {
 h.Lock()
 defer h.Unlock()
 h.SendType = send_type
}
func (h *HttpSend) Get() ([]byte, error) {
 return h.send(GET_METHOD)
}
func (h *HttpSend) Post() ([]byte, error) {
 return h.send(POST_METHOD)
}
func GetUrlBuild(link string, data map[string]string) string {
 u, _ := url.Parse(link)
 q := u.Query()
 for k, v := range data {
  q.Set(k, v)
 }
 u.RawQuery = q.Encode()
 return u.String()
}
func (h *HttpSend) send(method string) ([]byte, error) {
 var (
  req  *http.Request
  resp  *http.Response
  client http.Client
  send_data string
  err  error
 )
 if len(h.Body) > 0 {
  if strings.ToLower(h.SendType) == SENDTYPE_JSON {
   send_body, json_err := json.Marshal(h.Body)
   if json_err != nil {
    return nil, json_err
   }
   send_data = string(send_body)
  } else {
   send_body := http.Request{}
   send_body.ParseForm()
   for k, v := range h.Body {
    send_body.Form.Add(k, v)
   }
   send_data = send_body.Form.Encode()
  }
 }
 //忽略https的证书
 client.Transport = &http.Transport{
  TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
 }
 req, err = http.NewRequest(method, h.Link, strings.NewReader(send_data))
 if err != nil {
  return nil, err
 }
 defer req.Body.Close()

 //设置默认header
 if len(h.Header) == 0 {
  //json
  if strings.ToLower(h.SendType) == SENDTYPE_JSON {
   h.Header = map[string]string{
    "Content-Type": "application/json; charset=utf-8",
   }
  } else { //form
   h.Header = map[string]string{
    "Content-Type": "application/x-www-form-urlencoded",
   }
  }
 }
 for k, v := range h.Header {
  if strings.ToLower(k) == "host" {
   req.Host = v
  } else {
   req.Header.Add(k, v)
  }
 }
 resp, err = client.Do(req)
 if err != nil {
  return nil, err
 }
 defer resp.Body.Close()

 if resp.StatusCode != http.StatusOK {
  return nil, errors.New(fmt.Sprintf("error http code :%d", resp.StatusCode))
 }
 return ioutil.ReadAll(resp.Body)
}

http_test.go

package utils
import (
 "testing"
)
func Test_Get(t *testing.T) {
 h := NewHttpSend(GetUrlBuild("http://127.0.0.1/test.php", map[string]string{"name": "xiaochuan"}))
 _, err := h.Get()
 if err != nil {
 t.Error("请求错误:", err)
 } else {
 t.Log("正常返回")
 }
}
func Test_Post(t *testing.T) {
 h := NewHttpSend("http://127.0.0.1/test.php")
 h.SetBody(map[string]string{"name": "xiaochuan"})
 _, err := h.Post()
 if err != nil {
 t.Error("请求错误:", err)
 } else {
 t.Log("正常返回")
 }
}
func Test_Json(t *testing.T) {
 h := NewHttpSend("http://127.0.0.1/test.php")
 h.SetSendType("JSON")
 h.SetBody(map[string]string{"name": "xiaochuan"})
 _, err := h.Post()
 if err != nil {
 t.Error("请求错误:", err)
 } else {
 t.Log("正常返回")
 }
}
func Benchmark_GET(b *testing.B) {
 for i := 0; i < b.N; i++ {
 h := NewHttpSend(GetUrlBuild("http://127.0.0.1/test.php", map[string]string{"name": "xiaochuan"}))
 _, err := h.Get()
 if err != nil {
 b.Error("请求错误:", err)
 } else {
 b.Log("正常返回")
 }
 }
}

补充:golang中发送http请求的几种常见情况

整理一下golang中各种http的发送方式

最初的一些项目中,很多的地方都使用到了golang发送http请求,之后再对请求收到的结果进行一些处理,所用到的模式也比较固定,这里整理一下集中http的发送方式,先记录这么多,再一点一点添加。

最基本的场景

方式一 使用http.Newrequest

先生成http.client -> 再生成 http.request -> 之后提交请求:client.Do(request) -> 处理返回结果,每一步的过程都可以设置一些具体的参数,下面是一个最朴素最基本的例子:

//question ???将stdout重定向为response信息???
package main
import (
 "fmt"
 "io"
 "net/http"
 "os"
)
func main() {
 //生成client 参数为默认
 client := &http.Client{}
 //生成要访问的url
 url := "http://www.baidu.com"
 //提交请求
 reqest, err := http.NewRequest("GET", url, nil)
 if err != nil {
 panic(err)
 }
 //处理返回结果
 response, _ := client.Do(reqest)
 //将结果定位到标准输出 也可以直接打印出来 或者定位到其他地方进行相应的处理
 stdout := os.Stdout
 _, err = io.Copy(stdout, response.Body)
 //返回的状态码
 status := response.StatusCode
 fmt.Println(status)
}

方式二 先生成client,之后用client.get/post..

client结构自己也有一些发送api的方法,比如client.get,client.post,client.postform..等等。基本上涵盖了主要的http请求的类型,通常不进行什么特殊的配置的话,这样就可以了,其实client的get或者post方法,也是对http.Newerequest方法的封装,里面还额外添加了req.Header.Set("Content-Type", bodyType)一般用的话,也是ok的

方式三 http. Get/Post..

具体实现的时候,还是采用的先前提到的模式,先生成一个默认的client,之后调用http.Newrequest方法。

对每个步骤进行细节性的说明

生成client时候的参数配置

最常见的一个参数是使用https的方式发送信息时候client端的设置。如果生成client的时候,什么信息都不添加,就会使用默认的值。具体的信息包括:

 Transport RoundTripper
 CheckRedirect func(req *Request, via []*Request) error
 Jar CookieJar
 Timeout time.Duration

第一个参数是一个RoundTripper接口,里面包含了一个RoundTrip函数,指定了一些http请求的基本机制。

http.Transport中涉及到的参数较多,要是不指定的话,就会使用默认的DefaultTransport参数,里面包含一些默认的请求时间以及proxy机制之类的。

具体的细节参数涉及到好多,有的都没有使用到过比如那些我握手时间之类的,目前使用到的最多的就是https的相关参数:TLSClientConfig,这是一个*tls.Config类型,其中涉及到的参数还是有很多,一个基本的是用案例如下,仅仅是在配置中制定了rooca以及客户度端使用的证书。

通常发送https请求的时候,前面的参数可以使用如下方式进行处理:

pool := x509.NewCertPool()
 caCertPath := "certs/cert_server/ca.crt"
 caCrt, err := ioutil.ReadFile(caCertPath)
 if err != nil {
 fmt.Println("ReadFile err:", err)
 return
 }
 pool.AppendCertsFromPEM(caCrt)
 cliCrt, err := tls.LoadX509KeyPair("certs/cert_server/client.crt", "certs/cert_server/client.key")
 if err != nil {
 fmt.Println("Loadx509keypair err:", err)
 return
 }
 tr := &http.Transport{
 TLSClientConfig: &tls.Config{
 RootCAs:  pool,
 Certificates: []tls.Certificate{cliCrt},
 },
 }
 client := &http.Client{Transport: tr}

生成request时候的参数配置

生成request的时候,主要的是几个基本的参数。NewRequest函数有三个基本的参数,NewRequest(method, urlStr string, body io.Reader)第一个是请求的类型,GET, POST, PUT, etc.要设成大写的形式。第二个参数是请求要访问的url,第三个参数是请求的body中的内容,需要是一个io.Reader的类型。

注意io.Reader的接口中是一个Read方法,实现了Read方法的类型应该都可以作为io.Reader来返回,Read(p []byte) (n int, err error)函数具体的功能就是读入len(p)长度的内容到p中,返回读入的长度以及错误信息。

通常是采用strings.NewReader函数,将一个string类型转化为io.Reader类型,或者bytes.NewBuffer函数,将[]byte类型转化为io.Reader类型。

此外还可以给request的header中添加一些额外的信息,比如下面例子中添加了请求的body的类型以及token的信息。

reqest.Header.Set("Content-Type", "application/x-www-form-urlencoded")

reqest.Header.Set("Authorization", "qwertyuiopasdfghjklzxcvbnm1234567890")

还有比如模拟表单提交,可以把提交的类型设置为url.Values类型再进行Encode:

// use map as struct
 var clusterinfo = url.Values{}
 //var clusterinfo = map[string]string{}
 clusterinfo.Add("userName", user)
 clusterinfo.Add("password", pw)
 clusterinfo.Add("cloudName", clustername)
 clusterinfo.Add("masterIp", masterip)
 clusterinfo.Add("cacrt", string(caCrt))
 data := clusterinfo.Encode()
 url := "https://10.10.105.124:8443/user/checkAndUpdate"
 reqest, err := http.NewRequest("POST", url, strings.NewReader(data))

最常见的一种情况是发送一个json文件过去,可以把Header的类型设置成为:

"Content-Type", "application/json; charset=utf-8"

其余的部分按照先前同样的方式进行设置发送提交就好。

request的类型的属性还是比较多的,慢慢整理。

生成的response结果的处理

一般在client构建好之后,要采用client.Do(request)方法提交client请求,之后会返回一个*Response类型。response中的参数一般也比较多,我们需要的最多的通常是Body参数,一般通过body, _ := ioutil.ReadAll(resp.Body)会把body转化为[]byte类型返回过来, 之后再进行其他的处理。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。如有错误或未考虑完全的地方,望不吝赐教。

(0)

相关推荐

  • golang编程入门之http请求天气实例

    golang学习第一波,使用http get请求高德天气接口. 一.准备内容: 1.注册高德开发者账号,申请key 2.golang开发工具LiteIDE(可自行百度). 或者https://www.jb51.net/softjc/119086.html 3.大致了解下golang基础语法. 二.直接上代码 因为代码注释非常详尽,故直接上代码. package main import ( "fmt" "io/ioutil" "net/http"

  • 详解golang中发送http请求的几种常见情况

    方式一 使用http.Newrequest 先生成http.client -> 再生成 http.request -> 之后提交请求:client.Do(request) -> 处理返回结果,每一步的过程都可以设置一些具体的参数,下面是一个最朴素最基本的例子: //question ???将stdout重定向为response信息??? package main import ( "fmt" "io" "net/http" &q

  • golang使用http client发起get和post请求示例

    golang要请求远程网页,可以使用net/http包中的client提供的方法实现.查看了官方网站有一些示例,没有太全面的例子,于是自己整理了一下: get请求 func httpGet() { resp, err := http.Get("http://www.01happy.com/demo/accept.php?id=1") if err != nil { // handle error } defer resp.Body.Close() body, err := ioutil

  • Golang 发送http请求时设置header的实现

    某天,在需要抓取某个网页信息的时候,需要在header中增加一些信息,于是搜索了一下,如何在golang发起的http请求中设置header. package main import ( "fmt" "io/ioutil" "net/http" "os" "encoding/json" ) func main() { //生成client 参数为默认 client := &http.Client{}

  • Golang发送http GET请求的示例代码

    使用标准库http来实现 package tools import ( "io/ioutil" "net/http" ) func Get(url string)string{ res, err :=http.Get(url) if err != nil { return "" } robots, err := ioutil.ReadAll(res.Body) res.Body.Close() if err != nil { return &qu

  • 详解golang开发中http请求redirect的问题

    这两天在开发项目的时候遇到了一个问题,请求了一个URL,它会302到另一个地址,本意上只是想检查这个URL是否会做3XX的redirect跳转,结果每次reqeust都会返回最后一跳的结果.后来就看了下源码,了解下请求跳转的机制 实现代码 看下实现的简单代码 func main() { client := &http.Client{} url := "http://www.qq.com" reqest, err := http.NewRequest("GET"

  • golang http请求封装代码

    在GOPATH 中创建 utils 文件夹 放置这两个文件 http.go package utils import ( "crypto/tls" "encoding/json" "errors" "fmt" "io/ioutil" "net/http" "net/url" "strings" "sync" ) var ( GE

  • 微信小程序HTTP接口请求封装代码实例

    1.方法封装(新建文件夹util,工具文件,在文件夹下创建request.js文件,用于对方法封装) request.js: var app = getApp(); //项目URL相同部分,减轻代码量,同时方便项目迁移 //这里因为我是本地调试,所以host不规范,实际上应该是你备案的域名信息 var host = 'http://localhost:8081/demo/'; /** * POST请求, * URL:接口 * postData:参数,json类型 * doSuccess:成功的回

  • Python接口自动化之request请求封装源码分析

    目录 1. 源码分析 2. requests请求封装 3. 总结 前言: 我们在做自动化测试的时候,大家都是希望自己写的代码越简洁越好,代码重复量越少越好.那么,我们可以考虑将request的请求类型(如:Get.Post.Delect请求)都封装起来.这样,我们在编写用例的时候就可以直接进行请求了. 1. 源码分析 我们先来看一下Get.Post.Delect等请求的源码,看一下它们都有什么特点. (1)Get请求源码 def get(self, url, **kwargs): r""

  • 微信小程序 http请求封装详解及实例代码

    微信小程序  http请求封装 示例代码 wx.request({ url: 'test.php', //仅为示例,并非真实的接口地址 data: { x: '' , y: '' }, method:'POST', header: { 'content-type': 'application/json' }, success: function(res) { console.log(res.data) }, fail: function( res ) { fail( res ); } }) 以上

  • 浅谈Java代码的 微信长链转短链接口使用 post 请求封装Json(实例)

    废话不多说,直接上代码 String longUrl = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + MpUtil.APPID + "&redirect_uri=" + MpUtil.HOMEPAGE + "/nweixinLoginPc.fo%3Frandomcode=" + randomcode + "&response_type=co

  • 微信小程序request请求封装,验签代码实例

    这篇文章主要介绍了微信小程序request请求封装,验签代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 1.公共文件util添加 request请求 //简单封装请求 function request(params, path, isShowLoading = true, goBack = false, type = 'none', obj={}) { try { console.log(path) let NowTime = Date

  • 基于axios请求封装的vue应用实例代码

    什么是axios? Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中. 特性: 从浏览器中创建 XMLHttpRequests 从 node.js 创建 http 请求 支持 Promise API 拦截请求和响应 转换请求数据和响应数据 取消请求 自动转换 JSON 数据 客户端支持防御 XSRF Promises axios 依赖原生的 ES6 Promise 实现而被支持. 如果你的环境不支持 ES6 Promise,你可以使用 polyfil

  • 全网小程序接口请求封装实例代码

    前言 这篇文章主要针对一些初学者,有写的不好的地方,还请大家多多谅解! 在utils文件夹里面新建两个js文件,一个是api.js.一个就是requtil.js api.js 这个文件主要api接口,废话不多说直接上代码了 const request = require('requtil.js') /*Apis 把全部api都存在这里*/ const Apis = { /* 用户相关 */ 'login': '/devicecenter/auth/weChtLoin', 'bindUser':

  • 微信小程序  http请求封装详解及实例代码

    微信小程序  http请求封装 示例代码 wx.request({ url: 'test.php', //仅为示例,并非真实的接口地址 data: { x: '' , y: '' }, method:'POST', header: { 'content-type': 'application/json' }, success: function(res) { console.log(res.data) }, fail: function( res ) { fail( res ); } }) 以上

  • golang API请求队列的实现

    目录 概要 实现思路 使用方法 概要 在调用第三方 API 的时候, 基本都有访问限速的限制条件. 第三方的 API 有多个的时候, 就不太好控制访问速度, 常常会导致 HTTP 429(Too Many Requests) 然后就会有一段时间的禁止访问. 为了应对这种限速的情况, 通过一个简单的请求队列来控制访问的速度, 之后基本没遇到过 HTTP 429 了. 实现思路 首先, 每个请求包装成一个 RequestParam 的 struct, 其中包含请求的地址,类型,参数以及 respon

随机推荐