301 lines
6.3 KiB
Go
301 lines
6.3 KiB
Go
package requests
|
|
|
|
import (
|
|
"net/http"
|
|
"net/url"
|
|
"regexp"
|
|
"strings"
|
|
)
|
|
|
|
// Workflow 工作流
|
|
type Workflow struct {
|
|
session *Session
|
|
ParsedURL *url.URL
|
|
Method string
|
|
Body IBody
|
|
Header http.Header
|
|
Cookies map[string]*http.Cookie
|
|
}
|
|
|
|
// NewWorkflow new and init workflow
|
|
func NewWorkflow(ses *Session, u string) *Workflow {
|
|
wf := &Workflow{}
|
|
wf.SwitchSession(ses)
|
|
|
|
wf.SetRawURL(u)
|
|
|
|
wf.Body = NewBody()
|
|
wf.Header = make(http.Header)
|
|
wf.Cookies = make(map[string]*http.Cookie)
|
|
return wf
|
|
}
|
|
|
|
// SwitchSession 替换Session
|
|
func (wf *Workflow) SwitchSession(ses *Session) {
|
|
wf.session = ses
|
|
}
|
|
|
|
// AddHeader 添加头信息 Get方法从Header参数上获取
|
|
func (wf *Workflow) AddHeader(key, value string) *Workflow {
|
|
wf.Header.Add(key, value)
|
|
return wf
|
|
}
|
|
|
|
// SetHeader 设置头信息 这样构造 []string{value} Get方法从Header参数上获取
|
|
func (wf *Workflow) SetHeader(key, value string) *Workflow {
|
|
wf.Header.Set(key, value)
|
|
return wf
|
|
}
|
|
|
|
// GetHeader 获取Workflow Header
|
|
func (wf *Workflow) GetHeader() http.Header {
|
|
return wf.Header
|
|
}
|
|
|
|
// GetCombineHeader 获取后的Header信息
|
|
func (wf *Workflow) GetCombineHeader() http.Header {
|
|
return mergeMapList(wf.session.Header, wf.Header)
|
|
}
|
|
|
|
// DelHeader 添加头信息 Get方法从Header参数上获取
|
|
func (wf *Workflow) DelHeader(key string) *Workflow {
|
|
wf.Header.Del(key)
|
|
return wf
|
|
}
|
|
|
|
// AddCookie 添加Cookie
|
|
func (wf *Workflow) AddCookie(c *http.Cookie) *Workflow {
|
|
wf.Cookies[c.Name] = c
|
|
return wf
|
|
}
|
|
|
|
// AddKVCookie 添加 以 key value 的 Cookie
|
|
func (wf *Workflow) AddKVCookie(name, value string) *Workflow {
|
|
wf.Cookies[name] = &http.Cookie{Name: name, Value: value}
|
|
return wf
|
|
}
|
|
|
|
// DelCookie 删除Cookie
|
|
func (wf *Workflow) DelCookie(name interface{}) *Workflow {
|
|
switch n := name.(type) {
|
|
case string:
|
|
if _, ok := wf.Cookies[n]; ok {
|
|
delete(wf.Cookies, n)
|
|
return wf
|
|
}
|
|
case *http.Cookie:
|
|
if _, ok := wf.Cookies[n.Name]; ok {
|
|
delete(wf.Cookies, n.Name)
|
|
return wf
|
|
}
|
|
default:
|
|
panic("name type is not support")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// GetParsedURL 获取url的string形式
|
|
func (wf *Workflow) GetParsedURL() *url.URL {
|
|
return wf.ParsedURL
|
|
}
|
|
|
|
// SetParsedURL 获取url的string形式
|
|
func (wf *Workflow) SetParsedURL(u *url.URL) *Workflow {
|
|
wf.ParsedURL = u
|
|
return wf
|
|
}
|
|
|
|
// GetRawURL 获取url的string形式
|
|
func (wf *Workflow) GetRawURL() string {
|
|
u := strings.Split(wf.ParsedURL.String(), "?")[0] + "?" + wf.GetCombineQuery().Encode()
|
|
return u
|
|
}
|
|
|
|
// SetRawURL 设置 url
|
|
func (wf *Workflow) SetRawURL(srcURL string) *Workflow {
|
|
purl, err := url.ParseRequestURI(srcURL)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
wf.ParsedURL = purl
|
|
return wf
|
|
}
|
|
|
|
// GetQuery 获取Query参数
|
|
func (wf *Workflow) GetQuery() url.Values {
|
|
return wf.ParsedURL.Query()
|
|
}
|
|
|
|
// GetCombineQuery 获取Query参数
|
|
func (wf *Workflow) GetCombineQuery() url.Values {
|
|
if wf.ParsedURL != nil {
|
|
vs := wf.ParsedURL.Query()
|
|
return mergeMapList(wf.session.GetQuery(), vs)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// SetQuery 设置Query参数
|
|
func (wf *Workflow) SetQuery(query url.Values) *Workflow {
|
|
if query == nil {
|
|
return wf
|
|
}
|
|
query = (url.Values)(mergeMapList(wf.session.Query, query))
|
|
wf.ParsedURL.RawQuery = query.Encode()
|
|
return wf
|
|
}
|
|
|
|
var regexGetPath = regexp.MustCompile("/[^/]*")
|
|
|
|
// GetURLPath 获取Path参数
|
|
func (wf *Workflow) GetURLPath() []string {
|
|
return regexGetPath.FindAllString(wf.ParsedURL.Path, -1)
|
|
}
|
|
|
|
// GetURLRawPath 获取未分解Path参数
|
|
func (wf *Workflow) GetURLRawPath() string {
|
|
return wf.ParsedURL.Path
|
|
}
|
|
|
|
// encodePath path格式每个item都必须以/开头
|
|
func encodePath(path []string) string {
|
|
rawpath := ""
|
|
for _, p := range path {
|
|
if p[0] != '/' {
|
|
p = "/" + p
|
|
}
|
|
rawpath += p
|
|
}
|
|
return rawpath
|
|
}
|
|
|
|
// SetURLPath 设置Path参数
|
|
func (wf *Workflow) SetURLPath(path []string) *Workflow {
|
|
if path == nil {
|
|
return wf
|
|
}
|
|
wf.ParsedURL.Path = encodePath(path)
|
|
return wf
|
|
}
|
|
|
|
// SetURLRawPath 设置Pa晚上参数
|
|
func (wf *Workflow) SetURLRawPath(path string) *Workflow {
|
|
wf.ParsedURL.Path = path
|
|
return wf
|
|
}
|
|
|
|
// SetBody 参数设置
|
|
func (wf *Workflow) SetBody(body IBody) *Workflow {
|
|
wf.Body = body
|
|
return wf
|
|
}
|
|
|
|
// GetBody 参数设置
|
|
func (wf *Workflow) GetBody(body IBody) IBody {
|
|
return wf.Body
|
|
}
|
|
|
|
// AutoSetBody 参数设置
|
|
func (wf *Workflow) AutoSetBody(params ...interface{}) *Workflow {
|
|
|
|
if params != nil {
|
|
plen := len(params)
|
|
defaultContentType := TypeURLENCODED
|
|
|
|
if plen >= 2 {
|
|
t := params[plen-1]
|
|
defaultContentType = t.(string)
|
|
}
|
|
|
|
wf.Body.SetPrefix(defaultContentType)
|
|
|
|
if defaultContentType == TypeFormData {
|
|
createMultipart(wf.Body, params)
|
|
} else {
|
|
var values url.Values
|
|
switch param := params[0].(type) {
|
|
case map[string]string:
|
|
values := make(url.Values)
|
|
for k, v := range param {
|
|
values.Set(k, v)
|
|
}
|
|
wf.Body.SetIOBody([]byte(values.Encode()))
|
|
case map[string][]string:
|
|
values = param
|
|
wf.Body.SetIOBody([]byte(values.Encode()))
|
|
case string:
|
|
wf.Body.SetIOBody([]byte(param))
|
|
case []byte:
|
|
wf.Body.SetIOBody(param)
|
|
}
|
|
|
|
}
|
|
}
|
|
return wf
|
|
}
|
|
|
|
func mergeMapList(headers ...map[string][]string) map[string][]string {
|
|
|
|
set := make(map[string]map[string]int)
|
|
merged := make(map[string][]string)
|
|
|
|
for _, header := range headers {
|
|
for key, values := range header {
|
|
for _, v := range values {
|
|
if vs, ok := set[key]; ok {
|
|
vs[v] = 1
|
|
} else {
|
|
set[key] = make(map[string]int)
|
|
set[key][v] = 1
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
for key, mvalue := range set {
|
|
for v := range mvalue {
|
|
// merged.Add(key, v)
|
|
if mergeValue, ok := merged[key]; ok {
|
|
merged[key] = append(mergeValue, v)
|
|
} else {
|
|
merged[key] = []string{v}
|
|
}
|
|
}
|
|
}
|
|
|
|
return merged
|
|
}
|
|
|
|
// setHeaderRequest 设置request的头
|
|
func setHeaderRequest(req *http.Request, wf *Workflow) {
|
|
req.Header = mergeMapList(req.Header, wf.session.Header, wf.Header)
|
|
}
|
|
|
|
// setHeaderRequest 设置request的临时Cookie, 永久需要在session上设置cookie
|
|
func setTempCookieRequest(req *http.Request, wf *Workflow) {
|
|
if wf.Cookies != nil {
|
|
for _, c := range wf.Cookies {
|
|
req.AddCookie(c)
|
|
}
|
|
}
|
|
}
|
|
|
|
// Execute 执行
|
|
func (wf *Workflow) Execute() (*Response, error) {
|
|
|
|
req := buildBodyRequest(wf)
|
|
|
|
setHeaderRequest(req, wf)
|
|
setTempCookieRequest(req, wf)
|
|
|
|
if wf.session.auth != nil {
|
|
req.SetBasicAuth(wf.session.auth.User, wf.session.auth.Password)
|
|
}
|
|
|
|
resp, err := wf.session.client.Do(req)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return FromHTTPResponse(resp)
|
|
}
|