diff --git a/Package.swift b/Package.swift index bf3fc0d..f478d87 100644 --- a/Package.swift +++ b/Package.swift @@ -3,10 +3,10 @@ import PackageDescription let package = Package( - name: "DGPerfectMiddleware", + name: "PerfectMiddleware", dependencies: [ .Package(url: "https://github.com/PerfectlySoft/Perfect-HTTPServer.git", majorVersion: 2, - minor: 1) + minor: 2) ] ) diff --git a/README.md b/README.md index 0cdddf5..cd12509 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -DGPerfectMiddleware +PerfectMiddleware ================================= [![Twitter](https://img.shields.io/badge/twitter-@Digipolitan-blue.svg?style=flat)](http://twitter.com/Digipolitan) @@ -9,7 +9,7 @@ Perfect middleware swift allows developer to register middlewares inside a Perfe ### Swift Package Manager -To install DGPerfectMiddleware with SPM, add the following lines to your `Package.swift`. +To install PerfectMiddleware with SPM, add the following lines to your `Package.swift`. ```swift import PackageDescription @@ -160,4 +160,4 @@ unacceptable behavior to [contact@digipolitan.com](mailto:contact@digipolitan.co ## License -DGPerfectMiddleware is licensed under the [BSD 3-Clause license](LICENSE). +PerfectMiddleware is licensed under the [BSD 3-Clause license](LICENSE). diff --git a/Sources/Middleware.swift b/Sources/Middleware.swift index 3e469d4..ca9670d 100644 --- a/Sources/Middleware.swift +++ b/Sources/Middleware.swift @@ -1,6 +1,6 @@ // // Middleware.swift -// DGPerfectMiddleware +// PerfectMiddleware // // Created by Benoit BRIATTE on 17/04/2017. // diff --git a/Sources/MiddlewareIterator.swift b/Sources/MiddlewareIterator.swift index b7aeaf9..dc1f765 100644 --- a/Sources/MiddlewareIterator.swift +++ b/Sources/MiddlewareIterator.swift @@ -1,6 +1,6 @@ // // MiddlewareIterator.swift -// DGPerfectMiddleware +// PerfectMiddleware // // Created by Benoit BRIATTE on 20/04/2017. // @@ -10,7 +10,7 @@ import PerfectHTTP /** * Internal RouteContext implementation - * This implementation iterate over all middleware one by one + * This implementation iterate over all middlewares one by one * @author Benoit BRIATTE http://www.digipolitan.com * @copyright 2017 Digipolitan. All rights reserved. */ @@ -24,7 +24,7 @@ class MiddlewareIterator: RouteContext { private var userInfo: [String: Any] private var current: Int - public init(request: HTTPRequest, response: HTTPResponse, middlewares: [Middleware], errorHandler: ErrorHandler? = nil) { + public init(request: HTTPRequest, response: HTTPResponse, middlewares: [Middleware], errorHandler: ErrorHandler?) { self.request = request self.response = response self.middlewares = middlewares diff --git a/Sources/MiddlewareWrapper.swift b/Sources/MiddlewareWrapper.swift index a73af65..efd73bd 100644 --- a/Sources/MiddlewareWrapper.swift +++ b/Sources/MiddlewareWrapper.swift @@ -1,6 +1,6 @@ // // MiddlewareWrapper.swift -// DGPerfectMiddleware +// PerfectMiddleware // // Created by Benoit BRIATTE on 17/04/2017. // diff --git a/Sources/RouteContext.swift b/Sources/RouteContext.swift index 44febff..9793c06 100644 --- a/Sources/RouteContext.swift +++ b/Sources/RouteContext.swift @@ -1,6 +1,6 @@ // // RouteContext.swift -// DGPerfectMiddleware +// PerfectMiddleware // // Created by Benoit BRIATTE on 17/04/2017. // diff --git a/Sources/RouterMiddleware.swift b/Sources/RouterMiddleware.swift index ee3a15c..4258269 100644 --- a/Sources/RouterMiddleware.swift +++ b/Sources/RouterMiddleware.swift @@ -1,11 +1,12 @@ // // RouterMiddleware.swift -// DGPerfectMiddleware +// PerfectMiddleware // // Created by Benoit BRIATTE on 20/04/2017. // // +import PerfectLib import PerfectHTTP import PerfectHTTPServer @@ -34,12 +35,18 @@ open class RouterMiddleware { private var children: [String: RouterMiddleware] private var registry: RoutesRegistry private var errorHandler: ErrorHandler? + private var verbose: Bool; - public init() { + public convenience init() { + self.init(verbose: false) + } + + public init(verbose: Bool) { self.beforeAll = [Middleware]() self.afterAll = [Middleware]() self.children = [String: RouterMiddleware]() self.registry = RoutesRegistry() + self.verbose = verbose } @discardableResult @@ -68,7 +75,7 @@ open class RouterMiddleware { @discardableResult public func use(path: String, router: RouterMiddleware) -> Self { - self.children[path] = router + self.children[RoutesRegistry.sanitize(path: path)] = router return self } @@ -140,18 +147,21 @@ open class RouterMiddleware { return self } - fileprivate func getRoutes(path: String = "", beforeAll: [Middleware] = [], afterAll: [Middleware] = [], notFound: Middleware? = nil, errorHandler: ErrorHandler? = nil) -> Routes { + fileprivate func getRoutes(path: String = "", beforeAll: [Middleware] = [], afterAll: [Middleware] = [], verbose: Bool = false, errorHandler: ErrorHandler? = nil) -> Routes { var routes = Routes(baseUri: path) let depthBeforeAll = beforeAll + self.beforeAll - let depthAfterAll = afterAll + self.afterAll + let depthAfterAll = self.afterAll + afterAll let curErrorHandler = (self.errorHandler != nil) ? self.errorHandler : errorHandler - let curNotFound = (self.notFound != nil) ? self.notFound : notFound + let curVerbose = (verbose == true) ? verbose : self.verbose self.registry.routes.forEach { (method: HTTPMethod, value: [String : [Middleware]]) in value.forEach({ (key: String, value: [Middleware]) in let middlewares = depthBeforeAll + value + depthAfterAll + if curVerbose { + Log.info(message: "HTTP Server listen \(method.description) on \(path)\(key)") + } routes.add(method: method, uri: key, handler: { request, response in MiddlewareIterator(request: request, response: response, @@ -161,22 +171,23 @@ open class RouterMiddleware { }) } - let filePathComponents = path.filePathComponents self.children.forEach { (key: String, value: RouterMiddleware) in - let childComponents = key.filePathComponents - let components = filePathComponents + childComponents - routes.add(value.getRoutes(path: components.joined(separator: "/"), - beforeAll: depthBeforeAll, - afterAll: depthAfterAll, - notFound: curNotFound, - errorHandler: curErrorHandler)) + routes.add(value.getRoutes(path: path + key, + beforeAll: depthBeforeAll, + afterAll: depthAfterAll, + verbose: curVerbose, + errorHandler: curErrorHandler + )) } - if let notFound = curNotFound { + if let notFound = self.notFound { var notFoundMiddlewares = depthBeforeAll notFoundMiddlewares.append(notFound) notFoundMiddlewares.append(contentsOf: depthAfterAll) - routes.add(uri: "/**", handler: { request, response in + if curVerbose { + Log.info(message: "HTTP Server listen 404 from " + (path == "" ? "/" : path)); + } + routes.add(uri: "**", handler: { request, response in MiddlewareIterator(request: request, response: response, middlewares: notFoundMiddlewares, @@ -195,7 +206,6 @@ public extension HTTPServer { } } - fileprivate class RoutesRegistry { fileprivate private(set) var routes: [HTTPMethod: [String: [Middleware]]] @@ -205,12 +215,30 @@ fileprivate class RoutesRegistry { } public func add(method: HTTPMethod, path: String, middleware: Middleware) { + let sanitizePath = RoutesRegistry.sanitize(path: path) if self.routes[method] == nil { self.routes[method] = [String: [Middleware]]() } - if self.routes[method]![path] == nil { - self.routes[method]![path] = [Middleware]() + if self.routes[method]![sanitizePath] == nil { + self.routes[method]![sanitizePath] = [Middleware]() + } + self.routes[method]![sanitizePath]!.append(middleware) + } + + static fileprivate func sanitize(path: String) -> String { + var characters = path.characters + guard characters.count > 0 && path != "/" else { + return "/" + } + let last = characters.endIndex + let separator = Character(UnicodeScalar(47)) + if characters[characters.index(before: last)] == separator { + characters.removeLast() + } + let first = characters.startIndex + if characters[first] != separator { + characters.insert(separator, at: first) } - self.routes[method]![path]!.append(middleware) + return String(characters) } } diff --git a/Tests/DGPerfectMiddlewareTests/DGPerfectMiddlewareTests.swift b/Tests/PerfectMiddlewareTests/PerfectMiddlewareTests.swift similarity index 64% rename from Tests/DGPerfectMiddlewareTests/DGPerfectMiddlewareTests.swift rename to Tests/PerfectMiddlewareTests/PerfectMiddlewareTests.swift index 24d8ff7..45959d4 100644 --- a/Tests/DGPerfectMiddlewareTests/DGPerfectMiddlewareTests.swift +++ b/Tests/PerfectMiddlewareTests/PerfectMiddlewareTests.swift @@ -1,7 +1,7 @@ import XCTest -@testable import DGPerfectMiddleware +@testable import PerfectMiddleware -class DGPerfectMiddlewareTests: XCTestCase { +class PerfectMiddlewareTests: XCTestCase { func testExample() { XCTAssertTrue(true) }