python中https请求的封装_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 := "https://www.webkfz.com/d/file/202012152039198/20201215201339199"

//提交请求

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类型返回过来, 之后再进行其他的处理。

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值