前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【测试平台系列】第一章手撸压力机(二)自定义http客户端配置

【测试平台系列】第一章手撸压力机(二)自定义http客户端配置

作者头像
被测试耽误的大厨
发布2023-11-17 11:04:06
2090
发布2023-11-17 11:04:06
举报
文章被收录于专栏:测试平台系列测试平台系列

上一节简单实现了http发送get请求的客户端,但是在实际工作中,我们会对客户端有各种的设置,也会有各种的请求。

今天先看一下,如何定义http的客户端。(注意:咱们的http全部使用fasthttp开源框架)

首先看一下fasthttp.Client结构体源码:

代码语言:javascript
复制
// Client implements http client.
//  Client结构体实现http客户端。
// Copying Client by value is prohibited. Create new instance instead.
//  禁止按值复制Client。而是创建一个新实例。
// It is safe calling Client methods from concurrently running goroutines.
//  从并发运行的例程调用客户机方法是安全的。
// The fields of a Client should not be changed while it is in use.
// 客户端在使用时其字段不可更改。go中定义好的结构体字段都不可更改
type Client struct {
  noCopy noCopy
  // noCopy 字段我们不用管
  // Client name. Used in User-Agent request header.
  // Default client name is used if not set.
  //  客户端的名称,在header中的user-agent使用,通常我们默认就好
  Name string
  // NoDefaultUserAgentHeader when set to true, causes the default
  // User-Agent header to be excluded from the Request.
  // NoDefaultUserAgentHeader设置为true时,导致默认的User-Agent报头从请求中排除。
  // 默认为flase,表示User-Agent使用fasthttp的默认值
  NoDefaultUserAgentHeader bool
  // Callback for establishing new connections to hosts.
  //
  // Default Dial is used if not set.
  // 该函数,通常不使用,可以不用管
  Dial DialFunc
  // Attempt to connect to both ipv4 and ipv6 addresses if set to true.
  //
  // This option is used only if default TCP dialer is used,
  // i.e. if Dial is blank.
  //
  // By default client connects only to ipv4 addresses,
  // since unfortunately ipv6 remains broken in many networks worldwide :)
  // 默认即可,不用管
  DialDualStack bool
  // TLS config for https connections.
  // https连接的TLS配置。
  // Default TLS config is used if not set.
  // 如果没有设置,使用默认的TLS配置。
  // 这里使用的是tls.Config指针类型。可以在我们使用的时候配置
  TLSConfig *tls.Config
  // Maximum number of connections per each host which may be established.
  // 每台主机可以建立的最大连接数。
  // DefaultMaxConnsPerHost is used if not set.
  // 如果没有设置,则使用DefaultMaxConnsPerHost。
  MaxConnsPerHost int
  // Idle keep-alive connections are closed after this duration.
  //  空闲的保持连接在此持续时间之后关闭。
  // By default idle connections are closed
  // after DefaultMaxIdleConnDuration.
  // 默认情况下,在DefaultMaxIdleConnDuration之后关闭空闲连接。
  // 该连接如果空闲的话,在此时间后断开。
  MaxIdleConnDuration time.Duration
  // Keep-alive connections are closed after this duration.
  // Keep-alive连接在此持续时间后关闭。
  // By default connection duration is unlimited.
  // 默认情况下,连接时间是不限制的。
  MaxConnDuration time.Duration
  // Maximum number of attempts for idempotent calls
  //
  // DefaultMaxIdemponentCallAttempts is used if not set.
  // 默认,不用管
  MaxIdemponentCallAttempts int
  // Per-connection buffer size for responses' reading.
  // This also limits the maximum header size.
  //
  // Default buffer size is used if 0.
  // 默认,不用管
  ReadBufferSize int
  // Per-connection buffer size for requests' writing.
  //
  // Default buffer size is used if 0.
  // 默认,不用管
  WriteBufferSize int
  // Maximum duration for full response reading (including body).
  // 完整响应读取(包括body)的最大持续时间。
  // By default response read timeout is unlimited.
  // 默认情况下,响应读取超时时间是不限制的。
  ReadTimeout time.Duration
  // Maximum duration for full request writing (including body).
  // 完整写入请求(包括请求体)的最大持续时间。
  // By default request write timeout is unlimited.
  // 默认情况下,请求写超时时间不受限制。
  WriteTimeout time.Duration
  // Maximum response body size.
  //
  // The client returns ErrBodyTooLarge if this limit is greater than 0
  // and response body is greater than the limit.
  //
  // By default response body size is unlimited.
  // 默认不用管
  MaxResponseBodySize int
  // Header names are passed as-is without normalization
  // if this option is set.
  //
  // Disabled header names' normalization may be useful only for proxying
  // responses to other clients expecting case-sensitive
  // header names. See https://github.com/valyala/fasthttp/issues/57
  // for details.
  //
  // By default request and response header names are normalized, i.e.
  // The first letter and the first letters following dashes
  // are uppercased, while all the other letters are lowercased.
  // Examples:
  //
  //     * HOST -> Host
  //     * content-type -> Content-Type
  //     * cONTENT-lenGTH -> Content-Length
  // 请求头是否按标准格式传输
  DisableHeaderNamesNormalizing bool
  // Path values are sent as-is without normalization
  //
  // Disabled path normalization may be useful for proxying incoming requests
  // to servers that are expecting paths to be forwarded as-is.
  //
  // By default path values are normalized, i.e.
  // extra slashes are removed, special characters are encoded.
  // url路径是按照原样输出,还是按照规范化输出。默认按照规范化输出
  DisablePathNormalizing bool
  // Maximum duration for waiting for a free connection.
  // 等待空闲连接的最大持续时间。
  // By default will not waiting, return ErrNoFreeConns immediately
  // 默认不等待,立即返回ErrNoFreeConns
  MaxConnWaitTimeout time.Duration
  // RetryIf controls whether a retry should be attempted after an error.
  //
  // By default will use isIdempotent function
  // 默认,不用修改
  RetryIf RetryIfFunc
  // Connection pool strategy. Can be either LIFO or FIFO (default).
  // 连接池策略。可以是后进先出或先进先出(默认)。
  // 默认
  ConnPoolStrategy ConnPoolStrategyType
  // StreamResponseBody enables response body streaming
  // StreamResponseBody使能响应体流
  // 默认,有特定需求可使用
  StreamResponseBody bool
  // ConfigureClient configures the fasthttp.HostClient.
  ConfigureClient func(hc *HostClient) error
  mLock      sync.Mutex
  m          map[string]*HostClient
  ms         map[string]*HostClient
  readerPool sync.Pool
  writerPool sync.Pool
}

