package http1
import (
"bufio"
"strings"
"testing"
"github.com/google/go-cmp/cmp"
)
func TestReadRequest(t *testing.T) {
cases := []struct {
name string
raw string
want Request
}{
{
name: "simple_get",
raw: "GET /index.html HTTP/1.1\r\nHost: example.com\r\n\r\n",
want: Request{
Method: "GET",
Target: "/index.html",
Version: "HTTP/1.1",
Headers: [][2]string{{"Host", "example.com"}},
},
},
{
name: "post_with_body",
raw: "POST /api HTTP/1.1\r\nContent-Length: 5\r\n\r\nhello",
want: Request{
Method: "POST",
Target: "/api",
Version: "HTTP/1.1",
Headers: [][2]string{{"Content-Length", "5"}},
Body: []byte("hello"),
},
},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
r := bufio.NewReader(strings.NewReader(tc.raw))
got, err := ReadRequest(r)
if err != nil {
t.Fatalf("ReadRequest: %v", err)
}
if diff := cmp.Diff(&tc.want, got); diff != "" {
t.Errorf("mismatch (-want +got):\n%s", diff)
}
})
}
}
func TestParseRequestLineErrors(t *testing.T) {
cases := []struct {
name string
line string
}{
{"empty", ""},
{"only_method", "GET\r\n"},
{"bad_version", "GET / HTTP/9.0\r\n"},
{"bad_method", "G ET / HTTP/1.1\r\n"},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
if _, err := parseRequestLine(tc.line); err == nil {
t.Fatalf("expected error for %q", tc.line)
}
})
}
}
func TestIsToken(t *testing.T) {
for _, ok := range []string{"GET", "POST", "X-Custom"} {
if !isToken(ok) {
t.Errorf("isToken(%q) = false, want true", ok)
}
}
for _, bad := range []string{"", "has space", "with/slash", "semi;colon"} {
if isToken(bad) {
t.Errorf("isToken(%q) = true, want false", bad)
}
}
}