Files
computer-network/server/request.go
T

96 lines
1.6 KiB
Go
Raw Normal View History

2026-03-30 22:05:57 +08:00
package server
import (
"bufio"
"errors"
"strings"
)
type Request struct {
Method string
URL string
HTTPVersion string
Headers map[string]string
Body string
}
var (
ErrMalformedRequest = errors.New("malformed HTTP request")
ErrInvalidMethod = errors.New("invalid HTTP method")
)
func ParseRequest(reader *bufio.Reader) (*Request, error) {
requestLine, err := reader.ReadString('\n')
if err != nil {
return nil, ErrMalformedRequest
}
requestLine = strings.TrimSpace(requestLine)
if requestLine == "" {
return nil, ErrMalformedRequest
}
parts := strings.Fields(requestLine)
if len(parts) != 3 {
return nil, ErrMalformedRequest
}
req := &Request{
Method: parts[0],
URL: parts[1],
HTTPVersion: parts[2],
Headers: make(map[string]string),
}
for {
headerLine, err := reader.ReadString('\n')
if err != nil {
break
}
headerLine = strings.TrimSpace(headerLine)
if headerLine == "" {
break
}
parts := strings.SplitN(headerLine, ":", 2)
if len(parts) == 2 {
key := strings.TrimSpace(parts[0])
value := strings.TrimSpace(parts[1])
req.Headers[key] = value
}
}
return req, nil
}
func (r *Request) IsValid() bool {
switch r.Method {
case "GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS", "PATCH":
return true
default:
return false
}
}
func (r *Request) IsGET() bool {
return r.Method == "GET"
}
func (r *Request) GetPath() string {
if r.URL == "" || r.URL == "/" {
return "/index.html"
}
path := strings.SplitN(r.URL, "?", 2)[0]
if path == "/" {
return "/index.html"
}
if strings.HasPrefix(path, "/") {
return path
}
return "/" + path
}