httpLayer

package
v1.2.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 20, 2022 License: MIT Imports: 15 Imported by: 0

Documentation

Overview

Package httpLayer provides methods for parsing and sending http request and response.

Fallback 由 本包 处理. 因为回落的目标只可能是http服务器.

http头 格式 可以参考:

https://datatracker.ietf.org/doc/html/rfc2616#section-4

https://datatracker.ietf.org/doc/html/rfc2616#section-5

V2ray 兼容性

http头我们希望能够完全兼容 v2ray的行为。

观察v2ray的实现,在没有header时,还会添加一个 Date ,这个v2ray的文档里没提

v2ray文档: https://www.v2fly.org/config/transport/tcp.html#noneheaderobject

相关 v2ray代码: https://github.com/v2fly/v2ray-core/tree/master/transport/internet/headers/http/http.go

我们虽然宣称兼容 v2ray,但在对于这种 不在 v2ray文档里提及的 代码实现, 我们不予支持。

Index

Constants

View Source
const (
	FallBack_default byte = 1 << iota //default 其实也是path,只不过path是通配符。

	Fallback_path
	Fallback_alpn
	Fallback_sni
)
View Source
const (
	H11_Str = "http/1.1"
	H2_Str  = "h2"

	CRLF = "\r\n"

	//参考 https://datatracker.ietf.org/doc/html/rfc2616#section-4.1
	//
	//http头的尾部. 每个header末尾都有一个 crlf, 整个头部结尾还有一个crlf, 所以是两个.
	HeaderENDING = CRLF + CRLF
)
View Source
const (

	// real nginx response, echo xx | nc 127.0.0.1 80 > response
	Err400response_nginx = "" /* 314-byte string literal not displayed */

	// real nginx response, curl -iv --raw 127.0.0.1/not_exist_path > response
	Err404response_nginx = "" /* 404-byte string literal not displayed */

	/* real nginx response, set nginx config like:
	location / {
		return 403;
	}

	*/
	Err403response_nginx = `` /* 352-byte string literal not displayed */

)
View Source
const Err403response = "HTTP/1.1 403 Forbidden\r\nConnection: close\r\nCache-Control: max-age=3600, public\r\nContent-Length: 0\r\n\r\n"
View Source
const (
	Fallback_none = 0
)
View Source
const MaxParseUrlLen = 3000

也许有 ws 的 earlydata放在 query请求里的情况; 虽然本作不支持这种earlydata, 但是也要认定这是合法的请求。

Variables

View Source
var (
	HeaderENDING_bytes = []byte(HeaderENDING)

	ErrNotHTTP_Request = utils.InvalidDataErr("not http request")

	Err400response_golang string
)
View Source
var ErrShouldFallback = errors.New("will fallback")

Functions

func AllHeadersIn added in v1.2.0

func AllHeadersIn(template map[string][]string, realh http.Header) (ok bool, firstNotMatchKey string)

all values in template is given by real

func CanonicalizeHeaderKey added in v1.2.1

func CanonicalizeHeaderKey(k []byte)

Algorithm below is like standard textproto/CanonicalMIMEHeaderKey, except that it operates with slice of bytes and modifies it inplace without copying. copied from gobwas/ws

func GetReal400Response added in v1.2.1

func GetReal400Response() string

Get real a 400 response that looks like it comes from nginx.

func GetReal403Response added in v1.2.1

func GetReal403Response() string

Get real a 403 response that looks like it comes from nginx.

func GetReal404Response added in v1.2.1

func GetReal404Response() string

Get real a 404 response that looks like it comes from nginx.

func GetRealResponse added in v1.2.1

func GetRealResponse(template string) string

Get real a response that looks like it comes from nginx.

func HasFallbackType

func HasFallbackType(ftype, b byte) bool

判断 Fallback.SupportType 返回的 数值 是否具有特定的Fallback类型

func TrimHeaders added in v1.2.0

func TrimHeaders(m map[string][]string) (result map[string][]string)

return a clone of m with headers trimmed to one value

