package waf import ( "crypto/hmac" "crypto/sha256" "encoding/hex" "encoding/json" "github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs" "github.com/TeaOSLab/EdgeNode/internal/compressions" "github.com/TeaOSLab/EdgeNode/internal/ttlcache" "github.com/TeaOSLab/EdgeNode/internal/utils" "github.com/TeaOSLab/EdgeNode/internal/utils/fasttime" "github.com/TeaOSLab/EdgeNode/internal/waf/requests" wafutils "github.com/TeaOSLab/EdgeNode/internal/waf/utils" "github.com/iwind/TeaGo/logs" "github.com/iwind/TeaGo/maps" "github.com/iwind/TeaGo/rands" "github.com/iwind/TeaGo/types" stringutil "github.com/iwind/TeaGo/utils/string" "io" "net/http" "net/url" "strconv" "strings" "time" ) const captchaIdName = "GOEDGE_WAF_CAPTCHA_ID" const captchaCookiePrefix = "ge_wc" // 'wc' stands for "WAF Captcha" var captchaValidator = NewCaptchaValidator() var captchaGenerator = NewCaptchaGenerator() type CaptchaValidator struct { } func NewCaptchaValidator() *CaptchaValidator { return &CaptchaValidator{} } func (this *CaptchaValidator) Run(req requests.Request, writer http.ResponseWriter, defaultCaptchaType firewallconfigs.ServerCaptchaType) { var realURL string var urlObj = req.WAFRaw().URL if urlObj != nil { realURL = urlObj.Query().Get("from") } var info = req.WAFRaw().URL.Query().Get("info") if len(info) == 0 { if len(realURL) > 0 { req.ProcessResponseHeaders(writer.Header(), http.StatusTemporaryRedirect) http.Redirect(writer, req.WAFRaw(), realURL, http.StatusTemporaryRedirect) } else { req.ProcessResponseHeaders(writer.Header(), http.StatusBadRequest) writer.WriteHeader(http.StatusBadRequest) _, _ = writer.Write([]byte("invalid request (001)")) } return } var success bool var actionId int64 var setId int64 var originURL string var policyId int64 var groupId int64 var useLocalFirewall bool var timestamp int64 var infoArg = &InfoArg{} decodeErr := infoArg.Decode(info) if decodeErr == nil && infoArg.IsValid() { success = true actionId = infoArg.ActionId setId = infoArg.SetId originURL = infoArg.URL policyId = infoArg.PolicyId groupId = infoArg.GroupId useLocalFirewall = infoArg.UseLocalFirewall timestamp = infoArg.Timestamp } else { // 兼容老版本 m, decodeMapErr := utils.SimpleDecryptMap(info) if decodeMapErr == nil { success = true actionId = m.GetInt64("actionId") setId = m.GetInt64("setId") originURL = m.GetString("url") policyId = m.GetInt64("policyId") groupId = m.GetInt64("groupId") useLocalFirewall = m.GetBool("useLocalFirewall") timestamp = m.GetInt64("timestamp") } } if !success { if len(realURL) > 0 { req.ProcessResponseHeaders(writer.Header(), http.StatusTemporaryRedirect) http.Redirect(writer, req.WAFRaw(), realURL, http.StatusTemporaryRedirect) } else { req.ProcessResponseHeaders(writer.Header(), http.StatusBadRequest) writer.WriteHeader(http.StatusBadRequest) _, _ = writer.Write([]byte("invalid request (005)")) } return } if timestamp < fasttime.Now().Unix()-600 { // 10分钟之后信息过期 req.ProcessResponseHeaders(writer.Header(), http.StatusTemporaryRedirect) http.Redirect(writer, req.WAFRaw(), originURL, http.StatusTemporaryRedirect) return } var waf = SharedWAFManager.FindWAF(policyId) if waf == nil { req.ProcessResponseHeaders(writer.Header(), http.StatusTemporaryRedirect) http.Redirect(writer, req.WAFRaw(), originURL, http.StatusTemporaryRedirect) return } var actionConfig = waf.FindAction(actionId) if actionConfig == nil { req.ProcessResponseHeaders(writer.Header(), http.StatusTemporaryRedirect) http.Redirect(writer, req.WAFRaw(), originURL, http.StatusTemporaryRedirect) return } captchaActionConfig, ok := actionConfig.(*CaptchaAction) if !ok { req.ProcessResponseHeaders(writer.Header(), http.StatusTemporaryRedirect) http.Redirect(writer, req.WAFRaw(), originURL, http.StatusTemporaryRedirect) return } var captchaType = captchaActionConfig.CaptchaType if len(defaultCaptchaType) > 0 && defaultCaptchaType != firewallconfigs.ServerCaptchaTypeNone { captchaType = defaultCaptchaType } // check geetest if captchaType == firewallconfigs.CaptchaTypeGeeTest { if waf.DefaultCaptchaAction.GeeTestConfig == nil || !waf.DefaultCaptchaAction.GeeTestConfig.IsOn { captchaType = firewallconfigs.CaptchaTypeDefault } else if captchaActionConfig.GeeTestConfig == nil { captchaActionConfig.GeeTestConfig = waf.DefaultCaptchaAction.GeeTestConfig } } if req.WAFRaw().Method == http.MethodPost && len(req.WAFRaw().FormValue(captchaIdName)) > 0 { switch captchaType { case firewallconfigs.CaptchaTypeOneClick: this.validateOneClickForm(captchaActionConfig, policyId, groupId, setId, originURL, req, writer, useLocalFirewall) case firewallconfigs.CaptchaTypeSlide: this.validateSlideForm(captchaActionConfig, policyId, groupId, setId, originURL, req, writer, useLocalFirewall) case firewallconfigs.CaptchaTypeGeeTest: this.validateGeeTestForm(captchaActionConfig, policyId, groupId, setId, originURL, req, writer, useLocalFirewall) default: this.validateVerifyCodeForm(captchaActionConfig, policyId, groupId, setId, originURL, req, writer, useLocalFirewall) } } else { var captchaId = req.WAFRaw().URL.Query().Get(captchaIdName) if len(captchaId) > 0 { // 增加计数 CaptchaIncreaseFails(req, captchaActionConfig, policyId, groupId, setId, CaptchaPageCodeImage, useLocalFirewall) this.showImage(captchaActionConfig, req, writer, captchaType) } else { // 增加计数 CaptchaIncreaseFails(req, captchaActionConfig, policyId, groupId, setId, CaptchaPageCodeShow, useLocalFirewall) this.show(captchaActionConfig, setId, originURL, req, writer, captchaType) } } } func (this *CaptchaValidator) show(actionConfig *CaptchaAction, setId int64, originURL string, req requests.Request, writer http.ResponseWriter, captchaType firewallconfigs.ServerCaptchaType) { // validated yet? if SharedIPWhiteList.Contains(wafutils.ComposeIPType(setId, req), actionConfig.Scope, req.WAFServerId(), req.WAFRemoteIP()) { http.Redirect(writer, req.WAFRaw(), originURL, http.StatusSeeOther) return } switch captchaType { case firewallconfigs.CaptchaTypeOneClick: this.showOneClickForm(actionConfig, req, writer) case firewallconfigs.CaptchaTypeSlide: this.showSlideForm(actionConfig, req, writer) case firewallconfigs.CaptchaTypeGeeTest: this.showGeeTestForm(actionConfig, req, writer, originURL) default: this.showVerifyCodesForm(actionConfig, req, writer) } } func (this *CaptchaValidator) showImage(actionConfig *CaptchaAction, req requests.Request, writer http.ResponseWriter, captchaType firewallconfigs.ServerCaptchaType) { switch captchaType { case firewallconfigs.CaptchaTypeOneClick: // stub case firewallconfigs.CaptchaTypeSlide: // stub case firewallconfigs.CaptchaTypeGeeTest: // stub default: this.showVerifyImage(actionConfig, req, writer) } } func (this *CaptchaValidator) showVerifyCodesForm(actionConfig *CaptchaAction, req requests.Request, writer http.ResponseWriter) { // show captcha var countLetters = 6 if actionConfig.CountLetters > 0 && actionConfig.CountLetters <= 10 { countLetters = int(actionConfig.CountLetters) } var captchaId = captchaGenerator.NewCaptcha(countLetters) var lang = actionConfig.Lang if len(lang) == 0 { var acceptLanguage = req.WAFRaw().Header.Get("Accept-Language") if len(acceptLanguage) > 0 { langIndex := strings.Index(acceptLanguage, ",") if langIndex > 0 { lang = acceptLanguage[:langIndex] } } } if len(lang) == 0 { lang = "en-US" } var msgTitle string var msgPrompt string var msgButtonTitle string var msgRequestId string var msgPlaceholder string switch lang { case "en-US": msgTitle = "Verify Yourself" msgPrompt = "Input verify code above:" msgButtonTitle = "Verify Yourself" msgRequestId = "Request ID" msgPlaceholder = "" case "zh-CN": msgTitle = "身份验证" msgPrompt = "请输入上面的验证码" msgButtonTitle = "提交验证" msgRequestId = "请求ID" msgPlaceholder = "点此输入" case "zh-TW": msgTitle = "身份驗證" msgPrompt = "請輸入上面的驗證碼" msgButtonTitle = "提交驗證" msgRequestId = "請求ID" msgPlaceholder = "點此輸入" default: msgTitle = "Verify Yourself" msgPrompt = "Input verify code above:" msgButtonTitle = "Verify Yourself" msgRequestId = "Request ID" } var msgCss = "" var requestIdBox = `
` + msgRequestId + `: ` + req.Format("${requestId}") + `
` var msgFooter = "" // 默认设置 if actionConfig.UIIsOn { if len(actionConfig.UIPrompt) > 0 { msgPrompt = actionConfig.UIPrompt } if len(actionConfig.UIButtonTitle) > 0 { msgButtonTitle = actionConfig.UIButtonTitle } if len(actionConfig.UITitle) > 0 { msgTitle = actionConfig.UITitle } if len(actionConfig.UICss) > 0 { msgCss = actionConfig.UICss } if !actionConfig.UIShowRequestId { requestIdBox = "" } if len(actionConfig.UIFooter) > 0 { msgFooter = actionConfig.UIFooter } } var body = `

