Repository: TwiN/gatus

Issue:
Support redacting port from endpoint result errors
### Describe the feature request

Like `endpoints[].ui.hide-hostname`, there should be something to hide the port (e.g. `endpoints[].ui.hide-port`)

### Why do you personally want this feature to be implemented?

_No response_

### How long have you been using this project?

_No response_

### Additional information

_No response_

Hints from issue comments:

Solution patch:
diff --git a/README.md b/README.md
index 67550920..7f68545d 100644
--- a/README.md
+++ b/README.md
@@ -278,8 +278,9 @@ You can then configure alerts to be triggered when an endpoint is unhealthy once
 | `endpoints[].client`                            | [Client configuration](#client-configuration).                                                                                              | `{}`                       |
 | `endpoints[].ui`                                | UI configuration at the endpoint level.                                                                                                     | `{}`                       |
 | `endpoints[].ui.hide-conditions`                | Whether to hide conditions from the results. Note that this only hides conditions from results evaluated from the moment this was enabled.  | `false`                    |
-| `endpoints[].ui.hide-hostname`                  | Whether to hide the hostname in the result.                                                                                                 | `false`                    |
-| `endpoints[].ui.hide-url`                       | Whether to ensure the URL is not displayed in the results. Useful if the URL contains a token.                                              | `false`                    |
+| `endpoints[].ui.hide-hostname`                  | Whether to hide the hostname from the results.                                                                                              | `false`                    |
+| `endpoints[].ui.hide-port`                      | Whether to hide the port from the results.                                                                                                  | `false`                    |
+| `endpoints[].ui.hide-url`                       | Whether to hide the URL from the results. Useful if the URL contains a token.                                                               | `false`                    |
 | `endpoints[].ui.dont-resolve-failed-conditions` | Whether to resolve failed conditions for the UI.                                                                                            | `false`                    |
 | `endpoints[].ui.badge.response-time`            | List of response time thresholds. Each time a threshold is reached, the badge has a different color.                                        | `[50, 200, 300, 500, 750]` |
 
diff --git a/config/endpoint/endpoint.go b/config/endpoint/endpoint.go
index a0fdb875..dfd52336 100644
--- a/config/endpoint/endpoint.go
+++ b/config/endpoint/endpoint.go
@@ -13,12 +13,12 @@ import (
 	"strings"
 	"time"
 
-	"github.com/TwiN/gatus/v5/config/maintenance"
 	"github.com/TwiN/gatus/v5/alerting/alert"
 	"github.com/TwiN/gatus/v5/client"
 	"github.com/TwiN/gatus/v5/config/endpoint/dns"
 	sshconfig "github.com/TwiN/gatus/v5/config/endpoint/ssh"
 	"github.com/TwiN/gatus/v5/config/endpoint/ui"
+	"github.com/TwiN/gatus/v5/config/maintenance"
 	"golang.org/x/crypto/ssh"
 )
 
@@ -270,6 +270,7 @@ func (e *Endpoint) EvaluateHealth() *Result {
 			result.AddError(err.Error())
 		} else {
 			result.Hostname = urlObject.Hostname()
+			result.port = urlObject.Port()
 		}
 	}
 	// Retrieve IP if necessary
@@ -307,7 +308,13 @@ func (e *Endpoint) EvaluateHealth() *Result {
 		for errIdx, errorString := range result.Errors {
 			result.Errors[errIdx] = strings.ReplaceAll(errorString, result.Hostname, "<redacted>")
 		}
-		result.Hostname = ""
+		result.Hostname = "" // remove it from the result so it doesn't get exposed
+	}
+	if e.UIConfig.HidePort && len(result.port) > 0 {
+		for errIdx, errorString := range result.Errors {
+			result.Errors[errIdx] = strings.ReplaceAll(errorString, result.port, "<redacted>")
+		}
+		result.port = ""
 	}
 	if e.UIConfig.HideConditions {
 		result.ConditionResults = nil
diff --git a/config/endpoint/result.go b/config/endpoint/result.go
index 1d20a5c6..2a7aba94 100644
--- a/config/endpoint/result.go
+++ b/config/endpoint/result.go
@@ -49,6 +49,11 @@ type Result struct {
 	// Note that this field is not persisted in the storage.
 	// It is used for health evaluation as well as debugging purposes.
 	Body []byte `json:"-"`
+
+	///////////////////////////////////////////////////////////////////////
+	// Below is used only for the UI and is not persisted in the storage //
+	///////////////////////////////////////////////////////////////////////
+	port string `yaml:"-"` // used for endpoints[].ui.hide-port
 }
 
 // AddError adds an error to the result's list of errors.
diff --git a/config/endpoint/ui/ui.go b/config/endpoint/ui/ui.go
index 5a13ccdc..0f784cb5 100644
--- a/config/endpoint/ui/ui.go
+++ b/config/endpoint/ui/ui.go
@@ -13,6 +13,9 @@ type Config struct {
 	// HideURL whether to ensure the URL is not displayed in the results. Useful if the URL contains a token.
 	HideURL bool `yaml:"hide-url"`
 
+	// HidePort whether to hide the port in the Result
+	HidePort bool `yaml:"hide-port"`
+
 	// DontResolveFailedConditions whether to resolve failed conditions in the Result for display in the UI
 	DontResolveFailedConditions bool `yaml:"dont-resolve-failed-conditions"`
 
@@ -54,6 +57,7 @@ func GetDefaultConfig() *Config {
 	return &Config{
 		HideHostname:                false,
 		HideURL:                     false,
+		HidePort:                    false,
 		DontResolveFailedConditions: false,
 		HideConditions:              false,
 		Badge: &Badge{



Test patch:
diff --git a/config/endpoint/endpoint_test.go b/config/endpoint/endpoint_test.go
index 884cacb9..4d65ff90 100644
--- a/config/endpoint/endpoint_test.go
+++ b/config/endpoint/endpoint_test.go
@@ -165,9 +165,9 @@ func TestEndpoint(t *testing.T) {
 			Name: "endpoint-that-will-time-out-and-hidden-hostname",
 			Endpoint: Endpoint{
 				Name:         "endpoint-that-will-time-out",
-				URL:          "https://twin.sh/health",
+				URL:          "https://twin.sh:9999/health",
 				Conditions:   []Condition{"[CONNECTED] == true"},
-				UIConfig:     &ui.Config{HideHostname: true},
+				UIConfig:     &ui.Config{HideHostname: true, HidePort: true},
 				ClientConfig: &client.Config{Timeout: time.Millisecond},
 			},
 			ExpectedResult: &Result{
@@ -180,7 +180,7 @@ func TestEndpoint(t *testing.T) {
 				// Because there's no [DOMAIN_EXPIRATION] condition, this is not resolved, so it should be 0.
 				DomainExpiration: 0,
 				// Because Endpoint.UIConfig.HideHostname is true, the hostname should be replaced by <redacted>.
-				Errors: []string{`Get "https://<redacted>/health": context deadline exceeded (Client.Timeout exceeded while awaiting headers)`},
+				Errors: []string{`Get "https://<redacted>:<redacted>/health": context deadline exceeded (Client.Timeout exceeded while awaiting headers)`},
 			},
 			MockRoundTripper: nil,
 		},