extractIPsFromHeader will return a slice of IPs it found given a header name in the order they appear. When IP validation is enabled, any invalid IPs will be omitted.
(header string)
| 571 | // extractIPsFromHeader will return a slice of IPs it found given a header name in the order they appear. |
| 572 | // When IP validation is enabled, any invalid IPs will be omitted. |
| 573 | func (r *DefaultReq) extractIPsFromHeader(header string) []string { |
| 574 | // TODO: Reuse the c.extractIPFromHeader func somehow in here |
| 575 | |
| 576 | headerValue := r.Get(header) |
| 577 | |
| 578 | // We can't know how many IPs we will return, but we will try to guess with this constant division. |
| 579 | // Counting ',' makes function slower for about 50ns in general case. |
| 580 | const maxEstimatedCount = 8 |
| 581 | estimatedCount := min(len(headerValue)/maxEstimatedCount, |
| 582 | // Avoid big allocation on big header |
| 583 | maxEstimatedCount) |
| 584 | |
| 585 | ipsFound := make([]string, 0, estimatedCount) |
| 586 | |
| 587 | i := 0 |
| 588 | j := -1 |
| 589 | |
| 590 | for { |
| 591 | var v4, v6 bool |
| 592 | |
| 593 | // Manually splitting string without allocating slice, working with parts directly |
| 594 | i, j = j+1, j+2 |
| 595 | |
| 596 | if j > len(headerValue) { |
| 597 | break |
| 598 | } |
| 599 | |
| 600 | for j < len(headerValue) && headerValue[j] != ',' { |
| 601 | switch headerValue[j] { |
| 602 | case ':': |
| 603 | v6 = true |
| 604 | case '.': |
| 605 | v4 = true |
| 606 | default: |
| 607 | // do nothing |
| 608 | } |
| 609 | j++ |
| 610 | } |
| 611 | |
| 612 | for i < j && (headerValue[i] == ' ' || headerValue[i] == ',') { |
| 613 | i++ |
| 614 | } |
| 615 | |
| 616 | s := utils.TrimRight(headerValue[i:j], ' ') |
| 617 | |
| 618 | if r.c.app.config.EnableIPValidation { |
| 619 | // Skip validation if IP is clearly not IPv4/IPv6; otherwise, validate without allocations |
| 620 | if (!v6 && !v4) || (v6 && !utils.IsIPv6(s)) || (v4 && !utils.IsIPv4(s)) { |
| 621 | continue |
| 622 | } |
| 623 | } |
| 624 | |
| 625 | ipsFound = append(ipsFound, s) |
| 626 | } |
| 627 | |
| 628 | return ipsFound |
| 629 | } |
| 630 |