|
@@ -2,11 +2,13 @@ package http
|
|
|
|
|
|
import (
|
|
|
"bytes"
|
|
|
+ "context"
|
|
|
"errors"
|
|
|
"strings"
|
|
|
|
|
|
"github.com/xtls/xray-core/common"
|
|
|
"github.com/xtls/xray-core/common/net"
|
|
|
+ "github.com/xtls/xray-core/common/session"
|
|
|
)
|
|
|
|
|
|
type version byte
|
|
@@ -56,7 +58,14 @@ func beginWithHTTPMethod(b []byte) error {
|
|
|
return errNotHTTPMethod
|
|
|
}
|
|
|
|
|
|
-func SniffHTTP(b []byte) (*SniffHeader, error) {
|
|
|
+func SniffHTTP(b []byte, c context.Context) (*SniffHeader, error) {
|
|
|
+ content := session.ContentFromContext(c)
|
|
|
+ ShouldSniffAttr := true
|
|
|
+ // If content.Attributes have information, that means it comes from HTTP inbound PlainHTTP mode.
|
|
|
+ // It will set attributes, so skip it.
|
|
|
+ if content == nil || len(content.Attributes) != 0 {
|
|
|
+ ShouldSniffAttr = false
|
|
|
+ }
|
|
|
if err := beginWithHTTPMethod(b); err != nil {
|
|
|
return nil, err
|
|
|
}
|
|
@@ -76,8 +85,12 @@ func SniffHTTP(b []byte) (*SniffHeader, error) {
|
|
|
continue
|
|
|
}
|
|
|
key := strings.ToLower(string(parts[0]))
|
|
|
+ value := string(bytes.TrimSpace(parts[1]))
|
|
|
+ if ShouldSniffAttr {
|
|
|
+ content.SetAttribute(key, value) // Put header in attribute
|
|
|
+ }
|
|
|
if key == "host" {
|
|
|
- rawHost := strings.ToLower(string(bytes.TrimSpace(parts[1])))
|
|
|
+ rawHost := strings.ToLower(value)
|
|
|
dest, err := ParseHost(rawHost, net.Port(80))
|
|
|
if err != nil {
|
|
|
return nil, err
|
|
@@ -85,6 +98,16 @@ func SniffHTTP(b []byte) (*SniffHeader, error) {
|
|
|
sh.host = dest.Address.String()
|
|
|
}
|
|
|
}
|
|
|
+ // Parse request line
|
|
|
+ // Request line is like this
|
|
|
+ // "GET /homo/114514 HTTP/1.1"
|
|
|
+ if len(headers) > 0 && ShouldSniffAttr {
|
|
|
+ RequestLineParts := bytes.Split(headers[0], []byte{' '})
|
|
|
+ if len(RequestLineParts) == 3 {
|
|
|
+ content.SetAttribute(":method", string(RequestLineParts[0]))
|
|
|
+ content.SetAttribute(":path", string(RequestLineParts[1]))
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
if len(sh.host) > 0 {
|
|
|
return sh, nil
|