Skip to content

Commit 6d93d1e

Browse files
authored
Merge pull request #1 from Pattio/ebyla/localhost-configuration
Allow to customize port and scheme
2 parents a8e808b + 9a79dab commit 6d93d1e

File tree

4 files changed

+73
-0
lines changed

4 files changed

+73
-0
lines changed

Sources/Modules/Core/HTTPRequest.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,15 @@ public struct HTTPRequest: Sendable {
3030
/// - method: The HTTP method.
3131
/// - scheme: URL scheme (e.g. "https").
3232
/// - host: The host (e.g. "api.example.com").
33+
/// - port: The port of the server, if any (e.g. `8080`).
3334
/// - path: The URL path (e.g. "/v1/resource").
3435
/// - headers: Initial headers.
3536
/// - body: The request body.
3637
public init(
3738
method: Method,
3839
scheme: String = "https",
3940
host: String? = nil,
41+
port: Int? = nil,
4042
path: String,
4143
headers: [String: String] = [:],
4244
body: HTTPBody = EmptyBody()
@@ -47,6 +49,7 @@ public struct HTTPRequest: Sendable {
4749

4850
urlComponents.scheme = scheme
4951
urlComponents.host = host
52+
urlComponents.port = port
5053
urlComponents.path = path
5154
}
5255

@@ -93,6 +96,18 @@ extension HTTPRequest {
9396
set { urlComponents.host = newValue }
9497
}
9598

99+
/// The URL scheme for this request.
100+
public var scheme: String? {
101+
get { urlComponents.scheme }
102+
set { urlComponents.scheme = newValue }
103+
}
104+
105+
/// The port component of the URL.
106+
public var port: Int? {
107+
get { urlComponents.port }
108+
set { urlComponents.port = newValue }
109+
}
110+
96111
/// The path component of the URL.
97112
public var path: String {
98113
get { urlComponents.path }

Sources/Modules/Sauce/Handlers/ServerEnvironmentHandler.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,14 @@ public struct ServerEnvironmentHandler: HTTPHandler {
3737
requestCopy.host = environment.host
3838
}
3939

40+
if requestCopy.port == nil {
41+
requestCopy.port = environment.port
42+
}
43+
44+
if let customScheme = environment.scheme {
45+
requestCopy.scheme = customScheme
46+
}
47+
4048
if requestCopy.path.hasPrefix("/") == false {
4149
let pathSeparator = environment.pathPrefix.hasSuffix("/") ? "" : "/"
4250
requestCopy.path = environment.pathPrefix + pathSeparator + requestCopy.path

Sources/Modules/Sauce/Options/ServerEnvironment.swift

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,22 +18,35 @@ public struct ServerEnvironment: Sendable {
1818

1919
/// Default headers to include on every request.
2020
public var headers: [String: String]
21+
22+
/// Optional URL scheme to override on requests.
23+
public var scheme: String?
24+
25+
/// Optional port to use for the server.
26+
public var port: Int?
27+
2128

2229
/// Initializes a new environment.
2330
///
2431
/// - Parameters:
2532
/// - host: The server host.
2633
/// - pathPrefix: A path segment to prepend.
34+
/// - scheme: The URL scheme to override, if any.
35+
/// - port: The port to use for the server, if any.
2736
/// - headers: Default headers.
2837
public init(
2938
host: String,
3039
pathPrefix: String = "/",
40+
scheme: String? = nil,
41+
port: Int? = nil,
3142
headers: [String: String] = [:]
3243
) {
3344
let prefix = pathPrefix.hasPrefix("/") ? "" : "/"
3445

3546
self.host = host
3647
self.pathPrefix = prefix + pathPrefix
48+
self.scheme = scheme
49+
self.port = port
3750
self.headers = headers
3851
}
3952
}

Tests/SimpleHTTPTests/Sauce/Handlers/ServerEnvironmentHandlerTests.swift

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,41 @@ struct ServerEnvironmentHandlerTests {
4242
let url = try #require(sentRequest.url)
4343
#expect(url.absoluteString == "https://api.example.com/v1/users")
4444
}
45+
46+
@Test("Injects localhost environment")
47+
func testLocalhostEnvironmentInjection() async throws {
48+
let environment = ServerEnvironment(
49+
host: "localhost",
50+
pathPrefix: "/v1",
51+
scheme: "http",
52+
port: 8080,
53+
headers: ["Accept": "application/json"]
54+
)
55+
56+
let responseHandler = MockHTTPHandler { request in
57+
.mock(request: request)
58+
}
59+
60+
let environmentHandler = ServerEnvironmentHandler(
61+
environment: environment,
62+
nextHandler: responseHandler
63+
)
64+
65+
let request = HTTPRequest(
66+
method: .get,
67+
path: "users"
68+
)
69+
70+
let result = try await environmentHandler.handle(request: request)
71+
let sentRequest = result.request
72+
73+
#expect(sentRequest.host == environment.host)
74+
#expect(sentRequest.path == "/v1/users")
75+
#expect(sentRequest.headers["Accept"] == "application/json")
76+
#expect(sentRequest.port == environment.port)
77+
#expect(sentRequest.scheme == environment.scheme)
78+
79+
let url = try #require(sentRequest.url)
80+
#expect(url.absoluteString == "http://localhost:8080/v1/users")
81+
}
4582
}

0 commit comments

Comments
 (0)