loading ...

` + msgPrompt + `

` + requestIdBox + ` ` + msgFooter // Body if actionConfig.UIIsOn { if len(actionConfig.UIBody) > 0 { var index = strings.Index(actionConfig.UIBody, "${body}") if index < 0 { body = actionConfig.UIBody + body } else { body = actionConfig.UIBody[:index] + body + actionConfig.UIBody[index+7:] // 7是"${body}"的长度 } } } var msgHTML = ` ` + msgTitle + ` ` + body + ` ` req.ProcessResponseHeaders(writer.Header(), http.StatusOK) writer.Header().Set("Content-Type", "text/html; charset=utf-8") writer.Header().Set("Content-Length", types.String(len(msgHTML))) writer.WriteHeader(http.StatusOK) _, _ = writer.Write([]byte(msgHTML)) } func (this *CaptchaValidator) showVerifyImage(actionConfig *CaptchaAction, req requests.Request, writer http.ResponseWriter) { var captchaId = req.WAFRaw().URL.Query().Get(captchaIdName) if len(captchaId) == 0 { return } writer.Header().Set("Content-Type", "image/png") err := captchaGenerator.WriteImage(writer, captchaId, 200, 100) if err != nil { logs.Error(err) return } } func (this *CaptchaValidator) validateVerifyCodeForm(actionConfig *CaptchaAction, policyId int64, groupId int64, setId int64, originURL string, req requests.Request, writer http.ResponseWriter, useLocalFirewall bool) (allow bool) { var captchaId = req.WAFRaw().FormValue(captchaIdName) if len(captchaId) > 0 { var captchaCode = req.WAFRaw().FormValue("GOEDGE_WAF_CAPTCHA_CODE") if captchaGenerator.Verify(captchaId, captchaCode) { // 清除计数 CaptchaDeleteCacheKey(req) var life = CaptchaSeconds if actionConfig.Life > 0 { life = types.Int(actionConfig.Life) } // 加入到白名单 SharedIPWhiteList.RecordIP(wafutils.ComposeIPType(setId, req), actionConfig.Scope, req.WAFServerId(), req.WAFRemoteIP(), time.Now().Unix()+int64(life), policyId, false, groupId, setId, "") req.ProcessResponseHeaders(writer.Header(), http.StatusSeeOther) // 记录到Cookie this.setCookie(writer, setId, life) http.Redirect(writer, req.WAFRaw(), originURL, http.StatusSeeOther) return false } else { // 增加计数 if !CaptchaIncreaseFails(req, actionConfig, policyId, groupId, setId, CaptchaPageCodeSubmit, useLocalFirewall) { return false } req.ProcessResponseHeaders(writer.Header(), http.StatusSeeOther) http.Redirect(writer, req.WAFRaw(), req.WAFRaw().URL.String(), http.StatusSeeOther) } } return true } func (this *CaptchaValidator) showOneClickForm(actionConfig *CaptchaAction, req requests.Request, writer http.ResponseWriter) { var lang = actionConfig.Lang if len(lang) == 0 { var acceptLanguage = req.WAFRaw().Header.Get("Accept-Language") if len(acceptLanguage) > 0 { langIndex := strings.Index(acceptLanguage, ",") if langIndex > 0 { lang = acceptLanguage[:langIndex] } } } if len(lang) == 0 { lang = "en-US" } var msgTitle string var msgPrompt string var msgRequestId string switch lang { case "zh-CN": msgTitle = "身份验证" msgPrompt = "我不是机器人" msgRequestId = "请求ID" case "zh-TW": msgTitle = "身份驗證" msgPrompt = "我不是機器人" msgRequestId = "請求ID" default: msgTitle = "Verify Yourself" msgPrompt = "I'm not a robot" msgRequestId = "Request ID" } var msgCss = "" var requestIdBox = `
` + msgRequestId + `: ` + req.Format("${requestId}") + `
` var msgFooter = "" // 默认设置 if actionConfig.OneClickUIIsOn { if len(actionConfig.OneClickUIPrompt) > 0 { msgPrompt = actionConfig.OneClickUIPrompt } if len(actionConfig.OneClickUITitle) > 0 { msgTitle = actionConfig.OneClickUITitle } if len(actionConfig.OneClickUICss) > 0 { msgCss = actionConfig.OneClickUICss } if !actionConfig.OneClickUIShowRequestId { requestIdBox = "" } if len(actionConfig.OneClickUIFooter) > 0 { msgFooter = actionConfig.OneClickUIFooter } } var captchaId = stringutil.Md5(req.WAFRemoteIP() + "@" + stringutil.Rand(32)) var nonce = rands.Int64() if !ttlcache.SharedInt64Cache.Write("WAF_CAPTCHA:"+captchaId, nonce, fasttime.Now().Unix()+600) { return } var body = `

