(options RequestOptions)
| 3030 | } |
| 3031 | |
| 3032 | func requestPathNormalization(options RequestOptions) { |
| 3033 | parsedURL, err := url.Parse(options.uri) |
| 3034 | if err != nil { |
| 3035 | log.Println(err) |
| 3036 | return |
| 3037 | } |
| 3038 | |
| 3039 | pathValue := parsedURL.Path |
| 3040 | if pathValue == "" || pathValue == "/" { |
| 3041 | return |
| 3042 | } |
| 3043 | |
| 3044 | trailingSlash := strings.HasSuffix(pathValue, "/") |
| 3045 | trimmedPath := strings.Trim(pathValue, "/") |
| 3046 | segments := strings.Split(trimmedPath, "/") |
| 3047 | if len(segments) == 0 { |
| 3048 | return |
| 3049 | } |
| 3050 | |
| 3051 | lastSegment := segments[len(segments)-1] |
| 3052 | basePath := "/" |
| 3053 | if len(segments) > 1 { |
| 3054 | basePath = "/" + strings.Join(segments[:len(segments)-1], "/") + "/" |
| 3055 | } |
| 3056 | query := "" |
| 3057 | if parsedURL.RawQuery != "" { |
| 3058 | query = "?" + parsedURL.RawQuery |
| 3059 | } |
| 3060 | baseURL := parsedURL.Scheme + "://" + parsedURL.Host |
| 3061 | |
| 3062 | payloads := []string{ |
| 3063 | baseURL + basePath + "%2e/" + lastSegment + query, |
| 3064 | baseURL + basePath + ".%2e/" + lastSegment + query, |
| 3065 | baseURL + basePath + "%2e%2e/" + lastSegment + query, |
| 3066 | baseURL + basePath + "..%2f" + lastSegment + query, |
| 3067 | baseURL + basePath + "%2e%2e%2f" + lastSegment + query, |
| 3068 | baseURL + basePath + lastSegment + "/." + query, |
| 3069 | baseURL + basePath + lastSegment + "/%2e" + query, |
| 3070 | baseURL + basePath + ";" + lastSegment + query, |
| 3071 | } |
| 3072 | if trailingSlash { |
| 3073 | payloads = append(payloads, baseURL+basePath+lastSegment+"/..;/"+query) |
| 3074 | } |
| 3075 | payloads = removeDuplicates(payloads) |
| 3076 | |
| 3077 | w := goccm.New(maxGoroutines) |
| 3078 | p := newProgress("path-normalization", len(payloads)) |
| 3079 | |
| 3080 | for _, payload := range payloads { |
| 3081 | time.Sleep(time.Duration(delay) * time.Millisecond) |
| 3082 | w.Wait() |
| 3083 | go func(payload string) { |
| 3084 | defer w.Done() |
| 3085 | defer p.done() |
| 3086 | |
| 3087 | resp, err := requestWithRetry(options.method, payload, options.headers, options.proxy, options.rateLimit, options.timeout, options.redirect) |
| 3088 | if err != nil { |
| 3089 | if errors.Is(err, ErrRateLimited) { |
no test coverage detected