96 lines
1.6 KiB
Go
96 lines
1.6 KiB
Go
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
|
|
}
|