Skip to content

Commit 2c76df2

Browse files
committed
nonisolated pattern matching
1 parent f6b72be commit 2c76df2

File tree

2 files changed

+88
-7
lines changed

2 files changed

+88
-7
lines changed

FlyingFox/Sources/HTTPRoute.swift

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,9 +194,15 @@ public extension HTTPRoute {
194194
fatalError()
195195
}
196196

197+
#if compiler(>=6.2)
198+
nonisolated(nonsending) static func ~= (route: HTTPRoute, request: HTTPRequest) async -> Bool {
199+
await route.patternMatch(request: request)
200+
}
201+
#else
197202
static func ~= (route: HTTPRoute, request: HTTPRequest) async -> Bool {
198203
await route.patternMatch(request: request)
199204
}
205+
#endif
200206
}
201207

202208
private extension HTTPRoute {
@@ -224,13 +230,23 @@ private extension HTTPRoute {
224230
return nil
225231
}
226232

233+
#if compiler(>=6.2)
234+
nonisolated(nonsending) func patternMatch(request: HTTPRequest) async -> Bool {
235+
guard patternMatch(query: request.query),
236+
patternMatch(headers: request.headers),
237+
await patternMatch(body: request.bodySequence) else { return false }
238+
239+
return patternMatch(method: request.method, path: request.path)
240+
}
241+
#else
227242
func patternMatch(request: HTTPRequest) async -> Bool {
228243
guard patternMatch(query: request.query),
229244
patternMatch(headers: request.headers),
230245
await patternMatch(body: request.bodySequence) else { return false }
231246

232247
return patternMatch(method: request.method, path: request.path)
233248
}
249+
#endif
234250

235251
func patternMatch(method: HTTPMethod, path: String) -> Bool {
236252
guard self.methods.contains(method) else {
@@ -265,6 +281,22 @@ private extension HTTPRoute {
265281
}
266282
}
267283

284+
#if compiler(>=6.2)
285+
nonisolated(nonsending) func patternMatch(body request: HTTPBodySequence) async -> Bool {
286+
guard let body = body else { return true }
287+
288+
guard request.canReplay else {
289+
// body is large and can only be iterated one-time only so should not match it
290+
return false
291+
}
292+
293+
do {
294+
return try await body.evaluate(request.get())
295+
} catch {
296+
return false
297+
}
298+
}
299+
#else
268300
func patternMatch(body request: HTTPBodySequence) async -> Bool {
269301
guard let body = body else { return true }
270302

@@ -279,6 +311,7 @@ private extension HTTPRoute {
279311
return false
280312
}
281313
}
314+
#endif
282315

283316
static func components(for target: String) -> (
284317
methods: Set<HTTPMethod>,

FlyingFox/Sources/Handlers/RoutedHTTPHandler.swift

Lines changed: 55 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -78,13 +78,35 @@ public struct RoutedHTTPHandler: HTTPHandler, Sendable {
7878
insert((route, ClosureHTTPHandler(handler)), at: index)
7979
}
8080

81+
#if compiler(>=6.2)
82+
nonisolated(nonsending) public func handleRequest(_ request: HTTPRequest) async throws -> HTTPResponse {
83+
for entry in handlers {
84+
do {
85+
if let response = try await Self.handleMatchedRequest(
86+
request,
87+
to: entry.route,
88+
handler: entry.handler.handleRequest
89+
) {
90+
return response
91+
}
92+
} catch is HTTPUnhandledError {
93+
continue
94+
} catch {
95+
throw error
96+
}
97+
}
98+
throw HTTPUnhandledError()
99+
}
100+
#else
81101
public func handleRequest(_ request: HTTPRequest) async throws -> HTTPResponse {
82102
for entry in handlers {
83103
do {
84-
if await entry.route ~= request {
85-
return try await HTTPRequest.$matchedRoute.withValue(entry.route) {
86-
return try await entry.handler.handleRequest(request)
87-
}
104+
if let response = try await Self.handleMatchedRequest(
105+
request,
106+
to: entry.route,
107+
handler: entry.handler.handleRequest
108+
) {
109+
return response
88110
}
89111
} catch is HTTPUnhandledError {
90112
continue
@@ -94,6 +116,7 @@ public struct RoutedHTTPHandler: HTTPHandler, Sendable {
94116
}
95117
throw HTTPUnhandledError()
96118
}
119+
#endif
97120
}
98121

99122
public extension RoutedHTTPHandler {
@@ -136,9 +159,21 @@ public extension RoutedHTTPHandler {
136159
}
137160
}
138161

139-
#if compiler(>=6.0)
140162
public extension RoutedHTTPHandler {
141-
163+
#if compiler(>=6.2)
164+
nonisolated(nonsending) static func handleMatchedRequest(
165+
_ request: HTTPRequest,
166+
to route: HTTPRoute,
167+
handler: (HTTPRequest) async throws -> HTTPResponse
168+
) async throws -> HTTPResponse? {
169+
if await route ~= request {
170+
return try await HTTPRequest.$matchedRoute.withValue(route) {
171+
return try await handler(request)
172+
}
173+
}
174+
return nil
175+
}
176+
#elseif compiler(>=6.0)
142177
static func handleMatchedRequest(
143178
isolation: isolated (any Actor)? = #isolation,
144179
_ request: HTTPRequest,
@@ -153,8 +188,21 @@ public extension RoutedHTTPHandler {
153188
}
154189
return nil
155190
}
156-
}
191+
#else
192+
static func handleMatchedRequest(
193+
_ request: HTTPRequest,
194+
to route: HTTPRoute,
195+
handler: (HTTPRequest) async throws -> HTTPResponse
196+
) async throws -> HTTPResponse? {
197+
if await route ~= request {
198+
return try await HTTPRequest.$matchedRoute.withValue(route) {
199+
return try await handler(request)
200+
}
201+
}
202+
return nil
203+
}
157204
#endif
205+
}
158206

159207
extension RoutedHTTPHandler: RangeReplaceableCollection {
160208
public typealias Index = Array<Element>.Index

0 commit comments

Comments
 (0)