` + msgPrompt + `

` + requestIdBox + ` ` + msgFooter // Body if actionConfig.OneClickUIIsOn { if len(actionConfig.OneClickUIBody) > 0 { var index = strings.Index(actionConfig.OneClickUIBody, "${body}") if index < 0 { body = actionConfig.OneClickUIBody + body } else { body = actionConfig.OneClickUIBody[:index] + body + actionConfig.OneClickUIBody[index+7:] // 7是"${body}"的长度 } } } var msgHTML = ` ` + msgTitle + ` ` + body + ` ` req.ProcessResponseHeaders(writer.Header(), http.StatusOK) writer.Header().Set("Content-Type", "text/html; charset=utf-8") writer.Header().Set("Content-Length", types.String(len(msgHTML))) writer.WriteHeader(http.StatusOK) _, _ = writer.Write([]byte(msgHTML)) } func (this *CaptchaValidator) validateOneClickForm(actionConfig *CaptchaAction, policyId int64, groupId int64, setId int64, originURL string, req requests.Request, writer http.ResponseWriter, useLocalFirewall bool) (allow bool) { var captchaId = req.WAFRaw().FormValue(captchaIdName) var nonce = req.WAFRaw().FormValue("nonce") if len(captchaId) > 0 { var key = "WAF_CAPTCHA:" + captchaId var cacheItem = ttlcache.SharedInt64Cache.Read(key) ttlcache.SharedInt64Cache.Delete(key) if cacheItem != nil { // 清除计数 CaptchaDeleteCacheKey(req) if cacheItem.Value == types.Int64(nonce) { var life = CaptchaSeconds if actionConfig.Life > 0 { life = types.Int(actionConfig.Life) } // 加入到白名单 SharedIPWhiteList.RecordIP(wafutils.ComposeIPType(setId, req), actionConfig.Scope, req.WAFServerId(), req.WAFRemoteIP(), time.Now().Unix()+int64(life), policyId, false, groupId, setId, "") req.ProcessResponseHeaders(writer.Header(), http.StatusSeeOther) // 记录到Cookie this.setCookie(writer, setId, life) http.Redirect(writer, req.WAFRaw(), originURL, http.StatusSeeOther) return false } } else { // 增加计数 if !CaptchaIncreaseFails(req, actionConfig, policyId, groupId, setId, CaptchaPageCodeSubmit, useLocalFirewall) { return false } req.ProcessResponseHeaders(writer.Header(), http.StatusSeeOther) http.Redirect(writer, req.WAFRaw(), req.WAFRaw().URL.String(), http.StatusSeeOther) } } return true } func (this *CaptchaValidator) showSlideForm(actionConfig *CaptchaAction, req requests.Request, writer http.ResponseWriter) { var lang = actionConfig.Lang if len(lang) == 0 { var acceptLanguage = req.WAFRaw().Header.Get("Accept-Language") if len(acceptLanguage) > 0 { langIndex := strings.Index(acceptLanguage, ",") if langIndex > 0 { lang = acceptLanguage[:langIndex] } } } if len(lang) == 0 { lang = "en-US" } var msgTitle string var msgPrompt string var msgRequestId string switch lang { case "zh-CN": msgTitle = "身份验证" msgPrompt = "滑动上面方块到右侧解锁" msgRequestId = "请求ID" case "zh-TW": msgTitle = "身份驗證" msgPrompt = "滑動上面方塊到右側解鎖" msgRequestId = "請求ID" default: msgTitle = "Verify Yourself" msgPrompt = "Slide to Unlock" msgRequestId = "Request ID" } var msgCss = "" var requestIdBox = `
` + msgRequestId + `: ` + req.Format("${requestId}") + `
` var msgFooter = "" // 默认设置 if actionConfig.OneClickUIIsOn { if len(actionConfig.OneClickUIPrompt) > 0 { msgPrompt = actionConfig.OneClickUIPrompt } if len(actionConfig.OneClickUITitle) > 0 { msgTitle = actionConfig.OneClickUITitle } if len(actionConfig.OneClickUICss) > 0 { msgCss = actionConfig.OneClickUICss } if !actionConfig.OneClickUIShowRequestId { requestIdBox = "" } if len(actionConfig.OneClickUIFooter) > 0 { msgFooter = actionConfig.OneClickUIFooter } } var captchaId = stringutil.Md5(req.WAFRemoteIP() + "@" + stringutil.Rand(32)) var nonce = rands.Int64() if !ttlcache.SharedInt64Cache.Write("WAF_CAPTCHA:"+captchaId, nonce, fasttime.Now().Unix()+600) { return } var body = `

` + msgPrompt + `

