2022-01-08 06:35:32 +00:00
|
|
|
package packet
|
2022-01-07 17:41:02 +00:00
|
|
|
|
|
|
|
import (
|
2022-05-09 01:57:34 +00:00
|
|
|
"bufio"
|
2024-08-08 22:07:29 +00:00
|
|
|
"io"
|
2022-05-09 01:57:34 +00:00
|
|
|
"net"
|
|
|
|
"net/http"
|
2022-01-07 17:41:02 +00:00
|
|
|
"strings"
|
|
|
|
)
|
|
|
|
|
2022-01-10 19:27:12 +00:00
|
|
|
var validMethod = map[string]struct{}{
|
|
|
|
"DELETE": {},
|
|
|
|
"GET": {},
|
|
|
|
"HEAD": {},
|
|
|
|
"POST": {},
|
|
|
|
"PUT": {},
|
|
|
|
"CONNECT": {},
|
|
|
|
"OPTIONS": {},
|
|
|
|
"TRACE": {},
|
|
|
|
"COPY": {},
|
|
|
|
"LOCK": {},
|
|
|
|
"MKCOL": {},
|
|
|
|
"MOVE": {},
|
|
|
|
"PROPFIND": {},
|
|
|
|
"PROPPATCH": {},
|
|
|
|
"SEARCH": {},
|
|
|
|
"UNLOCK": {},
|
|
|
|
"BIND": {},
|
|
|
|
"REBIND": {},
|
|
|
|
"UNBIND": {},
|
|
|
|
"ACL": {},
|
|
|
|
"REPORT": {},
|
|
|
|
"MKACTIVITY": {},
|
|
|
|
"CHECKOUT": {},
|
|
|
|
"MERGE": {},
|
|
|
|
"M-SEARCH": {},
|
|
|
|
"NOTIFY": {},
|
|
|
|
"SUBSCRIBE": {},
|
|
|
|
"UNSUBSCRIBE": {},
|
|
|
|
"PATCH": {},
|
|
|
|
"PURGE": {},
|
|
|
|
"MKCALENDAR": {},
|
|
|
|
"LINK": {},
|
|
|
|
"UNLINK": {},
|
|
|
|
}
|
|
|
|
|
2024-08-22 04:05:19 +00:00
|
|
|
type HttpRequest struct {
|
2022-01-11 17:15:45 +00:00
|
|
|
raw []byte
|
|
|
|
method string
|
|
|
|
domain string
|
2022-11-29 07:54:28 +00:00
|
|
|
port string
|
2022-01-15 16:44:00 +00:00
|
|
|
path string
|
2022-01-11 17:15:45 +00:00
|
|
|
version string
|
2022-01-07 17:41:02 +00:00
|
|
|
}
|
|
|
|
|
2024-08-22 04:05:19 +00:00
|
|
|
func ReadHttpRequest(rdr io.Reader) (*HttpRequest, error) {
|
2024-08-14 17:39:23 +00:00
|
|
|
p, err := parse(rdr)
|
2024-08-08 22:07:29 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2024-08-14 17:39:23 +00:00
|
|
|
|
2024-08-08 22:07:29 +00:00
|
|
|
return p, nil
|
2022-01-07 18:01:54 +00:00
|
|
|
}
|
|
|
|
|
2024-08-22 04:05:19 +00:00
|
|
|
func (p *HttpRequest) Raw() []byte {
|
2022-01-11 17:15:45 +00:00
|
|
|
return p.raw
|
|
|
|
}
|
2024-08-22 04:05:19 +00:00
|
|
|
func (p *HttpRequest) Method() string {
|
2022-01-11 17:15:45 +00:00
|
|
|
return p.method
|
|
|
|
}
|
2022-01-15 16:44:00 +00:00
|
|
|
|
2024-08-22 04:05:19 +00:00
|
|
|
func (p *HttpRequest) Domain() string {
|
2022-01-11 17:15:45 +00:00
|
|
|
return p.domain
|
|
|
|
}
|
2022-01-15 16:44:00 +00:00
|
|
|
|
2024-08-22 04:05:19 +00:00
|
|
|
func (p *HttpRequest) Port() string {
|
2022-03-05 02:51:17 +00:00
|
|
|
return p.port
|
|
|
|
}
|
|
|
|
|
2024-08-22 04:05:19 +00:00
|
|
|
func (p *HttpRequest) Version() string {
|
2022-01-11 17:15:45 +00:00
|
|
|
return p.version
|
|
|
|
}
|
|
|
|
|
2024-08-22 04:05:19 +00:00
|
|
|
func (p *HttpRequest) IsValidMethod() bool {
|
2022-01-11 17:15:45 +00:00
|
|
|
if _, exists := validMethod[p.Method()]; exists {
|
2022-01-07 17:41:02 +00:00
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2024-08-22 04:05:19 +00:00
|
|
|
func (p *HttpRequest) IsConnectMethod() bool {
|
2022-01-11 17:15:45 +00:00
|
|
|
return p.Method() == "CONNECT"
|
2022-01-07 17:41:02 +00:00
|
|
|
}
|
|
|
|
|
2024-08-22 04:05:19 +00:00
|
|
|
func (p *HttpRequest) Tidy() {
|
2022-01-14 21:40:57 +00:00
|
|
|
s := string(p.raw)
|
|
|
|
|
2022-03-04 23:49:28 +00:00
|
|
|
lines := strings.Split(s, "\r\n")
|
2022-01-15 16:44:00 +00:00
|
|
|
|
|
|
|
lines[0] = p.method + " " + p.path + " " + p.version
|
|
|
|
|
2022-01-14 21:40:57 +00:00
|
|
|
for i := 0; i < len(lines); i++ {
|
|
|
|
if strings.HasPrefix(lines[i], "Proxy-Connection") {
|
|
|
|
lines[i] = ""
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
result := ""
|
2022-03-04 23:49:28 +00:00
|
|
|
|
2022-01-14 21:40:57 +00:00
|
|
|
for i := 0; i < len(lines); i++ {
|
|
|
|
if lines[i] == "" {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2022-03-04 23:49:28 +00:00
|
|
|
result += lines[i] + "\r\n"
|
2022-01-14 21:40:57 +00:00
|
|
|
}
|
|
|
|
|
2022-11-29 07:54:28 +00:00
|
|
|
result += "\r\n"
|
2022-03-04 23:49:28 +00:00
|
|
|
|
2022-01-14 21:40:57 +00:00
|
|
|
p.raw = []byte(result)
|
|
|
|
}
|
|
|
|
|
2024-08-22 04:05:19 +00:00
|
|
|
func parse(rdr io.Reader) (*HttpRequest, error) {
|
2024-08-14 17:39:23 +00:00
|
|
|
sb := strings.Builder{}
|
|
|
|
tee := io.TeeReader(rdr, &sb)
|
|
|
|
request, err := http.ReadRequest(bufio.NewReader(tee))
|
2022-11-29 07:54:28 +00:00
|
|
|
if err != nil {
|
2024-08-14 17:39:23 +00:00
|
|
|
return nil, err
|
2022-11-29 07:54:28 +00:00
|
|
|
}
|
|
|
|
|
2024-08-22 04:05:19 +00:00
|
|
|
p := &HttpRequest{}
|
2024-08-14 17:39:23 +00:00
|
|
|
p.raw = []byte(sb.String())
|
|
|
|
|
2022-11-29 07:54:28 +00:00
|
|
|
p.domain, p.port, err = net.SplitHostPort(request.Host)
|
|
|
|
if err != nil {
|
|
|
|
p.domain = request.Host
|
|
|
|
p.port = ""
|
|
|
|
}
|
|
|
|
|
|
|
|
p.method = request.Method
|
|
|
|
p.version = request.Proto
|
|
|
|
p.path = request.URL.Path
|
|
|
|
|
|
|
|
if request.URL.RawQuery != "" {
|
|
|
|
p.path += "?" + request.URL.RawQuery
|
|
|
|
}
|
|
|
|
|
|
|
|
if request.URL.RawFragment != "" {
|
|
|
|
p.path += "#" + request.URL.RawFragment
|
|
|
|
}
|
|
|
|
if p.path == "" {
|
|
|
|
p.path = "/"
|
|
|
|
}
|
|
|
|
|
|
|
|
request.Body.Close()
|
2024-08-14 17:39:23 +00:00
|
|
|
return p, nil
|
2022-01-07 17:41:02 +00:00
|
|
|
}
|