diff --git a/app/observatory/burst/config.pb.go b/app/observatory/burst/config.pb.go index ffbd0689..570384ae 100644 --- a/app/observatory/burst/config.pb.go +++ b/app/observatory/burst/config.pb.go @@ -90,6 +90,8 @@ type HealthPingConfig struct { SamplingCount int32 `protobuf:"varint,4,opt,name=samplingCount,proto3" json:"samplingCount,omitempty"` // ping timeout, int64 values of time.Duration Timeout int64 `protobuf:"varint,5,opt,name=timeout,proto3" json:"timeout,omitempty"` + // http method to make request + HttpMethod string `protobuf:"bytes,6,opt,name=httpMethod,proto3" json:"httpMethod,omitempty"` } func (x *HealthPingConfig) Reset() { @@ -157,6 +159,13 @@ func (x *HealthPingConfig) GetTimeout() int64 { return 0 } +func (x *HealthPingConfig) GetHttpMethod() string { + if x != nil { + return x.HttpMethod + } + return "" +} + var File_app_observatory_burst_config_proto protoreflect.FileDescriptor var file_app_observatory_burst_config_proto_rawDesc = []byte{ @@ -173,7 +182,7 @@ var file_app_observatory_burst_config_proto_rawDesc = []byte{ 0x2e, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f, 0x72, 0x79, 0x2e, 0x62, 0x75, 0x72, 0x73, 0x74, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x50, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0a, 0x70, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, - 0xb4, 0x01, 0x0a, 0x10, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x50, 0x69, 0x6e, 0x67, 0x43, 0x6f, + 0xd4, 0x01, 0x0a, 0x10, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x50, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x22, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, @@ -184,7 +193,9 @@ var file_app_observatory_burst_config_proto_rawDesc = []byte{ 0x6e, 0x67, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x74, - 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x42, 0x70, 0x0a, 0x1e, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, + 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x68, 0x74, 0x74, 0x70, 0x4d, 0x65, + 0x74, 0x68, 0x6f, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x68, 0x74, 0x74, 0x70, + 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x42, 0x70, 0x0a, 0x1e, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f, 0x72, 0x79, 0x2e, 0x62, 0x75, 0x72, 0x73, 0x74, 0x50, 0x01, 0x5a, 0x2f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, diff --git a/app/observatory/burst/config.proto b/app/observatory/burst/config.proto index ead75478..a60978d5 100644 --- a/app/observatory/burst/config.proto +++ b/app/observatory/burst/config.proto @@ -26,4 +26,7 @@ message HealthPingConfig { int32 samplingCount = 4; // ping timeout, int64 values of time.Duration int64 timeout = 5; + // http method to make request + string httpMethod = 6; + } diff --git a/app/observatory/burst/healthping.go b/app/observatory/burst/healthping.go index 0d8cab9f..cb1c3402 100644 --- a/app/observatory/burst/healthping.go +++ b/app/observatory/burst/healthping.go @@ -19,6 +19,7 @@ type HealthPingSettings struct { Interval time.Duration `json:"interval"` SamplingCount int `json:"sampling"` Timeout time.Duration `json:"timeout"` + HttpMethod string `json:"httpMethod"` } // HealthPing is the health checker for balancers @@ -37,12 +38,21 @@ type HealthPing struct { func NewHealthPing(ctx context.Context, dispatcher routing.Dispatcher, config *HealthPingConfig) *HealthPing { settings := &HealthPingSettings{} if config != nil { + + var httpMethod string + if config.HttpMethod == "" { + httpMethod = "HEAD" + } else { + httpMethod = strings.TrimSpace(config.HttpMethod) + } + settings = &HealthPingSettings{ Connectivity: strings.TrimSpace(config.Connectivity), Destination: strings.TrimSpace(config.Destination), Interval: time.Duration(config.Interval), SamplingCount: int(config.SamplingCount), Timeout: time.Duration(config.Timeout), + HttpMethod: httpMethod, } } if settings.Destination == "" { @@ -164,7 +174,7 @@ func (h *HealthPing) doCheck(tags []string, duration time.Duration, rounds int) } time.AfterFunc(delay, func() { errors.LogDebug(h.ctx, "checking ", handler) - delay, err := client.MeasureDelay() + delay, err := client.MeasureDelay(h.Settings.HttpMethod) if err == nil { ch <- &rtt{ handler: handler, @@ -251,7 +261,7 @@ func (h *HealthPing) checkConnectivity() bool { h.Settings.Connectivity, h.Settings.Timeout, ) - if _, err := tester.MeasureDelay(); err != nil { + if _, err := tester.MeasureDelay(h.Settings.HttpMethod); err != nil { return false } return true diff --git a/app/observatory/burst/ping.go b/app/observatory/burst/ping.go index 5ea1433a..fcb40f1a 100644 --- a/app/observatory/burst/ping.go +++ b/app/observatory/burst/ping.go @@ -2,6 +2,7 @@ package burst import ( "context" + "io" "net/http" "time" @@ -51,20 +52,28 @@ func newHTTPClient(ctxv context.Context, dispatcher routing.Dispatcher, handler } // MeasureDelay returns the delay time of the request to dest -func (s *pingClient) MeasureDelay() (time.Duration, error) { +func (s *pingClient) MeasureDelay(httpMethod string) (time.Duration, error) { if s.httpClient == nil { panic("pingClient not initialized") } - req, err := http.NewRequest(http.MethodHead, s.destination, nil) + + req, err := http.NewRequest(httpMethod, s.destination, nil) if err != nil { return rttFailed, err } + start := time.Now() resp, err := s.httpClient.Do(req) if err != nil { return rttFailed, err } - // don't wait for body + if httpMethod == http.MethodGet { + _, err = io.Copy(io.Discard, resp.Body) + if err != nil { + return rttFailed, err + } + } resp.Body.Close() + return time.Since(start), nil } diff --git a/infra/conf/router_strategy.go b/infra/conf/router_strategy.go index 98bcc8d1..464cbcfb 100644 --- a/infra/conf/router_strategy.go +++ b/infra/conf/router_strategy.go @@ -2,6 +2,7 @@ package conf import ( "google.golang.org/protobuf/proto" + "strings" "github.com/xtls/xray-core/app/observatory/burst" "github.com/xtls/xray-core/app/router" @@ -51,15 +52,23 @@ type healthCheckSettings struct { Interval duration.Duration `json:"interval"` SamplingCount int `json:"sampling"` Timeout duration.Duration `json:"timeout"` + HttpMethod string `json:"httpMethod"` } func (h healthCheckSettings) Build() (proto.Message, error) { + var httpMethod string + if h.HttpMethod == "" { + httpMethod = "HEAD" + } else { + httpMethod = strings.TrimSpace(h.HttpMethod) + } return &burst.HealthPingConfig{ Destination: h.Destination, Connectivity: h.Connectivity, Interval: int64(h.Interval), Timeout: int64(h.Timeout), SamplingCount: int32(h.SamplingCount), + HttpMethod: httpMethod, }, nil }