package health import ( "context" "errors" "fmt" "net/http" "time" ) const defaultRequestTimeout = 5 * time.Second // Config is the HTTP checker configuration settings container. type HTTPConfig struct { // URL is the remote service health check URL. URL string // RequestTimeout is the duration that health check will try to consume published test message. // If not set - 5 seconds RequestTimeout time.Duration } // New creates new HTTP service health check that verifies the following: // - connection establishing // - getting response status from defined URL // - verifying that status code is less than 500 func NewHTTPCheck(config HTTPConfig) CheckFunc { if config.RequestTimeout == 0 { config.RequestTimeout = defaultRequestTimeout } return func(ctx context.Context) error { req, err := http.NewRequest(http.MethodGet, config.URL, nil) if err != nil { return fmt.Errorf("creating the request for the health check failed: %w", err) } ctx, cancel := context.WithTimeout(ctx, config.RequestTimeout) defer cancel() // Inform remote service to close the connection after the transaction is complete req.Header.Set("Connection", "close") req = req.WithContext(ctx) res, err := http.DefaultClient.Do(req) if err != nil { return fmt.Errorf("making the request for the health check failed: %w", err) } defer res.Body.Close() if res.StatusCode >= http.StatusInternalServerError { return errors.New("remote service is not available at the moment") } return nil } }