From 3d167a685534bc0712647655d92aaaff4eae7aa7 Mon Sep 17 00:00:00 2001 From: Darien Raymond Date: Fri, 4 Nov 2016 10:49:18 +0100 Subject: [PATCH] json config for http header --- tools/conf/transport_authenticators.go | 145 +++++++++++++++++++++++++ tools/conf/transport_internet.go | 19 +++- 2 files changed, 163 insertions(+), 1 deletion(-) diff --git a/tools/conf/transport_authenticators.go b/tools/conf/transport_authenticators.go index 04073face..bc458d346 100644 --- a/tools/conf/transport_authenticators.go +++ b/tools/conf/transport_authenticators.go @@ -1,7 +1,12 @@ package conf import ( + "encoding/json" + + "errors" + "strings" "v2ray.com/core/common/loader" + "v2ray.com/core/transport/internet/authenticators/http" "v2ray.com/core/transport/internet/authenticators/noop" "v2ray.com/core/transport/internet/authenticators/srtp" "v2ray.com/core/transport/internet/authenticators/utp" @@ -24,3 +29,143 @@ type UTPAuthenticator struct{} func (UTPAuthenticator) Build() (*loader.TypedSettings, error) { return loader.NewTypedSettings(new(utp.Config)), nil } + +type HTTPAuthenticatorHeader struct { + Name string `json:"name"` + Value *StringList `json:"value"` +} + +type HTTPAuthenticatorRequest struct { + Version *string `json:"version"` + Method *string `json:"method"` + Path *StringList `json:"path"` + Headers []HTTPAuthenticatorHeader `json:"headers"` +} + +func (this *HTTPAuthenticatorRequest) Build() (*http.RequestConfig, error) { + config := &http.RequestConfig{ + Uri: []string{"/"}, + Header: []*http.Header{ + { + Name: "Host", + Value: []string{"www.baidu.com", "www.bing.com"}, + }, + }, + } + + if this.Version != nil { + config.Version = &http.Version{Value: *this.Version} + } + + if this.Method != nil { + config.Method = &http.Method{Value: *this.Method} + } + + if this.Path != nil && this.Path.Len() > 0 { + config.Uri = append([]string(nil), (*this.Path)...) + } + + if len(this.Headers) > 0 { + config.Header = make([]*http.Header, len(this.Headers)) + for idx, header := range this.Headers { + config.Header[idx] = &http.Header{ + Name: header.Name, + Value: append([]string(nil), (*header.Value)...), + } + } + } + + return config, nil +} + +type HTTPAuthenticatorResponse struct { + Version *string `json:"version"` + Status *string `json:"status"` + Reason *string `json:"reason"` + Headers []HTTPAuthenticatorHeader `json:"headers"` +} + +func (this *HTTPAuthenticatorResponse) Build() (*http.ResponseConfig, error) { + config := &http.ResponseConfig{ + Header: []*http.Header{ + { + Name: "Content-Type", + Value: []string{"application/octet-stream", "video/mpeg"}, + }, + { + Name: "Transfer-Encoding", + Value: []string{"chunked"}, + }, + }, + } + + if this.Version != nil { + config.Version = &http.Version{Value: *this.Version} + } + + if this.Status != nil || this.Reason != nil { + config.Status = http.Status{ + Code: "200", + Reason: "OK", + } + if this.Status != nil { + config.Status.Code = *this.Status + } + if this.Reason != nil { + config.Status.Reason = *this.Reason + } + } + + if len(this.Headers) > 0 { + config.Header = make([]*http.Header, len(this.Headers)) + for idx, header := range this.Headers { + config.Header[idx] = &http.Header{ + Name: header.Name, + Value: append([]string(nil), (*header.Value)...), + } + } + } + + return config, nil +} + +type HTTPAuthenticator struct { + Request *HTTPAuthenticatorRequest `json:"request"` + Response json.RawMessage `json:"response"` +} + +func (this *HTTPAuthenticator) Build() (*loader.TypedSettings, error) { + config := new(http.Config) + if this.Request != nil { + requestConfig, err := this.Request.Build() + if err != nil { + return nil, err + } + config.Request = requestConfig + } + + if len(this.Response) > 0 { + var text string + parsed := false + if err := json.Unmarshal(this.Response, &text); err == nil { + if strings.ToLower(text) != "disabled" { + return nil, errors.New("Unknown HTTP header settings: " + text) + } + parsed = true + } + + if !parsed { + var response HTTPAuthenticatorResponse + if err := json.Unmarshal(this.Response, &response); err != nil { + return nil, errors.New("Failed to parse HTTP header response.") + } + responseConfig, err := response.Build() + if err != nil { + return nil, err + } + config.Response = responseConfig + } + } + + return loader.NewTypedSettings(config), nil +} diff --git a/tools/conf/transport_internet.go b/tools/conf/transport_internet.go index 628eb4349..c2ec1a33e 100644 --- a/tools/conf/transport_internet.go +++ b/tools/conf/transport_internet.go @@ -22,6 +22,10 @@ var ( "srtp": func() interface{} { return new(SRTPAuthenticator) }, "utp": func() interface{} { return new(UTPAuthenticator) }, }, "type", "") + + tcpHeaderLoader = NewJSONConfigLoader(ConfigCreatorCache{ + "http": func() interface{} { return new(HTTPAuthenticator) }, + }, "type", "") ) type KCPConfig struct { @@ -93,7 +97,8 @@ func (this *KCPConfig) Build() (*loader.TypedSettings, error) { } type TCPConfig struct { - ConnectionReuse *bool `json:"connectionReuse"` + ConnectionReuse *bool `json:"connectionReuse"` + HeaderConfig json.RawMessage `json:"header"` } func (this *TCPConfig) Build() (*loader.TypedSettings, error) { @@ -103,6 +108,18 @@ func (this *TCPConfig) Build() (*loader.TypedSettings, error) { Enable: *this.ConnectionReuse, } } + if len(this.HeaderConfig) > 0 { + headerConfig, _, err := tcpHeaderLoader.Load(this.HeaderConfig) + if err != nil { + return nil, errors.New("TCP|Config: Failed to parse header config: " + err.Error()) + } + ts, err := headerConfig.(Buildable).Build() + if err != nil { + return nil, errors.New("Failed to get TCP authenticator config: " + err.Error()) + } + config.HeaderSettings = ts + } + return loader.NewTypedSettings(config), nil }