From 063746edb699caa116ccacdb7989273fa51df6c1 Mon Sep 17 00:00:00 2001 From: Logan Wright Date: Tue, 7 Mar 2017 22:22:59 +0100 Subject: [PATCH 1/2] update options support --- Sources/Branches/Branch+Paths.swift | 6 ++++ Sources/Routing/RouteBuilder.swift | 1 + Sources/Routing/Router+Responder.swift | 50 +++++++++++++++++++++++++- Tests/RoutingTests/RouteTests.swift | 2 +- Tests/RoutingTests/RouterTests.swift | 4 +-- Tests/RoutingTests/Utilities.swift | 2 +- 6 files changed, 60 insertions(+), 5 deletions(-) diff --git a/Sources/Branches/Branch+Paths.swift b/Sources/Branches/Branch+Paths.swift index 9373f288..69acd03a 100644 --- a/Sources/Branches/Branch+Paths.swift +++ b/Sources/Branches/Branch+Paths.swift @@ -20,6 +20,12 @@ extension Branch { } } +extension Branch { + public var allSubBranches: [Branch] { + return subBranches.allBranches + } +} + extension Branch { // The individual route leading to the calling branch internal var route: String { diff --git a/Sources/Routing/RouteBuilder.swift b/Sources/Routing/RouteBuilder.swift index 4e696b33..f1e347b0 100644 --- a/Sources/Routing/RouteBuilder.swift +++ b/Sources/Routing/RouteBuilder.swift @@ -24,6 +24,7 @@ extension RouteBuilder { register(host: nil, method: method, path: path, responder: responder) } + // FIXME: This function feels like it might not fit public func add( _ method: HTTP.Method, _ path: String ..., diff --git a/Sources/Routing/Router+Responder.swift b/Sources/Routing/Router+Responder.swift index 0ffe5a23..04706448 100644 --- a/Sources/Routing/Router+Responder.swift +++ b/Sources/Routing/Router+Responder.swift @@ -1,11 +1,59 @@ import HTTP +import Branches import Debugging +extension HTTP.Method { + static let standard: [Method] = [.get, .post, .put, .patch, .delete] +} + +public var supportOptionsRequests = true + extension Router: Responder { public func respond(to request: Request) throws -> Response { - guard let responder = route(request) else { throw RouterError.missingRoute(for: request) } + guard let responder = route(request) else { return try fallbackResponse(for: request) } return try responder.respond(to: request) } + + private func fallbackResponse(for request: Request) throws -> Response { + guard supportOptionsRequests, request.method == .options else { throw RouterError.missingRoute(for: request) } + return options(for: request) + } + + private func options(for request: Request) -> Response { + let opts = supportedMethods(for: request) + .map { $0.description } + .joined(separator: ", ") + return Response(status: .ok, headers: ["Allow": opts]) + } + + private func supportedMethods(for request: Request) -> [Method] { + let request = request.copy() + let host = self.host(for: request.uri.host) + let allOptions = host.allSubBranches + let allPossibleMethods = allOptions.map { Method($0.name) } + return allPossibleMethods.filter { method in + request.method = method + return route(request) != nil + } + } + + private func host(for host: String) -> Branch { + // FIXME: RM ! + return base.fetch([host])! + } +} + +extension Request { + public func copy() -> Request { + return Request( + method: method, + uri: uri, + version: version, + headers: headers, + body: body, + peerAddress: peerAddress + ) + } } public enum RouterError: Debuggable { diff --git a/Tests/RoutingTests/RouteTests.swift b/Tests/RoutingTests/RouteTests.swift index 58358316..2563d945 100644 --- a/Tests/RoutingTests/RouteTests.swift +++ b/Tests/RoutingTests/RouteTests.swift @@ -46,7 +46,7 @@ class RouteTests: XCTestCase { query: nil, fragment: nil ) - let request = try Request(method: .get, uri: uri) + let request = Request(method: .get, uri: uri) let response = try router.respond(to: request) XCTAssertEqual(response.body.bytes?.string, path.prefix(3).joined(separator: ":")) } diff --git a/Tests/RoutingTests/RouterTests.swift b/Tests/RoutingTests/RouterTests.swift index c9e576da..31560e2c 100644 --- a/Tests/RoutingTests/RouterTests.swift +++ b/Tests/RoutingTests/RouterTests.swift @@ -141,7 +141,7 @@ class RouterTests: XCTestCase { let empties: [String] = ["", "/"] try empties.forEach { emptypath in let uri = URI(scheme: "http", host: "0.0.0.0", path: emptypath) - let request = try Request(method: .get, uri: uri) + let request = Request(method: .get, uri: uri) let response = try router.respond(to: request) XCTAssertEqual(response.body.bytes?.string, "Hello, Empty!") } @@ -157,7 +157,7 @@ class RouterTests: XCTestCase { scheme: "", host: "" ) - let request = try Request(method: .get, uri: uri) + let request = Request(method: .get, uri: uri) let response = try router.respond(to: request) XCTAssertEqual(response.body.bytes?.string, "Hello, World!") } diff --git a/Tests/RoutingTests/Utilities.swift b/Tests/RoutingTests/Utilities.swift index 8748d0c0..f61db71f 100644 --- a/Tests/RoutingTests/Utilities.swift +++ b/Tests/RoutingTests/Utilities.swift @@ -6,7 +6,7 @@ import URI extension Request { convenience init(method: HTTP.Method, path: String, host: String = "0.0.0.0") { let uri = URI(host: host, path: path) - try! self.init(method: method, uri: uri) + self.init(method: method, uri: uri) } enum BytesError: Error { From efe56ac9ae2b744225a922176b5377b0052c0efd Mon Sep 17 00:00:00 2001 From: Logan Wright Date: Tue, 7 Mar 2017 22:25:01 +0100 Subject: [PATCH 2/2] rm unused --- Sources/Routing/Router+Responder.swift | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Sources/Routing/Router+Responder.swift b/Sources/Routing/Router+Responder.swift index 04706448..4f5059f0 100644 --- a/Sources/Routing/Router+Responder.swift +++ b/Sources/Routing/Router+Responder.swift @@ -2,10 +2,6 @@ import HTTP import Branches import Debugging -extension HTTP.Method { - static let standard: [Method] = [.get, .post, .put, .patch, .delete] -} - public var supportOptionsRequests = true extension Router: Responder {