Skip to content

Commit b700213

Browse files
authored
Merge pull request #257 from TelemetryDeck/fix/254-invalid-service-url
Fix: keep trailing slash as required by the ingestion API
2 parents ec5f901 + d842f5c commit b700213

File tree

4 files changed

+61
-11
lines changed

4 files changed

+61
-11
lines changed

.github/workflows/ci.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ jobs:
2727
xcode:
2828
- "26"
2929
xcodebuildCommand:
30-
- "-sdk iphonesimulator -destination 'platform=iOS Simulator,OS=26.0.1,name=iPhone 17'"
30+
- "-sdk iphonesimulator -destination 'platform=iOS Simulator,OS=26.1,name=iPhone 17'"
3131
- "-sdk macosx -destination 'platform=macOS'"
3232
- "-sdk xrsimulator -destination 'platform=visionOS Simulator,OS=26.0,name=Apple Vision Pro'"
3333
- "-sdk appletvsimulator -destination 'platform=tvOS Simulator,OS=26.0,name=Apple TV 4K (3rd generation)'"

Sources/TelemetryDeck/Signals/SignalManager.swift

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -262,15 +262,13 @@ extension SignalManager {
262262
extension SignalManager {
263263
private func send(_ signalPostBodies: [SignalPostBody], completionHandler: @escaping @Sendable (Data?, URLResponse?, Error?) -> Void) {
264264
DispatchQueue.global(qos: .utility).async {
265-
let url: URL
266-
if let namespace = self.configuration.namespace, !namespace.isEmpty {
267-
url = self.configuration.apiBaseURL
268-
.appendingPathComponent("v2")
269-
.appendingPathComponent("namespace")
270-
.appendingPathComponent(namespace)
271-
} else {
272-
url = self.configuration.apiBaseURL
273-
.appendingPathComponent("v2")
265+
guard let url = SignalManager.getServiceUrl(baseURL: self.configuration.apiBaseURL, namespace: self.configuration.namespace) else {
266+
self.configuration.logHandler?.log(
267+
.error,
268+
message: "Unable to construct signal API URL for namespace \(self.configuration.namespace ?? "nil")"
269+
)
270+
DispatchQueue.main.async { completionHandler(nil, nil, TelemetryError.invalidEndpointUrl) }
271+
return
274272
}
275273

276274
var urlRequest = URLRequest(url: url)
@@ -291,6 +289,21 @@ extension SignalManager {
291289
task.resume()
292290
}
293291
}
292+
293+
static func getServiceUrl(baseURL: URL, namespace: String? = nil) -> URL? {
294+
let path =
295+
if let namespace = namespace, !namespace.isEmpty {
296+
"/v2/namespace/\(namespace)/"
297+
} else {
298+
"/v2/"
299+
}
300+
301+
guard let serviceURL = URL(string: path, relativeTo: baseURL)?.standardized else {
302+
return nil
303+
}
304+
305+
return serviceURL
306+
}
294307
}
295308

296309
// MARK: - Helpers
@@ -364,6 +377,7 @@ private enum TelemetryError: Error {
364377
case forbidden
365378
case payloadTooLarge
366379
case invalidStatusCode(statusCode: Int)
380+
case invalidEndpointUrl
367381
}
368382

369383
extension TelemetryError: LocalizedError {
@@ -377,6 +391,8 @@ extension TelemetryError: LocalizedError {
377391
return "Forbidden (403)"
378392
case .payloadTooLarge:
379393
return "Payload is too large (413)"
394+
case .invalidEndpointUrl:
395+
return "Invalid endpoint URL"
380396
}
381397
}
382398
}

Sources/TelemetryDeck/TelemetryClient.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import Foundation
1010
import TVUIKit
1111
#endif
1212

13-
let sdkVersion = "2.9.7"
13+
let sdkVersion = "2.9.8"
1414

1515
/// Configuration for TelemetryManager
1616
///
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
//
2+
// TelemetryClientTests.swift
3+
// TelemetryDeck
4+
//
5+
// Created by Konstantin on 17/11/2025.
6+
//
7+
8+
import Foundation
9+
import Testing
10+
11+
@testable import TelemetryDeck
12+
13+
struct TelemetryClientTests {
14+
15+
@Test
16+
func `SignalManager creates correct service url`() {
17+
18+
let config = TelemetryManagerConfiguration(appID: "44e0f59a-60a2-4d4a-bf27-1f96ccb4aaa3")
19+
let result = SignalManager.getServiceUrl(baseURL: config.apiBaseURL)
20+
21+
#expect(result != nil)
22+
#expect(result?.absoluteString == "https://nom.telemetrydeck.com/v2/")
23+
}
24+
25+
@Test
26+
func `SignalManager creates correct service url with namespace`() {
27+
28+
let config = TelemetryManagerConfiguration(appID: "44e0f59a-60a2-4d4a-bf27-1f96ccb4aaa3")
29+
let result = SignalManager.getServiceUrl(baseURL: config.apiBaseURL, namespace: "deltaquadrant")
30+
31+
#expect(result != nil)
32+
#expect(result?.absoluteString == "https://nom.telemetrydeck.com/v2/namespace/deltaquadrant/")
33+
}
34+
}

0 commit comments

Comments
 (0)