Types

type ClassicFallback

type ClassicFallback struct {
	Default *FallbackResult

	Map map[string]map[FallbackConditionSet]*FallbackResult
	// contains filtered or unexported fields
}

实现 Fallback,支持 path, alpn, sni 分流。 内部 map 我们使用通用的集合办法, 而不是多层map嵌套; 虽然目前就三个fallback类型,但是谁知道以后会加几个?所以这样更通用. 目前3种fallback性能是没问题的,不过如果 fallback继续增加的话, 最差情况下集合的子集总数会急剧上升,导致最差情况下性能不如多重 map;不过一般没人那么脑残会给出那种配置.

func NewClassicFallback

func NewClassicFallback() *ClassicFallback

func NewClassicFallbackFromConfList

func NewClassicFallbackFromConfList(fcl []*FallbackConf) *ClassicFallback

func (*ClassicFallback) GetFallback

func (cfb *ClassicFallback) GetFallback(fromServerTag string, ftype byte, ss ...string) *FallbackResult

GetFallback 使用给出的 ftype mask 和 对应参数 来试图匹配到 回落地址. ss 必须按 FallBack_* 类型 从小到大顺序排列

func (*ClassicFallback) InsertFallbackConditionSet

func (cfb *ClassicFallback) InsertFallbackConditionSet(condition FallbackConditionSet, forServerTags []string, addr netLayer.Addr, xver int)

func (*ClassicFallback) SupportType

func (cfb *ClassicFallback) SupportType() byte

type Fallback

type Fallback interface {
	GetFallback(ftype byte, params ...string) *FallbackResult
	SupportType() byte //参考Fallback_开头的常量。如果支持多个,则返回它们 按位与 的结果
}

实现 Fallback. 这里的fallback只与http协议有关,所以只能按path,alpn 和 sni 进行分类

type FallbackConditionSet

type FallbackConditionSet struct {
	Path, Sni string
	AlpnMask  byte
}

func (*FallbackConditionSet) GetAllSubSets

func (fcs *FallbackConditionSet) GetAllSubSets() (rs []FallbackConditionSet)

返回不包括自己的所有子集

func (*FallbackConditionSet) GetSub

func (fcs *FallbackConditionSet) GetSub(subType byte) (r FallbackConditionSet)

func (*FallbackConditionSet) GetType

func (fcs *FallbackConditionSet) GetType() (r byte)

func (FallbackConditionSet) TestAllSubSets

func (fcs FallbackConditionSet) TestAllSubSets(allsupportedTypeMask byte, theMap map[FallbackConditionSet]*FallbackResult) *FallbackResult

TestAllSubSets 传入一个map, 对fcs自己以及其所有子集依次测试, 看是否有匹配的。 对比 GetAllSubSets 内存占用较大, 而本方法开销则小很多, 因为1是复用内存, 2是匹配到就会返回,一般不会到遍历全部子集.

type FallbackConf

type FallbackConf struct {
	//可选
	FromTag []string `toml:"from" json:"from"` //which inServer triggered this fallback

	Xver int `toml:"xver" json:"xver"` //use PROXY protocol or not, and which version

	//必填
	Dest any `toml:"dest" json:"dest"` //see netLayer.NewAddrFromAny for details about "any" addr

	Path string   `toml:"path" json:"path"`
	Sni  string   `toml:"sni" json:"sni"`
	Alpn []string `toml:"alpn" json:"alpn"`
}

type FallbackMeta added in v1.2.0

type FallbackMeta struct {
	net.Conn
	H1RequestBuf *bytes.Buffer
	Path         string
	Method       string
	IsH2         bool

	H2Request *http.Request
}

http level fallback metadata

type FallbackResult added in v1.2.0

type FallbackResult struct {
	Addr netLayer.Addr
	Xver int
}

func (*FallbackResult) GetFallback added in v1.2.0

func (r *FallbackResult) GetFallback(ftype byte, _ ...string) *FallbackResult

func (FallbackResult) SupportType added in v1.2.0

