From fec52b7942eb87e2b530955b3503b7c9db652a30 Mon Sep 17 00:00:00 2001 From: Javier Cicchelli Date: Sun, 23 Aug 2026 11:07:17 +0200 Subject: [PATCH] Added the noindex robots tag to the responses on the Health controller in the Website library target. --- .../Public/Extensions/HTTPFieldName+Constants.swift | 2 ++ .../Library/Public/Controllers/HealthController.swift | 10 +++++++++- .../Public/Controllers/HealthControllerTests.swift | 4 ++++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/Packages/Infrastructure/Sources/Public/Extensions/HTTPFieldName+Constants.swift b/Packages/Infrastructure/Sources/Public/Extensions/HTTPFieldName+Constants.swift index 365523e..71b5fc1 100644 --- a/Packages/Infrastructure/Sources/Public/Extensions/HTTPFieldName+Constants.swift +++ b/Packages/Infrastructure/Sources/Public/Extensions/HTTPFieldName+Constants.swift @@ -5,6 +5,8 @@ public extension HTTPField.Name { static let permissionsPolicy = Self("Permissions-Policy")! /// The `Referrer-Policy` field name (not provided as a standard `HTTPField.Name`). static let referrerPolicy = Self("Referrer-Policy")! + /// The `X-Robots-Tag` field name (not provided as a standard `HTTPField.Name`). + static let robotsTag = Self("X-Robots-Tag")! /// The `X-Frame-Options` field name (not provided as a standard `HTTPField.Name`). static let frameOptions = Self("X-Frame-Options")! /// The `X-Forwarded-For` field name (not provided as a standard `HTTPField.Name`). diff --git a/Services/Website/Sources/Library/Public/Controllers/HealthController.swift b/Services/Website/Sources/Library/Public/Controllers/HealthController.swift index b6043a0..4a35757 100644 --- a/Services/Website/Sources/Library/Public/Controllers/HealthController.swift +++ b/Services/Website/Sources/Library/Public/Controllers/HealthController.swift @@ -116,6 +116,11 @@ private extension HealthController { } /// Builds a JSON response carrying the given status and payload. + /// + /// Every response is marked `noindex`. The checks answer `200 OK` to anyone who asks and nothing on the site links to them, so they are + /// unlikely to be found — but `robots.txt` allows the whole site, and a path that leaks into a log, a monitor, or an inbound link is crawlable + /// on discovery. The header keeps them out of the index even once they are fetched, which a `Disallow` rule would not: that stops the crawl, not + /// the indexing, and publishes the paths to everyone reading the file. /// - Parameters: /// - status: the HTTP status of the response. /// - payload: the JSON body of the response. @@ -126,7 +131,10 @@ private extension HealthController { ) -> Response { Response( status: status, - headers: [.contentType: "application/json"], + headers: [ + .contentType: "application/json", + .robotsTag: "noindex", + ], body: .init(byteBuffer: .init(string: payload)) ) } diff --git a/Services/Website/Tests/Library/Cases/Public/Controllers/HealthControllerTests.swift b/Services/Website/Tests/Library/Cases/Public/Controllers/HealthControllerTests.swift index 00480d5..84048da 100644 --- a/Services/Website/Tests/Library/Cases/Public/Controllers/HealthControllerTests.swift +++ b/Services/Website/Tests/Library/Cases/Public/Controllers/HealthControllerTests.swift @@ -1,5 +1,6 @@ import Hummingbird import HummingbirdTesting +import Infrastructure import Logging import NIOCore import Persistence @@ -29,6 +30,7 @@ struct HealthControllerTests { #expect(response.status == .ok) #expect(response.headers[.contentType] == "application/json") #expect(body == #"{"status":"ok"}"#) + #expect(response.headers[.robotsTag] == "noindex") } } } @@ -54,6 +56,7 @@ struct HealthControllerTests { #expect(response.status == .ok) #expect(response.headers[.contentType] == "application/json") #expect(body == #"{"status":"ready"}"#) + #expect(response.headers[.robotsTag] == "noindex") } } } catch { @@ -99,6 +102,7 @@ struct HealthControllerTests { #expect(response.status == .serviceUnavailable) #expect(response.headers[.contentType] == "application/json") #expect(body == #"{"status":"unavailable"}"#) + #expect(response.headers[.robotsTag] == "noindex") } } } catch {