根据上面解读fasthttp.Client, 我们可以找到我们通常使用的配置项,如下:

代码语言:javascript
复制
type Client struct {
  //  客户端的名称,在header中的user-agent使用,通常我们默认就好
  Name string
  // NoDefaultUserAgentHeader when set to true, causes the default
  // User-Agent header to be excluded from the Request.
  // NoDefaultUserAgentHeader设置为true时,导致默认的User-Agent报头从请求中排除。
  // 默认为flase,表示User-Agent使用fasthttp的默认值
  NoDefaultUserAgentHeader bool
  // https连接的TLS配置。这里使用的是tls.Config指针类型。可以在我们使用的时候配置
  TLSConfig *tls.Config
  // 每台主机可以建立的最大连接数。如果没有设置,则使用DefaultMaxConnsPerHost。
  MaxConnsPerHost int
  // 空闲的保持连接在此持续时间之后关闭。默认情况下,在DefaultMaxIdleConnDuration之后关闭空闲连接。
  // 该连接如果空闲的话,在此时间后断开。
  MaxIdleConnDuration time.Duration
  // Keep-alive连接在此持续时间后关闭。默认情况下,连接时间是不限制的。
  MaxConnDuration time.Duration
  // 默认情况下,响应读取超时时间是不限制的。
  ReadTimeout time.Duration
  // 默认情况下,请求写超时时间不受限制。
  WriteTimeout time.Duration
  // 请求头是否按标准格式传输
  DisableHeaderNamesNormalizing bool
  // url路径是按照原样输出,还是按照规范化输出。默认按照规范化输出
  DisablePathNormalizing bool
}

通过上述梳理,我们知道通常使用的配置项为10项。我们在项目根目录下新建model文件夹,并在文件夹下新建http_model.go文件,代码如下:

代码语言:javascript
复制
package model
import (
  "crypto/tls"
)
type HttpClientSettings struct {
  //  客户端的名称,在header中的user-agent使用,通常我们默认就好
  Name string
  // 默认为flase,表示User-Agent使用fasthttp的默认值
  NoDefaultUserAgentHeader bool
  // https连接的TLS配置。这里使用的是tls.Config指针类型。可以在我们使用的时候配置
  TLSConfig *tls.Config
  // 每台主机可以建立的最大连接数。如果没有设置,则使用DefaultMaxConnsPerHost。
  MaxConnsPerHost int
  // 空闲的保持连接在此持续时间之后关闭。默认情况下,在DefaultMaxIdleConnDuration之后关闭空闲连接。
  // 该连接如果空闲的话,在此时间后断开。
  MaxIdleConnDuration int64
  // Keep-alive连接在此持续时间后关闭。默认情况下,连接时间是不限制的。
  MaxConnDuration int64
  // 默认情况下,响应读取超时时间是不限制的。
  ReadTimeout int64
  // 默认情况下,请求写超时时间不受限制。
  WriteTimeout int64
  // 请求头是否按标准格式传输
  DisableHeaderNamesNormalizing bool
  // url路径是按照原样输出,还是按照规范化输出。默认按照规范化输出
  DisablePathNormalizing bool
}

