mirror of
https://github.com/anotherhadi/spilltea.git
synced 2026-05-20 17:52:33 +02:00
1a1c0cff30
[37m- Add internal/util/rawhttp.go with ParseRawRequest and SortedHeaderLines[0m [37m- Refactor intercept/format.go and ui/intercept/helpers.go to use them[0m [37m- Eliminates duplicated bufio.Reader + textproto parsing spread across 3+ files[0m [37mCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>[0m
87 lines
1.8 KiB
Go
87 lines
1.8 KiB
Go
package util
|
|
|
|
import (
|
|
"fmt"
|
|
"net/http"
|
|
"sort"
|
|
"strings"
|
|
)
|
|
|
|
// RawRequest holds a parsed raw HTTP request string.
|
|
type RawRequest struct {
|
|
Method string
|
|
Path string
|
|
Proto string
|
|
Host string
|
|
Headers []RawHeader
|
|
Body string
|
|
}
|
|
|
|
// RawHeader is a single header key/value pair preserving insertion order.
|
|
type RawHeader struct {
|
|
Key string
|
|
Value string
|
|
}
|
|
|
|
// ParseRawRequest parses a raw HTTP request string (as produced by
|
|
// FormatRawRequest). The Host header, if present, is extracted into Host
|
|
// but also kept in Headers.
|
|
func ParseRawRequest(raw string) RawRequest {
|
|
lines := strings.Split(strings.ReplaceAll(raw, "\r\n", "\n"), "\n")
|
|
var r RawRequest
|
|
if len(lines) == 0 {
|
|
return r
|
|
}
|
|
|
|
parts := strings.SplitN(lines[0], " ", 3)
|
|
if len(parts) >= 1 {
|
|
r.Method = strings.TrimSpace(parts[0])
|
|
}
|
|
if len(parts) >= 2 {
|
|
r.Path = strings.TrimSpace(parts[1])
|
|
}
|
|
if len(parts) >= 3 {
|
|
r.Proto = strings.TrimSpace(parts[2])
|
|
}
|
|
|
|
i := 1
|
|
for i < len(lines) {
|
|
line := strings.TrimRight(lines[i], "\r")
|
|
if line == "" {
|
|
i++
|
|
break
|
|
}
|
|
if kv := strings.SplitN(line, ": ", 2); len(kv) == 2 {
|
|
k := strings.TrimSpace(kv[0])
|
|
v := strings.TrimSpace(kv[1])
|
|
r.Headers = append(r.Headers, RawHeader{k, v})
|
|
if strings.EqualFold(k, "host") {
|
|
r.Host = v
|
|
}
|
|
}
|
|
i++
|
|
}
|
|
|
|
if i < len(lines) {
|
|
r.Body = strings.TrimRight(strings.Join(lines[i:], "\n"), "\n")
|
|
}
|
|
return r
|
|
}
|
|
|
|
// SortedHeaderLines returns header lines sorted by key name, formatted as
|
|
// "Key: Value\n" strings. Useful for deterministic serialisation.
|
|
func SortedHeaderLines(h http.Header) []string {
|
|
keys := make([]string, 0, len(h))
|
|
for k := range h {
|
|
keys = append(keys, k)
|
|
}
|
|
sort.Strings(keys)
|
|
var out []string
|
|
for _, k := range keys {
|
|
for _, v := range h[k] {
|
|
out = append(out, fmt.Sprintf("%s: %s\n", k, v))
|
|
}
|
|
}
|
|
return out
|
|
}
|