mirror of
https://github.com/chainreactors/spray.git
synced 2026-10-29 03:50:47 +00:00
123 lines
3.6 KiB
Go
123 lines
3.6 KiB
Go
package pkg
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestParseRawResponse(t *testing.T) {
|
|
t.Run("valid complete response", func(t *testing.T) {
|
|
raw := "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nContent-Length: 5\r\n\r\nhello"
|
|
resp, err := ParseRawResponse([]byte(raw))
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if resp.StatusCode != 200 {
|
|
t.Fatalf("expected status 200, got %d", resp.StatusCode)
|
|
}
|
|
if ct := resp.Header.Get("Content-Type"); ct != "text/html" {
|
|
t.Fatalf("expected Content-Type text/html, got %s", ct)
|
|
}
|
|
})
|
|
|
|
t.Run("nil input", func(t *testing.T) {
|
|
_, err := ParseRawResponse(nil)
|
|
if err == nil {
|
|
t.Fatal("expected error for nil input")
|
|
}
|
|
})
|
|
|
|
t.Run("empty input", func(t *testing.T) {
|
|
_, err := ParseRawResponse([]byte{})
|
|
if err == nil {
|
|
t.Fatal("expected error for empty input")
|
|
}
|
|
})
|
|
|
|
t.Run("status line only no headers", func(t *testing.T) {
|
|
raw := "HTTP/1.1 200 OK\r\n\r\n"
|
|
resp, err := ParseRawResponse([]byte(raw))
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if resp.StatusCode != 200 {
|
|
t.Fatalf("expected status 200, got %d", resp.StatusCode)
|
|
}
|
|
})
|
|
|
|
t.Run("truncated status line", func(t *testing.T) {
|
|
raw := "HTTP/1."
|
|
_, err := ParseRawResponse([]byte(raw))
|
|
if err == nil {
|
|
t.Fatal("expected error for truncated status line")
|
|
}
|
|
})
|
|
|
|
t.Run("redirect response no body", func(t *testing.T) {
|
|
raw := "HTTP/1.1 302 Found\r\nLocation: https://example.com/new\r\n\r\n"
|
|
resp, err := ParseRawResponse([]byte(raw))
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if resp.StatusCode != 302 {
|
|
t.Fatalf("expected status 302, got %d", resp.StatusCode)
|
|
}
|
|
if loc := resp.Header.Get("Location"); loc != "https://example.com/new" {
|
|
t.Fatalf("expected Location https://example.com/new, got %s", loc)
|
|
}
|
|
})
|
|
|
|
t.Run("chunked transfer encoding header", func(t *testing.T) {
|
|
raw := "HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"
|
|
resp, err := ParseRawResponse([]byte(raw))
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if te := resp.Header.Get("Transfer-Encoding"); te == "" {
|
|
// Transfer-Encoding may be consumed by http.ReadResponse, just verify no panic
|
|
}
|
|
_ = resp
|
|
})
|
|
|
|
t.Run("large header value", func(t *testing.T) {
|
|
largeValue := strings.Repeat("A", 8192)
|
|
raw := "HTTP/1.1 200 OK\r\nX-Large: " + largeValue + "\r\n\r\n"
|
|
resp, err := ParseRawResponse([]byte(raw))
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if got := resp.Header.Get("X-Large"); got != largeValue {
|
|
t.Fatalf("large header value mismatch, got length %d", len(got))
|
|
}
|
|
})
|
|
|
|
t.Run("invalid status code", func(t *testing.T) {
|
|
raw := "HTTP/1.1 xyz OK\r\n\r\n"
|
|
_, err := ParseRawResponse([]byte(raw))
|
|
if err == nil {
|
|
t.Fatal("expected error for invalid status code")
|
|
}
|
|
})
|
|
|
|
t.Run("incomplete header no terminator", func(t *testing.T) {
|
|
raw := "HTTP/1.1 200 OK\r\nContent-Type: text/html"
|
|
_, err := ParseRawResponse([]byte(raw))
|
|
// Should return error or at least not panic
|
|
// http.ReadResponse may or may not error on missing \r\n\r\n,
|
|
// the key requirement is no panic
|
|
_ = err
|
|
})
|
|
|
|
t.Run("binary body", func(t *testing.T) {
|
|
body := []byte{0x00, 0x01, 0x02, 0xff, 0xfe, 0xfd}
|
|
raw := append([]byte("HTTP/1.1 200 OK\r\nContent-Length: 6\r\n\r\n"), body...)
|
|
resp, err := ParseRawResponse(raw)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if resp.StatusCode != 200 {
|
|
t.Fatalf("expected status 200, got %d", resp.StatusCode)
|
|
}
|
|
})
|
|
}
|