215 lines
5.5 KiB
Go
215 lines
5.5 KiB
Go
// Package model 请求数据模型package model
|
||
package model
|
||
|
||
import (
|
||
"errors"
|
||
"fmt"
|
||
"net/http"
|
||
"strings"
|
||
"sync"
|
||
"time"
|
||
)
|
||
|
||
// 返回 code 码
|
||
const (
|
||
// HTTPOk 请求成功
|
||
HTTPOk = 200
|
||
// RequestErr 请求错误
|
||
RequestErr = 509
|
||
// ParseError 解析错误
|
||
ParseError = 510 // 解析错误
|
||
)
|
||
|
||
// 支持协议
|
||
const (
|
||
/// FormTypeHTTP http 协议
|
||
//FormTypeHTTP = "http"
|
||
/// FormTypeWebSocket webSocket 协议
|
||
FormTypeWebSocket = "webSocket"
|
||
/// FormTypeGRPC grpc 协议
|
||
//FormTypeGRPC = "grpc"
|
||
//FormTypeRadius = "radius"
|
||
)
|
||
|
||
// 校验函数
|
||
var (
|
||
// verifyMapHTTP http 校验函数
|
||
verifyMapHTTP = make(map[string]VerifyHTTP)
|
||
// verifyMapHTTPMutex http 并发锁
|
||
verifyMapHTTPMutex sync.RWMutex
|
||
// verifyMapWebSocket webSocket 校验函数
|
||
verifyMapWebSocket = make(map[string]VerifyWebSocket)
|
||
// verifyMapWebSocketMutex webSocket 并发锁
|
||
verifyMapWebSocketMutex sync.RWMutex
|
||
)
|
||
|
||
// RegisterVerifyWebSocket 注册 webSocket 校验函数
|
||
func RegisterVerifyWebSocket(verify string, verifyFunc VerifyWebSocket) {
|
||
verifyMapWebSocketMutex.Lock()
|
||
defer verifyMapWebSocketMutex.Unlock()
|
||
key := fmt.Sprintf("%s.%s", FormTypeWebSocket, verify)
|
||
verifyMapWebSocket[key] = verifyFunc
|
||
}
|
||
|
||
// Verify 验证器
|
||
type Verify interface {
|
||
GetCode() int // 有一个方法,返回code为200为成功
|
||
GetResult() bool // 返回是否成功
|
||
}
|
||
|
||
// VerifyHTTP http 验证
|
||
type VerifyHTTP func(request *Request, response *http.Response) (code int, isSucceed bool)
|
||
|
||
// VerifyWebSocket webSocket 验证
|
||
type VerifyWebSocket func(request *Request, seq string, msg []byte) (code int, isSucceed bool)
|
||
|
||
// Request 请求数据
|
||
type Request struct {
|
||
URL string // URL
|
||
Form string // http/webSocket/tcp
|
||
// Method string // 方法 GET/POST/PUT
|
||
// Headers map[string]string // Headers
|
||
//Body string // body
|
||
Verify string // 验证的方法
|
||
Timeout time.Duration // 请求超时时间
|
||
Debug bool // 是否开启Debug模式
|
||
MaxCon int // 每个连接的请求数
|
||
Keepalive bool // 是否开启长连接
|
||
Code int // 验证的状态码
|
||
}
|
||
|
||
// getVerifyKey 获取校验 key
|
||
func (r *Request) getVerifyKey() (key string) {
|
||
return fmt.Sprintf("%s.%s", r.Form, r.Verify)
|
||
}
|
||
|
||
// GetVerifyHTTP 获取数据校验方法
|
||
func (r *Request) GetVerifyHTTP() VerifyHTTP {
|
||
verify, ok := verifyMapHTTP[r.getVerifyKey()]
|
||
if !ok {
|
||
panic("GetVerifyHTTP 验证方法不存在:" + r.Verify)
|
||
}
|
||
return verify
|
||
}
|
||
|
||
// GetVerifyWebSocket 获取数据校验方法
|
||
func (r *Request) GetVerifyWebSocket() VerifyWebSocket {
|
||
verify, ok := verifyMapWebSocket[r.getVerifyKey()]
|
||
if !ok {
|
||
panic("GetVerifyWebSocket 验证方法不存在:" + r.Verify)
|
||
}
|
||
return verify
|
||
}
|
||
|
||
// NewRequest 生成请求结构体
|
||
// url 压测的url
|
||
// verify 验证方法 在server/verify中 http 支持:statusCode、json webSocket支持:json
|
||
// timeout 请求超时时间
|
||
// debug 是否开启debug
|
||
// path curl文件路径 http接口压测,自定义参数设置
|
||
func NewRequest(url string, verify string, code int, timeout time.Duration, debug bool,
|
||
maxCon int, keepalive bool) (request *Request, err error) {
|
||
|
||
form := ""
|
||
if strings.HasPrefix(url, "ws://") || strings.HasPrefix(url, "wss://") {
|
||
form = FormTypeWebSocket
|
||
}
|
||
if form == "" {
|
||
err = fmt.Errorf("url:%s 不合法,必须是完整http、webSocket连接", url)
|
||
return
|
||
}
|
||
var ok bool
|
||
switch form {
|
||
case FormTypeWebSocket:
|
||
// verify
|
||
if verify == "" {
|
||
verify = "json"
|
||
}
|
||
key := fmt.Sprintf("%s.%s", form, verify)
|
||
_, ok = verifyMapWebSocket[key]
|
||
if !ok {
|
||
err = errors.New("验证器不存在:" + key)
|
||
return
|
||
}
|
||
}
|
||
if timeout == 0 {
|
||
timeout = 30 * time.Second
|
||
}
|
||
request = &Request{
|
||
URL: url,
|
||
Form: form,
|
||
Verify: verify,
|
||
Timeout: timeout,
|
||
Debug: debug,
|
||
MaxCon: maxCon,
|
||
Keepalive: keepalive,
|
||
Code: code,
|
||
}
|
||
return
|
||
}
|
||
|
||
// getHeaderValue 获取 header
|
||
func getHeaderValue(v string, headers map[string]string) {
|
||
index := strings.Index(v, ":")
|
||
if index < 0 {
|
||
return
|
||
}
|
||
vIndex := index + 1
|
||
if len(v) >= vIndex {
|
||
value := strings.TrimPrefix(v[vIndex:], " ")
|
||
if _, ok := headers[v[:index]]; ok {
|
||
headers[v[:index]] = fmt.Sprintf("%s; %s", headers[v[:index]], value)
|
||
} else {
|
||
headers[v[:index]] = value
|
||
}
|
||
}
|
||
}
|
||
|
||
// Print 格式化打印
|
||
func (r *Request) Print() {
|
||
if r == nil {
|
||
return
|
||
}
|
||
result := fmt.Sprintf("request:\n form:%s \n url:%s \n", r.Form, r.URL)
|
||
//result = fmt.Sprintf("%s data:%v \n", result, r.Body)
|
||
result = fmt.Sprintf("%s verify:%s \n timeout:%s \n debug:%v \n", result, r.Verify, r.Timeout, r.Debug)
|
||
//result = fmt.Sprintf("%s http2.0:%v \n keepalive:%v \n maxCon:%v ", result, r.HTTP2, r.Keepalive, r.MaxCon)
|
||
fmt.Println(result)
|
||
return
|
||
}
|
||
|
||
// GetDebug 获取 debug 参数
|
||
func (r *Request) GetDebug() bool {
|
||
return r.Debug
|
||
}
|
||
|
||
// IsParameterLegal 参数是否合法
|
||
func (r *Request) IsParameterLegal() (err error) {
|
||
r.Form = "http"
|
||
// statusCode json
|
||
r.Verify = "json"
|
||
key := fmt.Sprintf("%s.%s", r.Form, r.Verify)
|
||
_, ok := verifyMapHTTP[key]
|
||
if !ok {
|
||
return errors.New("验证器不存在:" + key)
|
||
}
|
||
return
|
||
}
|
||
|
||
// RequestResults 请求结果
|
||
type RequestResults struct {
|
||
ID string // 消息ID
|
||
ChanID uint64 // 消息ID
|
||
Time uint64 // 请求时间 纳秒
|
||
IsSucceed bool // 是否请求成功
|
||
ErrCode int // 错误码
|
||
ReceivedBytes int64
|
||
}
|
||
|
||
// SetID 设置请求唯一ID
|
||
func (r *RequestResults) SetID(chanID uint64, number uint64) {
|
||
id := fmt.Sprintf("%d_%d", chanID, number)
|
||
r.ID = id
|
||
r.ChanID = chanID
|
||
}
|