更新时间:2023-07-03 GMT+08:00
自定义样例
自定义请求样例
自定义请求Go样例:
package main import ( "crypto/tls" "encoding/json" "errors" "fmt" "io/ioutil" "net/http" "net/http/cookiejar" "strings" "sync" ) var ( trs = sync.Map{} jars = sync.Map{} ) func getTr(addr string) *http.Transport { if v, ok := trs.Load(addr); ok { return v.(*http.Transport) } else { tr := &http.Transport{ TLSClientConfig: &tls.Config{ InsecureSkipVerify: true, }, MaxConnsPerHost: 5000, MaxIdleConnsPerHost: 5000, } v, _ = trs.LoadOrStore(addr, tr) return v.(*http.Transport) } } func getJar(goroutineId string) *cookiejar.Jar { if v, ok := jars.Load(goroutineId); ok { return v.(*cookiejar.Jar) } else { jar, _ := cookiejar.New(nil) v, _ = jars.LoadOrStore(goroutineId, jar) return v.(*cookiejar.Jar) } } func outgoingLength(req *http.Request) int64 { if req.Body == nil || req.Body == http.NoBody { return 0 } if req.ContentLength != 0 { return req.ContentLength } return -1 } func redirectBehavior(reqMethod string, resp *http.Response, req *http.Request) (redirectMethod string, shouldRedirect, includeBody bool) { switch resp.StatusCode { case 301, 302, 303: redirectMethod = reqMethod shouldRedirect = true includeBody = false if reqMethod != "GET" && reqMethod != "HEAD" { redirectMethod = "GET" } case 307, 308: redirectMethod = reqMethod shouldRedirect = true includeBody = true if resp.Header.Get("Location") == "" { shouldRedirect = false break } if req.GetBody == nil && outgoingLength(req) != 0 { shouldRedirect = false } } return redirectMethod, shouldRedirect, includeBody } func Do(params map[string]string) interface{} { parent := acquireResult(params[InnerVarName]) sub := parent var ( err error redirectCount int req *http.Request res *http.Response ) defer func() { if p := recover(); p != nil { sub.ResponseCode = 500 sub.Success = false sub.FailureMessage = fmt.Sprintf("%v", sub) } else if err != nil { sub.ResponseCode = 500 sub.Success = false sub.FailureMessage = err.Error() } }() redirect := params["redirect"] for { // process params url, method, body := params["url"], params["method"], params["body"] sub.Url, sub.Method, sub.RequestBody = url, method, body sub.SentBytes = len(body) // create request req, err = http.NewRequest(method, url, strings.NewReader(body)) if err != nil { return parent } // load cookies jar := getJar(params[InnerVarGoroutineId]) cookies := jar.Cookies(req.URL) for _, c := range cookies { req.AddCookie(c) } // write headers if params["headers"] != "" { headers := map[string][]string{} if err = json.Unmarshal([]byte(params["headers"]), &headers); err != nil { return parent } for k, vs := range headers { for _, v := range vs { req.Header.Add(k, v) } } } for k, v := range req.Header { sub.RequestHeader[k] = strings.Join(v, ",") } // do request sub.begin() res, err = getTr(fmt.Sprintf("%s://%s", req.URL.Scheme, req.URL.Host)).RoundTrip(req) sub.end() if err != nil { return parent } var b []byte b, err = ioutil.ReadAll(res.Body) if err != nil { _ = res.Body.Close() return parent } // store cookies jar.SetCookies(req.URL, res.Cookies()) for k, v := range res.Header { sub.ResponseHeader[k] = strings.Join(v, ",") } sub.ResponseBody = string(b) sub.ReceivedBytes = len(b) sub.ResponseCode = res.StatusCode _ = res.Body.Close() if redirect != "on" { break } if redirectMethod, shouldRedirect, includeBody := redirectBehavior(method, res, req); shouldRedirect { redirectCount++ if redirectCount > 10 { err = errors.New("stopped after 10 redirects") return parent } params["url"] = res.Header.Get("Location") params["method"] = redirectMethod if !includeBody { params["body"] = "" } parent = acquireResult(params[InnerVarName]) sub = parent continue } break } return parent }
自定义请求JSON样例:
{ "name": "Http 1.0", "plugin": "http.so", "desc": "Http plugin supports http 1.0 test.", "funcs": [ { "name": "Do", "type": "req", "desc": "This is the entry of http request.", "params": [ { "name": "url", "default": "", "range": [], "desc": "The url of http request", "required": true }, { "name": "headers", "default": "{\"Content-Type\": [\"text/plain;utf-8\"]}", "range": [], "desc": "The headers of http request", "required": true }, { "name": "method", "default": "GET", "range": [ "GET", "HEAD", "POST", "PUT", "PATCH", "DELETE", "CONNECT", "OPTIONS", "TRACE" ], "desc": "The method of http request", "required": true }, { "name": "body", "default": "", "range": [], "desc": "The body of http request", "required": true }, { "name": "redirect", "default": "on", "range": [ "on", "off" ], "desc": "If enable auto redirect", "required": true } ] } ] }
自定义函数样例
自定义函数Go样例:
package main import ( "fmt" "math/rand" "strconv" ) func RandomNum(params map[string]string) (s string) { var err error defer func() { if r := recover(); r != nil { s = fmt.Sprintf("%v", r) } else if err != nil { s = err.Error() } }() min, err := strconv.ParseInt(params["min"], 10, 64) if err != nil { return } max, err := strconv.ParseInt(params["max"], 10, 64) if err != nil { return } if min > max { min, max = max, min } return strconv.FormatInt(min+rand.Int63n(max-min+1), 10) } var ( charSet = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789") ) func RandomText(params map[string]string) (s string) { var err error defer func() { if r := recover(); r != nil { s = fmt.Sprintf("%v", r) } else if err != nil { s = err.Error() } }() length, err := strconv.ParseInt(params["length"], 10, 64) if err != nil { return } if length == 0 { return "" } set := []rune(params["charset"]) if len(set) == 0 { set = charSet } n := len(set) rs := make([]rune, length) for i := int64(0); i < length; i++ { rs[i] = set[rand.Intn(n)] } return string(rs) }
自定义函数JSON样例:
{ "name": "Random", "plugin": "random.so", "desc": "Random plugin supports generating random value.", "funcs": [ { "name": "RandomNum", "type": "func", "desc": "RandomNum generates random number.", "params": [ { "name": "min", "default": "0", "range": [], "desc": "The maximum of random number.", "required": true }, { "name": "max", "default": "100", "range": [], "desc": "The maximum of random number.", "required": true } ] }, { "name": "RandomText", "type": "func", "desc": "RandomText generates random text of a specified length.", "params": [ { "name": "length", "default": "32", "range": [], "desc": "The length of random text.", "required": true }, { "name": "charset", "default": "", "range": [], "desc": "Random text is generated randomly from the specified character set. if empty, default char set is 0-9 a-z A-Z", "required": false } ] } ] }
父主题: 插件管理