这样,我们http客户端的配置项,基本已经定义完成了。下面,我们修改一下server目录下的http_client.go文件的newHttpClient()方法,添加一个HttpClientSettings参数, 同时修改RequestHttp()方法,添加一个HttpClientSettings参数。具体修改如下:

代码语言:javascript
复制
package server
import (
  "crypto/tls"
  "fmt"
  "github.com/valyala/fasthttp"
  "kitchen-engine/model"
  "time"
)
func RequestHttp(httpClientSettings model.HttpClientSettings) {
  // 使用fasthttp 协程池
  // 新建一个http请求
  req := fasthttp.AcquireRequest()
  defer fasthttp.ReleaseRequest(req)
  // 新建一个http响应接受服务端的返回
  resp := fasthttp.AcquireResponse()
  defer fasthttp.ReleaseResponse(resp)
  // 新建一个http的客户端, newHttpClient是一个方法,在下面
  client := newHttpClient(httpClientSettings)
  // 添加该请求的http方法:get、post、delete、update等等
  req.Header.SetMethod("GET")
  // 添加该请求的http的url
  req.SetRequestURI("http://www.baidu.com")
  // 开始请求
  err := client.Do(req, resp)
  if err != nil {
    fmt.Sprintln("发送http请求错误:   ", err.Error())
  }
  // 打印请求的header
  fmt.Println("resp:    ", req.Header.Header())
}
func newHttpClient(httpClientSettings model.HttpClientSettings) (httpClient *fasthttp.Client) {
  // tls验证,关闭验证
  tr := &tls.Config{
    InsecureSkipVerify: true,
  }
  // 新建指针类型的客户端
  httpClient = &fasthttp.Client{}
  httpClient.TLSConfig = tr
  if httpClientSettings.Name != "" {
    httpClient.Name = httpClientSettings.Name
  }
  if httpClientSettings.NoDefaultUserAgentHeader == true {
    httpClient.NoDefaultUserAgentHeader = true
  }
  // 如果最大连接数不为0,将设置此数
  if httpClientSettings.MaxConnsPerHost != 0 {
    httpClient.MaxConnsPerHost = httpClientSettings.MaxConnsPerHost
  }
  // url不按照标准输出,按照原样输出
  if httpClientSettings.DisablePathNormalizing == true {
    httpClient.DisablePathNormalizing = true
  }
  // 请求头不按标准格式传输
  if httpClientSettings.DisableHeaderNamesNormalizing == true {
    httpClient.DisableHeaderNamesNormalizing = true
  }
  // 如果此时间不为0,那么将设置此时间。keep-alive维持此时长后将关闭。时间单位为毫秒
  if httpClientSettings.MaxConnDuration != 0 {
    httpClient.MaxConnDuration = time.Duration(httpClientSettings.MaxConnDuration) * time.Millisecond
  }
  if httpClientSettings.ReadTimeout != 0 {
    httpClient.ReadTimeout = time.Duration(httpClientSettings.ReadTimeout) * time.Millisecond
  }
  if httpClientSettings.WriteTimeout != 0 {
    httpClient.WriteTimeout = time.Duration(httpClientSettings.WriteTimeout) * time.Millisecond
  }
  // 该连接如果空闲的话,在此时间后断开。
  if httpClientSettings.MaxIdleConnDuration != 0 {
    httpClient.MaxIdleConnDuration = time.Duration(httpClientSettings.MaxIdleConnDuration) * time.Millisecond
  }
  return
}

至此,客户端配置项,我们已经修改的差不多了,Tls配置,我们以后再深入讲解。下面,我们在main函数中,创建一个HttpClientSettings,并调用RequestHttp()方法, 具体如下:

代码语言:javascript
复制
package main
import (
  "kitchen-engine/model"
  "kitchen-engine/server"
)
func main() {

  // 一个类型中的字段,可以重置,也可以使用默认值,在go中,所有的类型的初始值,都是字段类型的0值,比如string的初始值是""空字符串,int类型的初始值是0等等
  httpClientSettings := model.HttpClientSettings{
    Name:                     "测试厨房",
    NoDefaultUserAgentHeader: true,
    MaxConnDuration:          1000,
  }
  // 调用
  server.RequestHttp(httpClientSettings)
}

执行结果如下:

代码语言:javascript
复制
req:   GET / HTTP/1.1
User-Agent: 测试厨房
Host: www.baidu.com

ok,慢慢的代码将深入,如果没有go语言基础,建议可以先学一下go的基础知识。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2023-11-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 全栈测试开发之路 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
腾讯云服务器利旧
云服务器(Cloud Virtual Machine,CVM)提供安全可靠的弹性计算服务。 您可以实时扩展或缩减计算资源,适应变化的业务需求,并只需按实际使用的资源计费。使用 CVM 可以极大降低您的软硬件采购成本,简化 IT 运维工作。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档