func (FallbackResult) SupportType() byte

type H1RequestParser added in v1.2.0

type H1RequestParser struct {
	Version         string
	Path            string
	Method          string
	WholeRequestBuf *bytes.Buffer
	Failreason      int //为0表示没错误
	Headers         []RawHeader
}

H1RequestParser被用于 预读一个链接,判断该连接是否是有效的http请求, 并将Version,Path,Method 记录在结构中.

只能过滤 http 0.9, 1.0 和 1.1. 无法过滤h2和h3.

func (*H1RequestParser) ReadAndParse added in v1.2.0

func (rhr *H1RequestParser) ReadAndParse(r io.Reader) error

尝试读取数据并解析HTTP请求, 解析道道 数据会存入 RequestParser 结构中. 如果读取错误,会返回该错误; 如果读到的不是HTTP请求,返回 的err 的 errors.Is(err,ErrNotHTTP_Request) == true;

type HeaderConn

type HeaderConn struct {
	net.Conn
	H           *HeaderPreset
	IsServerEnd bool
	// contains filtered or unexported fields
}

func (*HeaderConn) Read

func (c *HeaderConn) Read(p []byte) (n int, err error)

func (*HeaderConn) Write

func (c *HeaderConn) Write(p []byte) (n int, err error)

type HeaderPreset

type HeaderPreset struct {
	Request  *RequestHeader  `toml:"request"`
	Response *ResponseHeader `toml:"response"`

	Strict bool `toml:"strict"`
}

http 头 预设, 分客户端的request 和 服务端的 response这两部分.

func (*HeaderPreset) AssignDefaultValue

func (h *HeaderPreset) AssignDefaultValue()

默认值保持与v2ray的配置相同

func (*HeaderPreset) Prepare added in v1.2.0

func (h *HeaderPreset) Prepare()

将Header改为首字母大写

func (*HeaderPreset) ReadRequest

func (h *HeaderPreset) ReadRequest(underlay net.Conn) (leftBuf *bytes.Buffer, err error)

func (*HeaderPreset) ReadResponse

func (h *HeaderPreset) ReadResponse(underlay net.Conn) (leftBuf *bytes.Buffer, err error)

func (*HeaderPreset) WriteRequest

func (h *HeaderPreset) WriteRequest(underlay net.Conn, payload []byte) error

func (*HeaderPreset) WriteResponse

func (h *HeaderPreset) WriteResponse(underlay net.Conn, payload []byte) error

type RawHeader added in v1.2.1

type RawHeader struct {
	Head  []byte
	Value []byte
}

func ParseH1Request added in v1.2.1

func ParseH1Request(bs []byte, isproxy bool) (version, method, path string, headers []RawHeader, failreason int)

从数据中试图获取 http1.1, http1.0或 http0.9 请求的 version, path, method 和 headers. failreason!=0 表示获取失败, 即表示不是合法的h1请求.

如果是http代理的话,判断方式会有变化,所以需要 isproxy 参数。

type RequestErr

type RequestErr struct {
	Path   string
	Method string
}

func (*RequestErr) Error

func (e *RequestErr) Error() string

func (*RequestErr) Is added in v1.2.0

func (e *RequestErr) Is(err error) bool

type RequestHeader

type RequestHeader struct {
	Version string              `toml:"version"` //默认值为 "1.1"
	Method  string              `toml:"method"`  //默认值为 "GET"。
	Path    []string            `toml:"path"`    //默认值为 ["/"]。当有多个值时,每次请求随机选择一个值。
	Headers map[string][]string `toml:"headers"` //一个键值对,每个键表示一个 HTTP 头的名称,对应的值是一个数组。每次请求会附上所有的键,并随机选择一个对应的值。
}

type ResponseHeader

type ResponseHeader struct {
	Version    string              `toml:"version"` // 1.1
	StatusCode string              `toml:"status"`  // 200
	Reason     string              `toml:"reason"`  // OK
	Headers    map[string][]string `toml:"headers"`
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL