MCPcopy
hub / github.com/dreadl0ck/netcap / extractHeaderOrderFromReader

Function extractHeaderOrderFromReader

decoder/stream/http/http_reader.go:530–602  ·  view source on GitHub ↗

extractHeaderOrderFromReader extracts HTTP header order from a bufio.Reader by peeking at the raw bytes before http.ReadRequest consumes them. This is needed for JA4H fingerprinting which requires header order preservation.

(b *bufio.Reader)

Source from the content-addressed store, hash-verified

528// by peeking at the raw bytes before http.ReadRequest consumes them.
529// This is needed for JA4H fingerprinting which requires header order preservation.
530func extractHeaderOrderFromReader(b *bufio.Reader) (headerOrder []string, cookieFields []string, acceptLang string) {
531 // Try to peek enough bytes to see the headers
532 // HTTP headers typically end with \r\n\r\n
533 // We'll peek progressively larger amounts until we find the header end
534
535 peekSizes := []int{1024, 4096, 8192, 16384, 32768}
536 var peeked []byte
537
538 for _, size := range peekSizes {
539 data, err := b.Peek(size)
540 if err != nil && len(data) == 0 {
541 // Can't peek, return empty
542 return nil, nil, ""
543 }
544 peeked = data
545
546 // Check if we have the complete headers (ends with \r\n\r\n or \n\n)
547 if bytes.Contains(peeked, []byte("\r\n\r\n")) || bytes.Contains(peeked, []byte("\n\n")) {
548 break
549 }
550
551 // If we got less than requested, we've read all available data
552 if len(data) < size {
553 break
554 }
555 }
556
557 if len(peeked) == 0 {
558 return nil, nil, ""
559 }
560
561 // Find the end of headers
562 headerEnd := bytes.Index(peeked, []byte("\r\n\r\n"))
563 if headerEnd == -1 {
564 headerEnd = bytes.Index(peeked, []byte("\n\n"))
565 if headerEnd == -1 {
566 headerEnd = len(peeked)
567 }
568 }
569
570 headerBytes := peeked[:headerEnd]
571 lines := bytes.Split(headerBytes, []byte("\n"))
572
573 // Skip the request line (first line)
574 for i := 1; i < len(lines); i++ {
575 line := bytes.TrimRight(lines[i], "\r")
576 if len(line) == 0 {
577 continue
578 }
579
580 colonIdx := bytes.Index(line, []byte(":"))
581 if colonIdx <= 0 {
582 continue
583 }
584
585 headerName := string(bytes.TrimSpace(line[:colonIdx]))
586 headerValue := string(bytes.TrimSpace(line[colonIdx+1:]))
587

Callers 1

readRequestMethod · 0.85

Calls 1

Tested by

no test coverage detected