/
ApplicationResponder.swift
77 lines (67 loc) 路 2.43 KB
/
ApplicationResponder.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
extension Application {
public var responder: Responder {
ApplicationResponder(
routes: self.routes,
middleware: self.middleware.resolve()
)
}
}
/// Vapor's main `Responder` type. Combines configured middleware + router to create a responder.
internal struct ApplicationResponder: Responder {
private let responder: Responder
/// Creates a new `ApplicationResponder`.
public init(routes: Routes, middleware: [Middleware] = []) {
let router = RoutesResponder(routes: routes)
self.responder = middleware.makeResponder(chainingTo: router)
}
/// See `Responder`.
public func respond(to request: Request) -> EventLoopFuture<Response> {
request.logger.info("\(request.method) \(request.url.path)")
return self.responder.respond(to: request)
.hop(to: request.eventLoop)
}
}
// MARK: Private
/// Converts a `Router` into a `Responder`.
internal struct RoutesResponder: Responder {
private let router: TrieRouter<Responder>
/// Creates a new `RouterResponder`.
init(routes: Routes) {
let router = TrieRouter(Responder.self)
for route in routes.all {
// remove any empty path components
let path = route.path.filter { component in
switch component {
case .constant(let string):
return string != ""
default:
return true
}
}
let route = RoutingKit.Route<Responder>(
path: [.constant(route.method.string)] + path,
output: route.responder
)
router.register(route: route)
}
self.router = router
}
/// See `Responder`.
func respond(to request: Request) -> EventLoopFuture<Response> {
guard let responder = self.route(request) else {
return request.eventLoop.makeFailedFuture(Abort(.notFound))
}
return responder.respond(to: request)
}
/// See `Router`.
private func route(_ request: Request) -> Responder? {
let pathComponents = request.url.path
.split(separator: "/")
.map(String.init)
let method = (request.method == .HEAD) ? .GET : request.method
return self.router.route(
path: [method.string] + pathComponents,
parameters: &request.parameters
)
}
}