revert-54069ad305 #11

Closed
bagas wants to merge 217 commits from revert-54069ad305 into main
3 changed files with 24 additions and 198 deletions
Showing only changes of commit 4041681be6 - Show all commits
+1 -118
View File
@@ -1,15 +1,13 @@
package header
import (
"bufio"
"bytes"
"io"
"testing"
"github.com/stretchr/testify/assert"
)
func TestNewRequestFromBytes(t *testing.T) {
func TestNewRequest(t *testing.T) {
tests := []struct {
name string
data []byte
@@ -93,94 +91,6 @@ func TestNewRequestFromBytes(t *testing.T) {
}
}
func TestNewRequestFromReader(t *testing.T) {
tests := []struct {
name string
data []byte
expectErr bool
errContains string
expectEOF bool
expectMethod string
expectPath string
expectVersion string
expectHeaders map[string]string
}{
{
name: "success",
data: []byte("POST /api HTTP/1.1\r\nContent-Type: application/json\r\n\r\n"),
expectErr: false,
expectMethod: "POST",
expectPath: "/api",
expectVersion: "HTTP/1.1",
expectHeaders: map[string]string{
"Content-Type": "application/json",
},
},
{
name: "read error on start line",
data: []byte{},
expectErr: true,
expectEOF: true,
},
{
name: "invalid start line",
data: []byte("INVALID\n\n"),
expectErr: true,
errContains: "invalid start line",
},
{
name: "read error on headers",
data: []byte("GET / HTTP/1.1\nHost: example.com"),
expectErr: true,
expectEOF: true,
},
{
name: "multiple colons in header",
data: []byte("GET / HTTP/1.1\r\nX-Custom: value:with:colons\r\n\r\n"),
expectErr: false,
expectMethod: "GET",
expectPath: "/",
expectVersion: "HTTP/1.1",
expectHeaders: map[string]string{
"X-Custom": "value:with:colons",
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
br := bufio.NewReader(bytes.NewReader(tt.data))
req, err := NewRequest(br)
if tt.expectErr {
assert.Error(t, err)
if tt.expectEOF {
assert.Equal(t, io.EOF, err)
}
if tt.errContains != "" {
assert.Contains(t, err.Error(), tt.errContains)
}
assert.Nil(t, req)
} else {
assert.NoError(t, err)
assert.NotNil(t, req)
assert.Equal(t, tt.expectMethod, req.Method())
assert.Equal(t, tt.expectPath, req.Path())
assert.Equal(t, tt.expectVersion, req.Version())
for k, v := range tt.expectHeaders {
assert.Equal(t, v, req.Value(k))
}
}
})
}
}
func TestNewRequestUnsupportedType(t *testing.T) {
req, err := NewRequest(123)
assert.Error(t, err)
assert.Contains(t, err.Error(), "unsupported type: int")
assert.Nil(t, req)
}
func TestRequestHeaderMethods(t *testing.T) {
data := []byte("GET / HTTP/1.1\r\nHost: original\r\n\r\n")
req, _ := NewRequest(data)
@@ -315,30 +225,3 @@ func TestSetRemainingHeaders(t *testing.T) {
})
}
}
func TestParseHeadersFromReaderEdgeCases(t *testing.T) {
tests := []struct {
name string
data []byte
expectHeaders map[string]string
}{
{
name: "malformed header line",
data: []byte("GET / HTTP/1.1\r\nMalformedLine\r\nK1: V1\r\n\r\n"),
expectHeaders: map[string]string{
"K1": "V1",
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
br := bufio.NewReader(bytes.NewReader(tt.data))
req, err := parseHeadersFromReader(br)
assert.NoError(t, err)
for k, v := range tt.expectHeaders {
assert.Equal(t, v, req.Value(k))
}
})
}
}
-71
View File
@@ -1,7 +1,6 @@
package header
import (
"bufio"
"bytes"
"fmt"
)
@@ -36,31 +35,6 @@ func setRemainingHeaders(remaining []byte, header interface {
}
}
func parseHeadersFromBytes(headerData []byte) (RequestHeader, error) {
header := &requestHeader{
headers: make(map[string]string, 16),
}
lineEnd := bytes.Index(headerData, []byte("\r\n"))
if lineEnd == -1 {
return nil, fmt.Errorf("invalid request: no CRLF found in start line")
}
startLine := headerData[:lineEnd]
header.startLine = startLine
var err error
header.method, header.path, header.version, err = parseStartLine(startLine)
if err != nil {
return nil, err
}
remaining := headerData[lineEnd+2:]
setRemainingHeaders(remaining, header)
return header, nil
}
func parseStartLine(startLine []byte) (method, path, version string, err error) {
firstSpace := bytes.IndexByte(startLine, ' ')
if firstSpace == -1 {
@@ -80,51 +54,6 @@ func parseStartLine(startLine []byte) (method, path, version string, err error)
return method, path, version, nil
}
func parseHeadersFromReader(br *bufio.Reader) (RequestHeader, error) {
header := &requestHeader{
headers: make(map[string]string, 16),
}
startLineBytes, err := br.ReadSlice('\n')
if err != nil {
return nil, err
}
startLineBytes = bytes.TrimRight(startLineBytes, "\r\n")
header.startLine = make([]byte, len(startLineBytes))
copy(header.startLine, startLineBytes)
header.method, header.path, header.version, err = parseStartLine(header.startLine)
if err != nil {
return nil, err
}
for {
lineBytes, err := br.ReadSlice('\n')
if err != nil {
return nil, err
}
lineBytes = bytes.TrimRight(lineBytes, "\r\n")
if len(lineBytes) == 0 {
break
}
colonIdx := bytes.IndexByte(lineBytes, ':')
if colonIdx == -1 {
continue
}
key := bytes.TrimSpace(lineBytes[:colonIdx])
value := bytes.TrimSpace(lineBytes[colonIdx+1:])
header.headers[string(key)] = string(value)
}
return header, nil
}
func finalize(startLine []byte, headers map[string]string) []byte {
size := len(startLine) + 2
for key, val := range headers {
+23 -9
View File
@@ -1,19 +1,33 @@
package header
import (
"bufio"
"bytes"
"fmt"
)
func NewRequest(r interface{}) (RequestHeader, error) {
switch v := r.(type) {
case []byte:
return parseHeadersFromBytes(v)
case *bufio.Reader:
return parseHeadersFromReader(v)
default:
return nil, fmt.Errorf("unsupported type: %T", r)
func NewRequest(headerData []byte) (RequestHeader, error) {
header := &requestHeader{
headers: make(map[string]string, 16),
}
lineEnd := bytes.Index(headerData, []byte("\r\n"))
if lineEnd == -1 {
return nil, fmt.Errorf("invalid request: no CRLF found in start line")
}
startLine := headerData[:lineEnd]
header.startLine = startLine
var err error
header.method, header.path, header.version, err = parseStartLine(startLine)
if err != nil {
return nil, err
}
remaining := headerData[lineEnd+2:]
setRemainingHeaders(remaining, header)
return header, nil
}
func (req *requestHeader) Value(key string) string {