requests/workflow.go

282 lines
6.0 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.SetURL(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
}
// GetStringURL 获取url的string形式
func (wf *Workflow) GetStringURL() string {
u := strings.Split(wf.ParsedURL.String(), "?")[0] + "?" + wf.GetCombineQuery().Encode()
return u
}
// SetURL 设置 url
func (wf *Workflow) SetURL(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(params ...interface{}) *Workflow {
if params != nil {
plen := len(params)
defaultContentType := TypeURLENCODED
if plen >= 2 {
t := params[plen-1]
defaultContentType = t.(string)
wf.Body.AddContentType(defaultContentType)
} else {
wf.Body.AddContentType(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)
}