Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions Sources/Modules/Core/HTTPRequest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,15 @@ public struct HTTPRequest: Sendable {
/// - method: The HTTP method.
/// - scheme: URL scheme (e.g. "https").
/// - host: The host (e.g. "api.example.com").
/// - port: The port of the server, if any (e.g. `8080`).
/// - path: The URL path (e.g. "/v1/resource").
/// - headers: Initial headers.
/// - body: The request body.
public init(
method: Method,
scheme: String = "https",
host: String? = nil,
port: Int? = nil,
path: String,
headers: [String: String] = [:],
body: HTTPBody = EmptyBody()
Expand All @@ -47,6 +49,7 @@ public struct HTTPRequest: Sendable {

urlComponents.scheme = scheme
urlComponents.host = host
urlComponents.port = port
urlComponents.path = path
}

Expand Down Expand Up @@ -93,6 +96,18 @@ extension HTTPRequest {
set { urlComponents.host = newValue }
}

/// The URL scheme for this request.
public var scheme: String? {
get { urlComponents.scheme }
set { urlComponents.scheme = newValue }
}

/// The port component of the URL.
public var port: Int? {
get { urlComponents.port }
set { urlComponents.port = newValue }
}

/// The path component of the URL.
public var path: String {
get { urlComponents.path }
Expand Down
8 changes: 8 additions & 0 deletions Sources/Modules/Sauce/Handlers/ServerEnvironmentHandler.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,14 @@ public struct ServerEnvironmentHandler: HTTPHandler {
requestCopy.host = environment.host
}

if requestCopy.port == nil {
requestCopy.port = environment.port
}

if let customScheme = environment.scheme {
requestCopy.scheme = customScheme
}

if requestCopy.path.hasPrefix("/") == false {
let pathSeparator = environment.pathPrefix.hasSuffix("/") ? "" : "/"
requestCopy.path = environment.pathPrefix + pathSeparator + requestCopy.path
Expand Down
13 changes: 13 additions & 0 deletions Sources/Modules/Sauce/Options/ServerEnvironment.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,35 @@ public struct ServerEnvironment: Sendable {

/// Default headers to include on every request.
public var headers: [String: String]

/// Optional URL scheme to override on requests.
public var scheme: String?

/// Optional port to use for the server.
public var port: Int?


/// Initializes a new environment.
///
/// - Parameters:
/// - host: The server host.
/// - pathPrefix: A path segment to prepend.
/// - scheme: The URL scheme to override, if any.
/// - port: The port to use for the server, if any.
/// - headers: Default headers.
public init(
host: String,
pathPrefix: String = "/",
scheme: String? = nil,
port: Int? = nil,
headers: [String: String] = [:]
) {
let prefix = pathPrefix.hasPrefix("/") ? "" : "/"

self.host = host
self.pathPrefix = prefix + pathPrefix
self.scheme = scheme
self.port = port
self.headers = headers
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,41 @@ struct ServerEnvironmentHandlerTests {
let url = try #require(sentRequest.url)
#expect(url.absoluteString == "https://api.example.com/v1/users")
}

@Test("Injects localhost environment")
func testLocalhostEnvironmentInjection() async throws {
let environment = ServerEnvironment(
host: "localhost",
pathPrefix: "/v1",
scheme: "http",
port: 8080,
headers: ["Accept": "application/json"]
)

let responseHandler = MockHTTPHandler { request in
.mock(request: request)
}

let environmentHandler = ServerEnvironmentHandler(
environment: environment,
nextHandler: responseHandler
)

let request = HTTPRequest(
method: .get,
path: "users"
)

let result = try await environmentHandler.handle(request: request)
let sentRequest = result.request

#expect(sentRequest.host == environment.host)
#expect(sentRequest.path == "/v1/users")
#expect(sentRequest.headers["Accept"] == "application/json")
#expect(sentRequest.port == environment.port)
#expect(sentRequest.scheme == environment.scheme)

let url = try #require(sentRequest.url)
#expect(url.absoluteString == "http://localhost:8080/v1/users")
}
}