(resp *http.Response)
| 276 | } |
| 277 | |
| 278 | func (p *Parser) UseResponse(resp *http.Response) { |
| 279 | sampler := newSampler(resp.Body) |
| 280 | resp.Body = sampler |
| 281 | |
| 282 | p.wg.Add(1) |
| 283 | go func() { |
| 284 | defer p.wg.Done() |
| 285 | start := time.Now() |
| 286 | |
| 287 | h, err := har.NewResponse(resp, false) |
| 288 | if err != nil { |
| 289 | p.errs <- fmt.Errorf("parse HAR response: %w", err) |
| 290 | return |
| 291 | } |
| 292 | |
| 293 | // TODO: does the "wait" timer start before or after the request is fully |
| 294 | // sent (including body)? |
| 295 | p.timings.Wait = time.Since(start).Milliseconds() |
| 296 | |
| 297 | for i := range h.Headers { |
| 298 | switch strings.ToLower(h.Headers[i].Name) { |
| 299 | case "set-cookie": |
| 300 | h.Headers[i].Value = p.global.Config.SantizeCredential(h.Headers[i].Value) |
| 301 | } |
| 302 | } |
| 303 | |
| 304 | for i := range h.Cookies { |
| 305 | h.Cookies[i].Value = p.global.Config.SantizeCredential(h.Cookies[i].Value) |
| 306 | } |
| 307 | |
| 308 | start = time.Now() |
| 309 | if err := <-sampler.errs; err != nil { |
| 310 | p.errs <- fmt.Errorf("parse HAR response: %w", err) |
| 311 | return |
| 312 | } |
| 313 | p.timings.Receive = time.Since(start).Milliseconds() |
| 314 | |
| 315 | text := sampler.data[:sampler.used] |
| 316 | if !sampler.over { |
| 317 | switch resp.Header.Get("content-encoding") { |
| 318 | case "gzip": |
| 319 | gr, err := gzip.NewReader(bytes.NewBuffer(text)) |
| 320 | if err != nil { |
| 321 | p.errs <- fmt.Errorf("create gzip reader: %w", err) |
| 322 | return |
| 323 | } |
| 324 | if raw, err := io.ReadAll(gr); err != nil { |
| 325 | p.errs <- fmt.Errorf("read gzip: %w", err) |
| 326 | return |
| 327 | } else { |
| 328 | text = raw |
| 329 | } |
| 330 | case "br": |
| 331 | if raw, err := io.ReadAll(brotli.NewReader(bytes.NewBuffer(text))); err != nil { |
| 332 | p.errs <- fmt.Errorf("decode brotli: %w", err) |
| 333 | return |
| 334 | } else { |
| 335 | text = raw |
no test coverage detected