| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990 | 
							- package http
 
- import (
 
- 	"bytes"
 
- 	"errors"
 
- 	"strings"
 
- 	"v2ray.com/core"
 
- )
 
- type version byte
 
- const (
 
- 	HTTP1 version = iota
 
- 	HTTP2
 
- )
 
- type SniffHeader struct {
 
- 	version version
 
- 	host    string
 
- }
 
- func (h *SniffHeader) Protocol() string {
 
- 	switch h.version {
 
- 	case HTTP1:
 
- 		return "http1"
 
- 	case HTTP2:
 
- 		return "http2"
 
- 	default:
 
- 		return "unknown"
 
- 	}
 
- }
 
- func (h *SniffHeader) Domain() string {
 
- 	return h.host
 
- }
 
- var (
 
- 	methods = [...]string{"get", "post", "head", "put", "delete", "options", "connect"}
 
- 	errNotHTTPMethod = errors.New("not an HTTP method")
 
- )
 
- func beginWithHTTPMethod(b []byte) error {
 
- 	for _, m := range &methods {
 
- 		if len(b) >= len(m) && strings.ToLower(string(b[:len(m)])) == m {
 
- 			return nil
 
- 		}
 
- 		if len(b) < len(m) {
 
- 			return core.ErrNoClue
 
- 		}
 
- 	}
 
- 	return errNotHTTPMethod
 
- }
 
- func SniffHTTP(b []byte) (*SniffHeader, error) {
 
- 	if err := beginWithHTTPMethod(b); err != nil {
 
- 		return nil, err
 
- 	}
 
- 	sh := &SniffHeader{
 
- 		version: HTTP1,
 
- 	}
 
- 	headers := bytes.Split(b, []byte{'\n'})
 
- 	for i := 1; i < len(headers); i++ {
 
- 		header := headers[i]
 
- 		if len(header) == 0 {
 
- 			break
 
- 		}
 
- 		parts := bytes.SplitN(header, []byte{':'}, 2)
 
- 		if len(parts) != 2 {
 
- 			continue
 
- 		}
 
- 		key := strings.ToLower(string(parts[0]))
 
- 		value := strings.ToLower(string(bytes.Trim(parts[1], " ")))
 
- 		if key == "host" {
 
- 			domain := strings.Split(value, ":")
 
- 			sh.host = strings.TrimSpace(domain[0])
 
- 		}
 
- 	}
 
- 	if len(sh.host) > 0 {
 
- 		return sh, nil
 
- 	}
 
- 	return nil, core.ErrNoClue
 
- }
 
 
  |