Skip to content

[server] Add health check HTTP endpoint for Relay server #4297

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: main
Choose a base branch
from

Conversation

pappz
Copy link
Contributor

@pappz pappz commented Aug 6, 2025

Describe your changes

The health check endpoint listens on a dedicated HTTP server.
By default, it is available at 0.0.0.0:9000/health. This can be configured using the --health-listen-address flag.

The results are cached for 3 seconds to avoid excessive calls.

The health check performs the following:

  • Checks the number of active listeners.
  • Validates each listener via WebSocket and QUIC dials, including TLS certificate verification.

Issue ticket number and link

Stack

Checklist

  • Is it a bug fix
  • Is a typo/documentation fix
  • Is a feature enhancement
  • It is a refactor
  • Created tests that fail without the change (if possible)
  • Extended the README / documentation, if necessary

By submitting this pull request, you confirm that you have read and agree to the terms of the Contributor License Agreement.

@pappz pappz marked this pull request as ready for review August 6, 2025 14:28
@Copilot Copilot AI review requested due to automatic review settings August 6, 2025 14:28
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Adds a health check HTTP endpoint for the Relay server to monitor service availability and certificate validation. The health check listens on a dedicated HTTP server (default: :9000/health) and performs WebSocket and QUIC connectivity tests with TLS certificate verification.

  • Implements health check endpoint with caching mechanism for 3 seconds
  • Adds protocol-specific dial validation for WebSocket and QUIC listeners
  • Refactors ALPN constant naming for consistency across the codebase

Reviewed Changes

Copilot reviewed 14 out of 14 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
shared/relay/tls/*.go Updates ALPN constant from nbalpn to NBalpn for public visibility
relay/protocol/protocol.go Adds new Protocol type for listener identification
relay/server/listener/*.go Adds Protocol method to listeners and updates interface
relay/server/server.go Adds health check support methods and thread-safe listener management
relay/healthcheck/*.go Implements health check server with WebSocket and QUIC dial validation
relay/cmd/root.go Integrates health check server with proper lifecycle management

@@ -40,6 +42,7 @@ type Config struct {
AuthSecret string
LogLevel string
LogFile string
HatcheckListenAddress string
Copy link
Preview

Copilot AI Aug 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The field name 'HatcheckListenAddress' appears to be a typo. It should be 'HealthcheckListenAddress' or 'HealthCheckListenAddress'.

Suggested change
HatcheckListenAddress string
HealthcheckListenAddress string

Copilot uses AI. Check for mistakes.

@@ -87,6 +90,7 @@ func init() {
rootCmd.PersistentFlags().StringVarP(&cobraConfig.AuthSecret, "auth-secret", "s", "", "auth secret")
rootCmd.PersistentFlags().StringVar(&cobraConfig.LogLevel, "log-level", "info", "log level")
rootCmd.PersistentFlags().StringVar(&cobraConfig.LogFile, "log-file", "console", "log file")
rootCmd.PersistentFlags().StringVarP(&cobraConfig.HatcheckListenAddress, "health-listen-address", "H", ":9000", "listen address of healthcheck server")
Copy link
Preview

Copilot AI Aug 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The variable reference 'HatcheckListenAddress' appears to be a typo. It should be 'HealthcheckListenAddress' or 'HealthCheckListenAddress' to match the corrected field name.

Suggested change
rootCmd.PersistentFlags().StringVarP(&cobraConfig.HatcheckListenAddress, "health-listen-address", "H", ":9000", "listen address of healthcheck server")
rootCmd.PersistentFlags().StringVarP(&cobraConfig.HealthcheckListenAddress, "health-listen-address", "H", ":9000", "listen address of healthcheck server")

Copilot uses AI. Check for mistakes.

if err := srv.Listen(srvListenerCfg); err != nil {
log.Fatalf("failed to bind server: %s", err)
}
}()

hCfg := healthcheck.Config{
ListenAddress: cobraConfig.HatcheckListenAddress,
Copy link
Preview

Copilot AI Aug 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The variable reference 'HatcheckListenAddress' appears to be a typo. It should be 'HealthcheckListenAddress' or 'HealthCheckListenAddress' to match the corrected field name.

Suggested change
ListenAddress: cobraConfig.HatcheckListenAddress,
ListenAddress: cobraConfig.HealthcheckListenAddress,

Copilot uses AI. Check for mistakes.


const (
statusHealthy = "healthy"
statusUnHealthy = "unHealthy"
Copy link
Preview

Copilot AI Aug 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The constant 'statusUnHealthy' should be 'statusUnhealthy' (lowercase 'h') to follow standard English spelling.

Suggested change
statusUnHealthy = "unHealthy"
statusUnhealthy = "unhealthy"

Copilot uses AI. Check for mistakes.

Comment on lines 133 to 139
status.Status = statusUnHealthy
healthy = false
}
status.Listeners = listeners

if ok := s.validateCertificate(ctx); !ok {
status.Status = statusUnHealthy
Copy link
Preview

Copilot AI Aug 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The status assignment should use 'statusUnhealthy' instead of 'statusUnHealthy' to match the corrected constant name.

Suggested change
status.Status = statusUnHealthy
healthy = false
}
status.Listeners = listeners
if ok := s.validateCertificate(ctx); !ok {
status.Status = statusUnHealthy
status.Status = statusUnhealthy
healthy = false
}
status.Listeners = listeners
if ok := s.validateCertificate(ctx); !ok {
status.Status = statusUnhealthy

Copilot uses AI. Check for mistakes.

status.Listeners = listeners

if ok := s.validateCertificate(ctx); !ok {
status.Status = statusUnHealthy
Copy link
Preview

Copilot AI Aug 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The status assignment should use 'statusUnhealthy' instead of 'statusUnHealthy' to match the corrected constant name.

Copilot uses AI. Check for mistakes.

Proto protocol.Protocol = "ws"
URLPath = relay.WebSocketURLPath
)

// URLPath is the path for the websocket connection.
Copy link
Preview

Copilot AI Aug 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment is now redundant since URLPath is defined as a constant above. The comment should be removed or moved to the constant definition.

Suggested change
// URLPath is the path for the websocket connection.

Copilot uses AI. Check for mistakes.

defer func() {
_ = resp.Body.Close()
}()

Copy link
Preview

Copilot AI Aug 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The empty line after the anonymous function declaration creates unnecessary whitespace. Remove the blank line for cleaner code formatting.

Suggested change

Copilot uses AI. Check for mistakes.

Copy link

sonarqubecloud bot commented Aug 6, 2025

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant