skipped 4 lines 5 5 "crypto/tls" 6 6 "errors" 7 7 "fmt" 8 + "github.com/zan8in/afrog/pkg/utils" 8 9 "io/ioutil" 9 10 "net/http" 10 11 "net/url" skipped 18 lines 29 30 type FastClient struct { 30 31 MaxRedirect int32 31 32 DialTimeout int32 33 + UserAgent string 32 34 } 33 35 34 36 func Init(options *config.Options) { skipped 24 lines 59 61 60 62 func (fc *FastClient) HTTPRequest(httpRequest *http.Request, rule poc.Rule, variableMap map[string]interface{}) error { 61 63 var err error 64 + 65 + protoRequest, err := ParseRequest(httpRequest) 66 + if err != nil { 67 + return err 68 + } 69 + 70 + variableMap["request"] = nil 71 + variableMap["response"] = nil 72 + 73 + newRuleHeader := make(map[string]string) 74 + for k, v := range rule.Request.Headers { 75 + newRuleHeader[k] = fc.AssignVariableMap(v, variableMap) 76 + } 77 + rule.Request.Headers = newRuleHeader 78 + rule.Request.Path = fc.AssignVariableMap(strings.TrimSpace(rule.Request.Path), variableMap) 79 + //rule.Request.Body = fc.AssignVariableMap(strings.TrimSpace(rule.Request.Body), variableMap) 80 + if strings.HasPrefix(strings.ToLower(rule.Request.Headers["Content-Type"]), "multipart/form-Data") && strings.Contains(rule.Request.Body, "\n\n") { 81 + multipartBody, err := DealMultipart(rule.Request.Headers["Content-Type"], rule.Request.Body) 82 + if err != nil { 83 + return err 84 + } 85 + rule.Request.Body = fc.AssignVariableMap(strings.TrimSpace(multipartBody), variableMap) 86 + } else { 87 + rule.Request.Body = fc.AssignVariableMap(strings.TrimSpace(rule.Request.Body), variableMap) 88 + } 89 + 90 + if strings.HasPrefix(rule.Request.Path, "/") { 91 + protoRequest.Url.Path = strings.TrimRight(httpRequest.URL.Path, "/") + rule.Request.Path 92 + } else if strings.HasPrefix(rule.Request.Path, "^") { 93 + protoRequest.Url.Path = "/" + rule.Request.Path[1:] 94 + } 95 + 96 + protoRequest.Url.Path = strings.ReplaceAll(protoRequest.Url.Path, " ", "%20") 97 + protoRequest.Url.Path = strings.ReplaceAll(protoRequest.Url.Path, "+", "%20") 98 + 99 + if rule.Request.Method == "POST" && len(rule.Request.Headers["Content-Type"]) == 0 { 100 + if rule.Request.Headers == nil { 101 + rule.Request.Headers = make(map[string]string) 102 + } 103 + rule.Request.Headers["Content-Type"] = "application/x-www-form-urlencoded" 104 + } 105 + 106 + finalRequest, err := http.NewRequest(rule.Request.Method, fmt.Sprintf("%s://%s%s", protoRequest.Url.Scheme, protoRequest.Url.Host, protoRequest.Url.Path), strings.NewReader(rule.Request.Body)) 107 + if err != nil { 108 + return err 109 + } 110 + 111 + fastReq := fasthttp.AcquireRequest() 112 + defer fasthttp.ReleaseRequest(fastReq) 113 + 114 + var rawHeader strings.Builder 115 + newheader := make(map[string]string) 116 + for k, v := range rule.Request.Headers { 117 + fastReq.Header.Set(k, v) 118 + 119 + newheader[k] = v 120 + 121 + rawHeader.WriteString(k) 122 + rawHeader.WriteString(": ") 123 + rawHeader.WriteString(v) 124 + rawHeader.WriteString("\n") 125 + } 126 + 127 + if len(fc.UserAgent) > 0 { 128 + fastReq.Header.Set("User-Agent", fc.UserAgent) 129 + } else { 130 + fastReq.Header.Set("User-Agent", utils.RandomUA()) 131 + } 132 + 133 + fastReq.Header.SetMethod(rule.Request.Method) 134 + 135 + if len(rule.Request.Headers["Host"]) == 0 { 136 + fastReq.Header.SetHost(finalRequest.Host) 137 + } 138 + if len(rule.Request.Headers["Content-Length"]) == 0 { 139 + fastReq.Header.SetContentLength(int(finalRequest.ContentLength)) 140 + } 141 + fastReq.SetBody([]byte(rule.Request.Body)) 142 + fastReq.URI().Update(finalRequest.URL.String()) 143 + fastReq.SetRequestURI(finalRequest.URL.String()) 144 + 145 + fastResp := fasthttp.AcquireResponse() 146 + defer fasthttp.ReleaseResponse(fastResp) 147 + 148 + if rule.Request.FollowRedirects { 149 + maxrd := 5 // follow redirects default 5 150 + if fc.MaxRedirect > 0 { 151 + maxrd = int(fc.MaxRedirect) 152 + } 153 + err = F.DoRedirects(fastReq, fastResp, maxrd) 154 + } else { 155 + dialtimeout := 6 156 + if fc.DialTimeout > 0 { 157 + dialtimeout = int(fc.DialTimeout) 158 + } 159 + err = F.DoTimeout(fastReq, fastResp, time.Second*time.Duration(dialtimeout)) 160 + } 161 + if err != nil { 162 + errName, known := httpConnError(err) 163 + if known { 164 + log.Log().Error(fmt.Sprintf("WARN conn error: %s\n", errName)) 165 + } else { 166 + log.Log().Error(fmt.Sprintf("ERR conn failure: %s %s\n", errName, err)) 167 + } 168 + } 169 + 170 + // set fastResp body 171 + var respBody []byte 172 + contentEncoding := strings.ToLower(string(fastResp.Header.Peek("Content-Encoding"))) 173 + switch contentEncoding { 174 + case "", "none", "identity": 175 + respBody = fastResp.Body() 176 + case "gzip": 177 + respBody, err = fastResp.BodyGunzip() 178 + case "deflate": 179 + respBody, err = fastResp.BodyInflate() 180 + default: 181 + respBody = []byte{} 182 + } 183 + if err != nil { 184 + return err 185 + } 186 + fastResp.SetBody(respBody) 187 + 188 + // fc.VariableMap["response"] variable assignment 189 + tempResultResponse := &proto.Response{} 190 + tempResultResponse.Status = int32(fastResp.StatusCode()) 191 + u, err := url.Parse(fastReq.URI().String()) 192 + if err != nil { 193 + return err 194 + } 195 + urlType := &proto.UrlType{ 196 + Scheme: u.Scheme, 197 + Domain: u.Hostname(), 198 + Host: u.Host, 199 + Port: u.Port(), 200 + Path: u.Path, 201 + Query: u.RawQuery, 202 + Fragment: u.Fragment, 203 + } 204 + tempResultResponse.Url = urlType 205 + newheader2 := make(map[string]string) 206 + respHeaderSlice := strings.Split(fastResp.Header.String(), "\r\n") 207 + for _, h := range respHeaderSlice { 208 + hslice := strings.SplitN(h, ":", 2) 209 + if len(hslice) != 2 { 210 + continue 211 + } 212 + k := strings.ToLower(hslice[0]) 213 + v := strings.TrimLeft(hslice[1], " ") 214 + if newheader2[k] != "" { 215 + newheader2[k] += v 216 + } else { 217 + newheader2[k] = v 218 + } 219 + } 220 + tempResultResponse.Headers = newheader2 221 + tempResultResponse.ContentType = string(fastResp.Header.ContentType()) 222 + tempResultResponse.Body = fastResp.Body() 223 + tempResultResponse.Raw = []byte(fastResp.String()) 224 + tempResultResponse.RawHeader = fastResp.Header.Header() 225 + variableMap["response"] = tempResultResponse 226 + 227 + protoRequest.Method = rule.Request.Method 228 + protoRequest.Url = urlType 229 + protoRequest.RawHeader = []byte(strings.Trim(rawHeader.String(), "\n")) 230 + protoRequest.Raw = []byte(string(fastReq.Header.String()) + "\n" + string(fastReq.Body())) 231 + protoRequest.Headers = newheader 232 + protoRequest.ContentType = newheader["content-type"] 233 + protoRequest.Body = []byte(rule.Request.Body) 234 + variableMap["request"] = protoRequest 235 + 236 + return err 237 + } 238 + 239 + func (fc *FastClient) HTTPRequest2(httpRequest *http.Request, rule poc.Rule, variableMap map[string]interface{}) error { 240 + var err error 241 + 242 + variableMap["request"] = nil 243 + variableMap["response"] = nil 62 244 63 245 fastReq := fasthttp.AcquireRequest() 64 246 defer fasthttp.ReleaseRequest(fastReq) skipped 301 lines 366 548 } 367 549 368 550 func CopyRequest(req *http.Request, dstRequest *fasthttp.Request, data []byte) { 369 - dstRequest.SetRequestURI(req.URL.String()) 551 + / / dstRequest.SetRequestURI(req.URL.String()) 552 + dstRequest.URI().Update(req.URL.String()) 370 553 dstRequest.Header.SetMethod(req.Method) 371 554 for name, values := range req.Header { 372 555 // Loop over all values for the name. skipped 5 lines 378 561 } 379 562 } 380 563 } 564 + dstRequest.SetBody(data) 381 565 dstRequest.SetBodyRaw(data) 382 566 } 383 567 skipped 72 lines