` + requestIdBox + ` ` + msgFooter // Body if actionConfig.OneClickUIIsOn { if len(actionConfig.OneClickUIBody) > 0 { var index = strings.Index(actionConfig.OneClickUIBody, "${body}") if index < 0 { body = actionConfig.OneClickUIBody + body } else { body = actionConfig.OneClickUIBody[:index] + body + actionConfig.OneClickUIBody[index+7:] // 7是"${body}"的长度 } } } var msgHTML = ` ` + msgTitle + ` ` + body + ` ` req.ProcessResponseHeaders(writer.Header(), http.StatusOK) writer.Header().Set("Content-Type", "text/html; charset=utf-8") writer.Header().Set("Content-Length", types.String(len(msgHTML))) writer.WriteHeader(http.StatusOK) _, _ = writer.Write([]byte(msgHTML)) } func (this *CaptchaValidator) validateSlideForm(actionConfig *CaptchaAction, policyId int64, groupId int64, setId int64, originURL string, req requests.Request, writer http.ResponseWriter, useLocalFirewall bool) (allow bool) { var captchaId = req.WAFRaw().FormValue(captchaIdName) var nonce = req.WAFRaw().FormValue("nonce") if len(captchaId) > 0 { var key = "WAF_CAPTCHA:" + captchaId var cacheItem = ttlcache.SharedInt64Cache.Read(key) ttlcache.SharedInt64Cache.Delete(key) if cacheItem != nil { // 清除计数 CaptchaDeleteCacheKey(req) if cacheItem.Value == types.Int64(nonce) { var life = CaptchaSeconds if actionConfig.Life > 0 { life = types.Int(actionConfig.Life) } // 加入到白名单 SharedIPWhiteList.RecordIP(wafutils.ComposeIPType(setId, req), actionConfig.Scope, req.WAFServerId(), req.WAFRemoteIP(), time.Now().Unix()+int64(life), policyId, false, groupId, setId, "") req.ProcessResponseHeaders(writer.Header(), http.StatusSeeOther) // 记录到Cookie this.setCookie(writer, setId, life) http.Redirect(writer, req.WAFRaw(), originURL, http.StatusSeeOther) return false } } else { // 增加计数 if !CaptchaIncreaseFails(req, actionConfig, policyId, groupId, setId, CaptchaPageCodeSubmit, useLocalFirewall) { return false } req.ProcessResponseHeaders(writer.Header(), http.StatusSeeOther) http.Redirect(writer, req.WAFRaw(), req.WAFRaw().URL.String(), http.StatusSeeOther) } } return true } func (this *CaptchaValidator) validateGeeTestForm(actionConfig *CaptchaAction, policyId int64, groupId int64, setId int64, originURL string, req requests.Request, writer http.ResponseWriter, useLocalFirewall bool) (allow bool) { var geeTestConfig = actionConfig.GeeTestConfig if geeTestConfig == nil || !geeTestConfig.IsOn { return } defer func() { if allow { // 清除计数 CaptchaDeleteCacheKey(req) var life = CaptchaSeconds if actionConfig.Life > 0 { life = types.Int(actionConfig.Life) } // 加入到白名单 SharedIPWhiteList.RecordIP(wafutils.ComposeIPType(setId, req), actionConfig.Scope, req.WAFServerId(), req.WAFRemoteIP(), time.Now().Unix()+int64(life), policyId, false, groupId, setId, "") // 记录到Cookie this.setCookie(writer, setId, life) writer.WriteHeader(http.StatusOK) } else { // 增加计数 CaptchaIncreaseFails(req, actionConfig, policyId, groupId, setId, CaptchaPageCodeSubmit, useLocalFirewall) writer.WriteHeader(http.StatusBadRequest) } }() if req.WAFRaw().Body == nil || req.WAFRaw().ContentLength <= 0 || req.WAFRaw().ContentLength > 2048 { return false } data, err := io.ReadAll(req.WAFRaw().Body) if err != nil { return false } var m = maps.Map{} err = json.Unmarshal(data, &m) if err != nil { return false } const GeeTestAPIServer = "https://gcaptcha4.geetest.com" var GeeTestAPIURL = GeeTestAPIServer + "/validate" + "?captcha_id=" + geeTestConfig.CaptchaId var lotNumber = m.GetString("lot_number") var hash = hmac.New(sha256.New, []byte(geeTestConfig.CaptchaKey)) hash.Write([]byte(lotNumber)) var signToken = hex.EncodeToString(hash.Sum(nil)) var query = url.Values{ "lot_number": []string{lotNumber}, "captcha_output": []string{m.GetString("captcha_output")}, "pass_token": []string{m.GetString("pass_token")}, "gen_time": []string{m.GetString("gen_time")}, "sign_token": []string{signToken}, } resp, err := geeTestHTTPClient.PostForm(GeeTestAPIURL, query) defer func() { if resp != nil && resp.Body != nil { _ = resp.Body.Close() } }() if err != nil || resp.StatusCode != http.StatusOK { // 放行,避免阻塞业务 allow = true return } data, err = io.ReadAll(resp.Body) if err != nil { // 放行,避免阻塞业务 allow = true return } var resultMap = maps.Map{} err = json.Unmarshal(data, &resultMap) if err != nil { // 放行,避免阻塞业务 allow = true return } allow = resultMap.GetString("result") == "success" return allow } func (this *CaptchaValidator) showGeeTestForm(actionConfig *CaptchaAction, req requests.Request, writer http.ResponseWriter, originURL string) { var geeTestConfig = actionConfig.GeeTestConfig if geeTestConfig == nil || !geeTestConfig.IsOn { return } var lang = actionConfig.Lang if len(lang) == 0 { var acceptLanguage = req.WAFRaw().Header.Get("Accept-Language") if len(acceptLanguage) > 0 { langIndex := strings.Index(acceptLanguage, ",") if langIndex > 0 { lang = acceptLanguage[:langIndex] } } } if len(lang) == 0 { lang = "en-US" } var msgTitle string switch lang { case "zh-CN": msgTitle = "身份验证" case "zh-TW": msgTitle = "身份驗證" default: msgTitle = "Verify Yourself" } var msgHTML = ` ` + msgTitle + ` ` req.ProcessResponseHeaders(writer.Header(), http.StatusOK) writer.Header().Set("Content-Type", "text/html; charset=utf-8") this.compressWrite(req.WAFRaw(), writer, []byte(msgHTML)) } func (this *CaptchaValidator) compressWrite(req *http.Request, writer http.ResponseWriter, htmlContent []byte) { var acceptEncoding = req.Header.Get("Accept-Encoding") if strings.Contains(acceptEncoding, "gzip") { this.compressGzip(writer, htmlContent) } else if strings.Contains(acceptEncoding, "br") { this.compressBR(writer, htmlContent) } else { writer.Header().Set("Content-Length", types.String(len(htmlContent))) writer.WriteHeader(http.StatusOK) _, _ = writer.Write(htmlContent) } } func (this *CaptchaValidator) compressBR(writer http.ResponseWriter, htmlContent []byte) { compressWriter, err := compressions.NewBrotliWriter(writer, 0) if err != nil { writer.Header().Set("Content-Length", types.String(len(htmlContent))) writer.WriteHeader(http.StatusOK) _, _ = writer.Write(htmlContent) return } writer.Header().Set("Content-Encoding", "br") writer.WriteHeader(http.StatusOK) _, _ = compressWriter.Write(htmlContent) _ = compressWriter.Close() } func (this *CaptchaValidator) compressGzip(writer http.ResponseWriter, htmlContent []byte) { compressWriter, err := compressions.NewGzipWriter(writer, 0) if err != nil { writer.Header().Set("Content-Length", types.String(len(htmlContent))) writer.WriteHeader(http.StatusOK) _, _ = writer.Write(htmlContent) return } writer.Header().Set("Content-Encoding", "gzip") writer.WriteHeader(http.StatusOK) _, _ = compressWriter.Write(htmlContent) _ = compressWriter.Close() } func (this *CaptchaValidator) setCookie(writer http.ResponseWriter, setId int64, life int) { if life < 1 { return } infoString, err := (&AllowCookieInfo{ SetId: setId, ExpiresAt: time.Now().Unix() + int64(life), }).Encode() if err != nil { return } http.SetCookie(writer, &http.Cookie{ Name: captchaCookiePrefix + "_" + types.String(setId), Value: infoString, MaxAge: life, Path: "/", }) } const axiosJavascript = "!function(e,t){\"object\"==typeof exports&&\"undefined\"!=typeof module?module.exports=t():\"function\"==typeof define&&define.amd?define(t):(e=\"undefined\"!=typeof globalThis?globalThis:e||self).axios=t()}(this,(function(){\"use strict\";function e(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function t(t){for(var n=1;ne.length)&&(t=e.length);for(var n=0,r=new Array(t);n2&&void 0!==arguments[2]?arguments[2]:{},a=i.allOwnKeys,s=void 0!==a&&a;if(null!=e)if(\"object\"!==n(e)&&(e=[e]),O(e))for(r=0,o=e.length;r0;)if(t===(n=r[o]).toLowerCase())return n;return null}var D=\"undefined\"!=typeof globalThis?globalThis:\"undefined\"!=typeof self?self:\"undefined\"!=typeof window?window:global,B=function(e){return!E(e)&&e!==D};var L,I=(L=\"undefined\"!=typeof Uint8Array&&v(Uint8Array),function(e){return L&&e instanceof L}),q=g(\"HTMLFormElement\"),z=function(e){var t=Object.prototype.hasOwnProperty;return function(e,n){return t.call(e,n)}}(),M=g(\"RegExp\"),H=function(e,t){var n=Object.getOwnPropertyDescriptors(e),r={};F(n,(function(n,o){var i;!1!==(i=t(n,o,e))&&(r[o]=i||n)})),Object.defineProperties(e,r)},J=\"abcdefghijklmnopqrstuvwxyz\",W=\"0123456789\",K={DIGIT:W,ALPHA:J,ALPHA_DIGIT:J+J.toUpperCase()+W};var V=g(\"AsyncFunction\"),G={isArray:O,isArrayBuffer:S,isBuffer:function(e){return null!==e&&!E(e)&&null!==e.constructor&&!E(e.constructor)&&A(e.constructor.isBuffer)&&e.constructor.isBuffer(e)},isFormData:function(e){var t;return e&&(\"function\"==typeof FormData&&e instanceof FormData||A(e.append)&&(\"formdata\"===(t=b(e))||\"object\"===t&&A(e.toString)&&\"[object FormData]\"===e.toString()))},isArrayBufferView:function(e){return\"undefined\"!=typeof ArrayBuffer&&ArrayBuffer.isView?ArrayBuffer.isView(e):e&&e.buffer&&S(e.buffer)},isString:R,isNumber:j,isBoolean:function(e){return!0===e||!1===e},isObject:T,isPlainObject:P,isUndefined:E,isDate:N,isFile:x,isBlob:C,isRegExp:M,isFunction:A,isStream:function(e){return T(e)&&A(e.pipe)},isURLSearchParams:_,isTypedArray:I,isFileList:k,forEach:F,merge:function e(){for(var t=B(this)&&this||{},n=t.caseless,r={},o=function(t,o){var i=n&&U(r,o)||o;P(r[i])&&P(t)?r[i]=e(r[i],t):P(t)?r[i]=e({},t):O(t)?r[i]=t.slice():r[i]=t},i=0,a=arguments.length;i3&&void 0!==arguments[3]?arguments[3]:{},o=r.allOwnKeys;return F(t,(function(t,r){n&&A(t)?e[r]=h(t,n):e[r]=t}),{allOwnKeys:o}),e},trim:function(e){return e.trim?e.trim():e.replace(/^[\\s\\uFEFF\\xA0]+|[\\s\\uFEFF\\xA0]+$/g,\"\")},stripBOM:function(e){return 65279===e.charCodeAt(0)&&(e=e.slice(1)),e},inherits:function(e,t,n,r){e.prototype=Object.create(t.prototype,r),e.prototype.constructor=e,Object.defineProperty(e,\"super\",{value:t.prototype}),n&&Object.assign(e.prototype,n)},toFlatObject:function(e,t,n,r){var o,i,a,s={};if(t=t||{},null==e)return t;do{for(i=(o=Object.getOwnPropertyNames(e)).length;i-- >0;)a=o[i],r&&!r(a,e,t)||s[a]||(t[a]=e[a],s[a]=!0);e=!1!==n&&v(e)}while(e&&(!n||n(e,t))&&e!==Object.prototype);return t},kindOf:b,kindOfTest:g,endsWith:function(e,t,n){e=String(e),(void 0===n||n>e.length)&&(n=e.length),n-=t.length;var r=e.indexOf(t,n);return-1!==r&&r===n},toArray:function(e){if(!e)return null;if(O(e))return e;var t=e.length;if(!j(t))return null;for(var n=new Array(t);t-- >0;)n[t]=e[t];return n},forEachEntry:function(e,t){for(var n,r=(e&&e[Symbol.iterator]).call(e);(n=r.next())&&!n.done;){var o=n.value;t.call(e,o[0],o[1])}},matchAll:function(e,t){for(var n,r=[];null!==(n=e.exec(t));)r.push(n);return r},isHTMLForm:q,hasOwnProperty:z,hasOwnProp:z,reduceDescriptors:H,freezeMethods:function(e){H(e,(function(t,n){if(A(e)&&-1!==[\"arguments\",\"caller\",\"callee\"].indexOf(n))return!1;var r=e[n];A(r)&&(t.enumerable=!1,\"writable\"in t?t.writable=!1:t.set||(t.set=function(){throw Error(\"Can not rewrite read-only method '\"+n+\"'\")}))}))},toObjectSet:function(e,t){var n={},r=function(e){e.forEach((function(e){n[e]=!0}))};return O(e)?r(e):r(String(e).split(t)),n},toCamelCase:function(e){return e.toLowerCase().replace(/[-_\\s]([a-z\\d])(\\w*)/g,(function(e,t,n){return t.toUpperCase()+n}))},noop:function(){},toFiniteNumber:function(e,t){return e=+e,Number.isFinite(e)?e:t},findKey:U,global:D,isContextDefined:B,ALPHABET:K,generateString:function(){for(var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:16,t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:K.ALPHA_DIGIT,n=\"\",r=t.length;e--;)n+=t[Math.random()*r|0];return n},isSpecCompliantForm:function(e){return!!(e&&A(e.append)&&\"FormData\"===e[Symbol.toStringTag]&&e[Symbol.iterator])},toJSONObject:function(e){var t=new Array(10);return function e(n,r){if(T(n)){if(t.indexOf(n)>=0)return;if(!(\"toJSON\"in n)){t[r]=n;var o=O(n)?[]:{};return F(n,(function(t,n){var i=e(t,r+1);!E(i)&&(o[n]=i)})),t[r]=void 0,o}}return n}(e,0)},isAsyncFn:V,isThenable:function(e){return e&&(T(e)||A(e))&&A(e.then)&&A(e.catch)}};function X(e,t,n,r,o){Error.call(this),Error.captureStackTrace?Error.captureStackTrace(this,this.constructor):this.stack=(new Error).stack,this.message=e,this.name=\"AxiosError\",t&&(this.code=t),n&&(this.config=n),r&&(this.request=r),o&&(this.response=o)}G.inherits(X,Error,{toJSON:function(){return{message:this.message,name:this.name,description:this.description,number:this.number,fileName:this.fileName,lineNumber:this.lineNumber,columnNumber:this.columnNumber,stack:this.stack,config:G.toJSONObject(this.config),code:this.code,status:this.response&&this.response.status?this.response.status:null}}});var $=X.prototype,Q={};[\"ERR_BAD_OPTION_VALUE\",\"ERR_BAD_OPTION\",\"ECONNABORTED\",\"ETIMEDOUT\",\"ERR_NETWORK\",\"ERR_FR_TOO_MANY_REDIRECTS\",\"ERR_DEPRECATED\",\"ERR_BAD_RESPONSE\",\"ERR_BAD_REQUEST\",\"ERR_CANCELED\",\"ERR_NOT_SUPPORT\",\"ERR_INVALID_URL\"].forEach((function(e){Q[e]={value:e}})),Object.defineProperties(X,Q),Object.defineProperty($,\"isAxiosError\",{value:!0}),X.from=function(e,t,n,r,o,i){var a=Object.create($);return G.toFlatObject(e,a,(function(e){return e!==Error.prototype}),(function(e){return\"isAxiosError\"!==e})),X.call(a,e.message,t,n,r,o),a.cause=e,a.name=e.name,i&&Object.assign(a,i),a};function Z(e){return G.isPlainObject(e)||G.isArray(e)}function Y(e){return G.endsWith(e,\"[]\")?e.slice(0,-2):e}function ee(e,t,n){return e?e.concat(t).map((function(e,t){return e=Y(e),!n&&t?\"[\"+e+\"]\":e})).join(n?\".\":\"\"):t}var te=G.toFlatObject(G,{},null,(function(e){return/^is[A-Z]/.test(e)}));function ne(e,t,r){if(!G.isObject(e))throw new TypeError(\"target must be an object\");t=t||new FormData;var o=(r=G.toFlatObject(r,{metaTokens:!0,dots:!1,indexes:!1},!1,(function(e,t){return!G.isUndefined(t[e])}))).metaTokens,i=r.visitor||f,a=r.dots,s=r.indexes,u=(r.Blob||\"undefined\"!=typeof Blob&&Blob)&&G.isSpecCompliantForm(t);if(!G.isFunction(i))throw new TypeError(\"visitor must be a function\");function c(e){if(null===e)return\"\";if(G.isDate(e))return e.toISOString();if(!u&&G.isBlob(e))throw new X(\"Blob is not supported. Use a Buffer instead.\");return G.isArrayBuffer(e)||G.isTypedArray(e)?u&&\"function\"==typeof Blob?new Blob([e]):Buffer.from(e):e}function f(e,r,i){var u=e;if(e&&!i&&\"object\"===n(e))if(G.endsWith(r,\"{}\"))r=o?r:r.slice(0,-2),e=JSON.stringify(e);else if(G.isArray(e)&&function(e){return G.isArray(e)&&!e.some(Z)}(e)||(G.isFileList(e)||G.endsWith(r,\"[]\"))&&(u=G.toArray(e)))return r=Y(r),u.forEach((function(e,n){!G.isUndefined(e)&&null!==e&&t.append(!0===s?ee([r],n,a):null===s?r:r+\"[]\",c(e))})),!1;return!!Z(e)||(t.append(ee(i,r,a),c(e)),!1)}var l=[],d=Object.assign(te,{defaultVisitor:f,convertValue:c,isVisitable:Z});if(!G.isObject(e))throw new TypeError(\"data must be an object\");return function e(n,r){if(!G.isUndefined(n)){if(-1!==l.indexOf(n))throw Error(\"Circular reference detected in \"+r.join(\".\"));l.push(n),G.forEach(n,(function(n,o){!0===(!(G.isUndefined(n)||null===n)&&i.call(t,n,G.isString(o)?o.trim():o,r,d))&&e(n,r?r.concat(o):[o])})),l.pop()}}(e),t}function re(e){var t={\"!\":\"%21\",\"'\":\"%27\",\"(\":\"%28\",\")\":\"%29\",\"~\":\"%7E\",\"%20\":\"+\",\"%00\":\"\\0\"};return encodeURIComponent(e).replace(/[!'()~]|%20|%00/g,(function(e){return t[e]}))}function oe(e,t){this._pairs=[],e&&ne(e,this,t)}var ie=oe.prototype;function ae(e){return encodeURIComponent(e).replace(/%3A/gi,\":\").replace(/%24/g,\"$\").replace(/%2C/gi,\",\").replace(/%20/g,\"+\").replace(/%5B/gi,\"[\").replace(/%5D/gi,\"]\")}function se(e,t,n){if(!t)return e;var r,o=n&&n.encode||ae,i=n&&n.serialize;if(r=i?i(t,n):G.isURLSearchParams(t)?t.toString():new oe(t,n).toString(o)){var a=e.indexOf(\"#\");-1!==a&&(e=e.slice(0,a)),e+=(-1===e.indexOf(\"?\")?\"?\":\"&\")+r}return e}ie.append=function(e,t){this._pairs.push([e,t])},ie.toString=function(e){var t=e?function(t){return e.call(this,t,re)}:re;return this._pairs.map((function(e){return t(e[0])+\"=\"+t(e[1])}),\"\").join(\"&\")};var ue,ce=function(){function e(){r(this,e),this.handlers=[]}return i(e,[{key:\"use\",value:function(e,t,n){return this.handlers.push({fulfilled:e,rejected:t,synchronous:!!n&&n.synchronous,runWhen:n?n.runWhen:null}),this.handlers.length-1}},{key:\"eject\",value:function(e){this.handlers[e]&&(this.handlers[e]=null)}},{key:\"clear\",value:function(){this.handlers&&(this.handlers=[])}},{key:\"forEach\",value:function(e){G.forEach(this.handlers,(function(t){null!==t&&e(t)}))}}]),e}(),fe={silentJSONParsing:!0,forcedJSONParsing:!0,clarifyTimeoutError:!1},le={isBrowser:!0,classes:{URLSearchParams:\"undefined\"!=typeof URLSearchParams?URLSearchParams:oe,FormData:\"undefined\"!=typeof FormData?FormData:null,Blob:\"undefined\"!=typeof Blob?Blob:null},protocols:[\"http\",\"https\",\"file\",\"blob\",\"url\",\"data\"]},de=\"undefined\"!=typeof window&&\"undefined\"!=typeof document,pe=(ue=\"undefined\"!=typeof navigator&&navigator.product,de&&[\"ReactNative\",\"NativeScript\",\"NS\"].indexOf(ue)<0),he=\"undefined\"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope&&\"function\"==typeof self.importScripts,me=t(t({},Object.freeze({__proto__:null,hasBrowserEnv:de,hasStandardBrowserWebWorkerEnv:he,hasStandardBrowserEnv:pe})),le);function ye(e){function t(e,n,r,o){var i=e[o++],a=Number.isFinite(+i),s=o>=e.length;return i=!i&&G.isArray(r)?r.length:i,s?(G.hasOwnProp(r,i)?r[i]=[r[i],n]:r[i]=n,!a):(r[i]&&G.isObject(r[i])||(r[i]=[]),t(e,n,r[i],o)&&G.isArray(r[i])&&(r[i]=function(e){var t,n,r={},o=Object.keys(e),i=o.length;for(t=0;t-1,i=G.isObject(e);if(i&&G.isHTMLForm(e)&&(e=new FormData(e)),G.isFormData(e))return o&&o?JSON.stringify(ye(e)):e;if(G.isArrayBuffer(e)||G.isBuffer(e)||G.isStream(e)||G.isFile(e)||G.isBlob(e))return e;if(G.isArrayBufferView(e))return e.buffer;if(G.isURLSearchParams(e))return t.setContentType(\"application/x-www-form-urlencoded;charset=utf-8\",!1),e.toString();if(i){if(r.indexOf(\"application/x-www-form-urlencoded\")>-1)return function(e,t){return ne(e,new me.classes.URLSearchParams,Object.assign({visitor:function(e,t,n,r){return me.isNode&&G.isBuffer(e)?(this.append(t,e.toString(\"base64\")),!1):r.defaultVisitor.apply(this,arguments)}},t))}(e,this.formSerializer).toString();if((n=G.isFileList(e))||r.indexOf(\"multipart/form-data\")>-1){var a=this.env&&this.env.FormData;return ne(n?{\"files[]\":e}:e,a&&new a,this.formSerializer)}}return i||o?(t.setContentType(\"application/json\",!1),function(e,t,n){if(G.isString(e))try{return(t||JSON.parse)(e),G.trim(e)}catch(e){if(\"SyntaxError\"!==e.name)throw e}return(n||JSON.stringify)(e)}(e)):e}],transformResponse:[function(e){var t=this.transitional||ve.transitional,n=t&&t.forcedJSONParsing,r=\"json\"===this.responseType;if(e&&G.isString(e)&&(n&&!this.responseType||r)){var o=!(t&&t.silentJSONParsing)&&r;try{return JSON.parse(e)}catch(e){if(o){if(\"SyntaxError\"===e.name)throw X.from(e,X.ERR_BAD_RESPONSE,this,null,this.response);throw e}}}return e}],timeout:0,xsrfCookieName:\"XSRF-TOKEN\",xsrfHeaderName:\"X-XSRF-TOKEN\",maxContentLength:-1,maxBodyLength:-1,env:{FormData:me.classes.FormData,Blob:me.classes.Blob},validateStatus:function(e){return e>=200&&e<300},headers:{common:{Accept:\"application/json, text/plain, */*\",\"Content-Type\":void 0}}};G.forEach([\"delete\",\"get\",\"head\",\"post\",\"put\",\"patch\"],(function(e){ve.headers[e]={}}));var be=ve,ge=G.toObjectSet([\"age\",\"authorization\",\"content-length\",\"content-type\",\"etag\",\"expires\",\"from\",\"host\",\"if-modified-since\",\"if-unmodified-since\",\"last-modified\",\"location\",\"max-forwards\",\"proxy-authorization\",\"referer\",\"retry-after\",\"user-agent\"]),we=Symbol(\"internals\");function Oe(e){return e&&String(e).trim().toLowerCase()}function Ee(e){return!1===e||null==e?e:G.isArray(e)?e.map(Ee):String(e)}function Se(e,t,n,r,o){return G.isFunction(r)?r.call(this,t,n):(o&&(t=n),G.isString(t)?G.isString(r)?-1!==t.indexOf(r):G.isRegExp(r)?r.test(t):void 0:void 0)}var Re=function(e,t){function n(e){r(this,n),e&&this.set(e)}return i(n,[{key:\"set\",value:function(e,t,n){var r=this;function o(e,t,n){var o=Oe(t);if(!o)throw new Error(\"header name must be a non-empty string\");var i=G.findKey(r,o);(!i||void 0===r[i]||!0===n||void 0===n&&!1!==r[i])&&(r[i||t]=Ee(e))}var i,a,s,u,c,f=function(e,t){return G.forEach(e,(function(e,n){return o(e,n,t)}))};return G.isPlainObject(e)||e instanceof this.constructor?f(e,t):G.isString(e)&&(e=e.trim())&&!/^[-_a-zA-Z0-9^`|~,!#$%&'*+.]+$/.test(e.trim())?f((c={},(i=e)&&i.split(\"\\n\").forEach((function(e){u=e.indexOf(\":\"),a=e.substring(0,u).trim().toLowerCase(),s=e.substring(u+1).trim(),!a||c[a]&&ge[a]||(\"set-cookie\"===a?c[a]?c[a].push(s):c[a]=[s]:c[a]=c[a]?c[a]+\", \"+s:s)})),c),t):null!=e&&o(t,e,n),this}},{key:\"get\",value:function(e,t){if(e=Oe(e)){var n=G.findKey(this,e);if(n){var r=this[n];if(!t)return r;if(!0===t)return function(e){for(var t,n=Object.create(null),r=/([^\\s,;=]+)\\s*(?:=\\s*([^,;]+))?/g;t=r.exec(e);)n[t[1]]=t[2];return n}(r);if(G.isFunction(t))return t.call(this,r,n);if(G.isRegExp(t))return t.exec(r);throw new TypeError(\"parser must be boolean|regexp|function\")}}}},{key:\"has\",value:function(e,t){if(e=Oe(e)){var n=G.findKey(this,e);return!(!n||void 0===this[n]||t&&!Se(0,this[n],n,t))}return!1}},{key:\"delete\",value:function(e,t){var n=this,r=!1;function o(e){if(e=Oe(e)){var o=G.findKey(n,e);!o||t&&!Se(0,n[o],o,t)||(delete n[o],r=!0)}}return G.isArray(e)?e.forEach(o):o(e),r}},{key:\"clear\",value:function(e){for(var t=Object.keys(this),n=t.length,r=!1;n--;){var o=t[n];e&&!Se(0,this[o],o,e,!0)||(delete this[o],r=!0)}return r}},{key:\"normalize\",value:function(e){var t=this,n={};return G.forEach(this,(function(r,o){var i=G.findKey(n,o);if(i)return t[i]=Ee(r),void delete t[o];var a=e?function(e){return e.trim().toLowerCase().replace(/([a-z\\d])(\\w*)/g,(function(e,t,n){return t.toUpperCase()+n}))}(o):String(o).trim();a!==o&&delete t[o],t[a]=Ee(r),n[a]=!0})),this}},{key:\"concat\",value:function(){for(var e,t=arguments.length,n=new Array(t),r=0;r1?n-1:0),o=1;o1?\"since :\\n\"+u.map(Fe).join(\"\\n\"):\" \"+Fe(u[0]):\"as no adapter specified\"),\"ERR_NOT_SUPPORT\")}return n};function Be(e){if(e.cancelToken&&e.cancelToken.throwIfRequested(),e.signal&&e.signal.aborted)throw new Pe(null,e)}function Le(e){return Be(e),e.headers=Ae.from(e.headers),e.data=je.call(e,e.transformRequest),-1!==[\"post\",\"put\",\"patch\"].indexOf(e.method)&&e.headers.setContentType(\"application/x-www-form-urlencoded\",!1),De(e.adapter||be.adapter)(e).then((function(t){return Be(e),t.data=je.call(e,e.transformResponse,t),t.headers=Ae.from(t.headers),t}),(function(t){return Te(t)||(Be(e),t&&t.response&&(t.response.data=je.call(e,e.transformResponse,t.response),t.response.headers=Ae.from(t.response.headers))),Promise.reject(t)}))}var Ie=function(e){return e instanceof Ae?e.toJSON():e};function qe(e,t){t=t||{};var n={};function r(e,t,n){return G.isPlainObject(e)&&G.isPlainObject(t)?G.merge.call({caseless:n},e,t):G.isPlainObject(t)?G.merge({},t):G.isArray(t)?t.slice():t}function o(e,t,n){return G.isUndefined(t)?G.isUndefined(e)?void 0:r(void 0,e,n):r(e,t,n)}function i(e,t){if(!G.isUndefined(t))return r(void 0,t)}function a(e,t){return G.isUndefined(t)?G.isUndefined(e)?void 0:r(void 0,e):r(void 0,t)}function s(n,o,i){return i in t?r(n,o):i in e?r(void 0,n):void 0}var u={url:i,method:i,data:i,baseURL:a,transformRequest:a,transformResponse:a,paramsSerializer:a,timeout:a,timeoutMessage:a,withCredentials:a,withXSRFToken:a,adapter:a,responseType:a,xsrfCookieName:a,xsrfHeaderName:a,onUploadProgress:a,onDownloadProgress:a,decompress:a,maxContentLength:a,maxBodyLength:a,beforeRedirect:a,transport:a,httpAgent:a,httpsAgent:a,cancelToken:a,socketPath:a,responseEncoding:a,validateStatus:s,headers:function(e,t){return o(Ie(e),Ie(t),!0)}};return G.forEach(Object.keys(Object.assign({},e,t)),(function(r){var i=u[r]||o,a=i(e[r],t[r],r);G.isUndefined(a)&&i!==s||(n[r]=a)})),n}var ze=\"1.6.2\",Me={};[\"object\",\"boolean\",\"number\",\"function\",\"string\",\"symbol\"].forEach((function(e,t){Me[e]=function(r){return n(r)===e||\"a\"+(t<1?\"n \":\" \")+e}}));var He={};Me.transitional=function(e,t,n){function r(e,t){return\"[Axios v1.6.2] Transitional option '\"+e+\"'\"+t+(n?\". \"+n:\"\")}return function(n,o,i){if(!1===e)throw new X(r(o,\" has been removed\"+(t?\" in \"+t:\"\")),X.ERR_DEPRECATED);return t&&!He[o]&&(He[o]=!0,console.warn(r(o,\" has been deprecated since v\"+t+\" and will be removed in the near future\"))),!e||e(n,o,i)}};var Je={assertOptions:function(e,t,r){if(\"object\"!==n(e))throw new X(\"options must be an object\",X.ERR_BAD_OPTION_VALUE);for(var o=Object.keys(e),i=o.length;i-- >0;){var a=o[i],s=t[a];if(s){var u=e[a],c=void 0===u||s(u,a,e);if(!0!==c)throw new X(\"option \"+a+\" must be \"+c,X.ERR_BAD_OPTION_VALUE)}else if(!0!==r)throw new X(\"Unknown option \"+a,X.ERR_BAD_OPTION)}},validators:Me},We=Je.validators,Ke=function(){function e(t){r(this,e),this.defaults=t,this.interceptors={request:new ce,response:new ce}}return i(e,[{key:\"request\",value:function(e,t){\"string\"==typeof e?(t=t||{}).url=e:t=e||{};var n=t=qe(this.defaults,t),r=n.transitional,o=n.paramsSerializer,i=n.headers;void 0!==r&&Je.assertOptions(r,{silentJSONParsing:We.transitional(We.boolean),forcedJSONParsing:We.transitional(We.boolean),clarifyTimeoutError:We.transitional(We.boolean)},!1),null!=o&&(G.isFunction(o)?t.paramsSerializer={serialize:o}:Je.assertOptions(o,{encode:We.function,serialize:We.function},!0)),t.method=(t.method||this.defaults.method||\"get\").toLowerCase();var a=i&&G.merge(i.common,i[t.method]);i&&G.forEach([\"delete\",\"get\",\"head\",\"post\",\"put\",\"patch\",\"common\"],(function(e){delete i[e]})),t.headers=Ae.concat(a,i);var s=[],u=!0;this.interceptors.request.forEach((function(e){\"function\"==typeof e.runWhen&&!1===e.runWhen(t)||(u=u&&e.synchronous,s.unshift(e.fulfilled,e.rejected))}));var c,f=[];this.interceptors.response.forEach((function(e){f.push(e.fulfilled,e.rejected)}));var l,d=0;if(!u){var p=[Le.bind(this),void 0];for(p.unshift.apply(p,s),p.push.apply(p,f),l=p.length,c=Promise.resolve(t);d0;)o._listeners[t](e);o._listeners=null}})),this.promise.then=function(e){var t,n=new Promise((function(e){o.subscribe(e),t=e})).then(e);return n.cancel=function(){o.unsubscribe(t)},n},t((function(e,t,r){o.reason||(o.reason=new Pe(e,t,r),n(o.reason))}))}return i(e,[{key:\"throwIfRequested\",value:function(){if(this.reason)throw this.reason}},{key:\"subscribe\",value:function(e){this.reason?e(this.reason):this._listeners?this._listeners.push(e):this._listeners=[e]}},{key:\"unsubscribe\",value:function(e){if(this._listeners){var t=this._listeners.indexOf(e);-1!==t&&this._listeners.splice(t,1)}}}],[{key:\"source\",value:function(){var t;return{token:new e((function(e){t=e})),cancel:t}}}]),e}();var Xe={Continue:100,SwitchingProtocols:101,Processing:102,EarlyHints:103,Ok:200,Created:201,Accepted:202,NonAuthoritativeInformation:203,NoContent:204,ResetContent:205,PartialContent:206,MultiStatus:207,AlreadyReported:208,ImUsed:226,MultipleChoices:300,MovedPermanently:301,Found:302,SeeOther:303,NotModified:304,UseProxy:305,Unused:306,TemporaryRedirect:307,PermanentRedirect:308,BadRequest:400,Unauthorized:401,PaymentRequired:402,Forbidden:403,NotFound:404,MethodNotAllowed:405,NotAcceptable:406,ProxyAuthenticationRequired:407,RequestTimeout:408,Conflict:409,Gone:410,LengthRequired:411,PreconditionFailed:412,PayloadTooLarge:413,UriTooLong:414,UnsupportedMediaType:415,RangeNotSatisfiable:416,ExpectationFailed:417,ImATeapot:418,MisdirectedRequest:421,UnprocessableEntity:422,Locked:423,FailedDependency:424,TooEarly:425,UpgradeRequired:426,PreconditionRequired:428,TooManyRequests:429,RequestHeaderFieldsTooLarge:431,UnavailableForLegalReasons:451,InternalServerError:500,NotImplemented:501,BadGateway:502,ServiceUnavailable:503,GatewayTimeout:504,HttpVersionNotSupported:505,VariantAlsoNegotiates:506,InsufficientStorage:507,LoopDetected:508,NotExtended:510,NetworkAuthenticationRequired:511};Object.entries(Xe).forEach((function(e){var t=s(e,2),n=t[0],r=t[1];Xe[r]=n}));var $e=Xe;var Qe=function e(t){var n=new Ve(t),r=h(Ve.prototype.request,n);return G.extend(r,Ve.prototype,n,{allOwnKeys:!0}),G.extend(r,n,null,{allOwnKeys:!0}),r.create=function(n){return e(qe(t,n))},r}(be);return Qe.Axios=Ve,Qe.CanceledError=Pe,Qe.CancelToken=Ge,Qe.isCancel=Te,Qe.VERSION=ze,Qe.toFormData=ne,Qe.AxiosError=X,Qe.Cancel=Qe.CanceledError,Qe.all=function(e){return Promise.all(e)},Qe.spread=function(e){return function(t){return e.apply(null,t)}},Qe.isAxiosError=function(e){return G.isObject(e)&&!0===e.isAxiosError},Qe.mergeConfig=qe,Qe.AxiosHeaders=Ae,Qe.formToJSON=function(e){return ye(G.isHTMLForm(e)?new FormData(e):e)},Qe.getAdapter=De,Qe.HttpStatusCode=$e,Qe.default=Qe,Qe}));" var geeTestHTTPClient = &http.Client{Timeout: 5 * time.Second}