Skip to content

Commit

Permalink
Make url scheme and host match and register case insensitive (#222)
Browse files Browse the repository at this point in the history
Currently the mapping and register of url routes are case sensitive
The RFC-3986 states that theses routes should be case insensitive

- Add case insensitive url routes mapping and register logic
- Add UnitTests to test, said logic
- Conform to RFC-3986
  • Loading branch information
JOCuendet authored and jonathan Cuendet committed Oct 23, 2020
1 parent 538f770 commit ae73565
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 11 deletions.
10 changes: 6 additions & 4 deletions Sources/DeepLinking/Route+TrieRouter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -178,8 +178,9 @@ extension Route {
private func parseAnnotatedRoute(_ route: URL) throws -> [Route.Component] {

// use a wildcard for empty schemes/hosts, to match any scheme/host
let schemeComponent = route.scheme.constantOrWildcardComponent
let hostComponent = route.host.constantOrWildcardComponent
// URL scheme and host comparison should be case insensitive in conformance to RFC-3986
let schemeComponent = (route.scheme?.lowercased()).constantOrWildcardComponent
let hostComponent = (route.host?.lowercased()).constantOrWildcardComponent

do {
let pathComponents = try route.pathComponents.filter { $0 != "/" }.map(Route.Component.init(component:))
Expand All @@ -204,8 +205,9 @@ extension Route {
private func parseMatchRoute(_ route: URL) throws -> MatchRoute {

// use an empty string for empty scheme/host, to match wildcard scheme/host
let schemeComponent = route.scheme ?? ""
let hostComponent = route.host ?? ""
// URL scheme and host comparison should be case insensitive in conformance to RFC-3986
let schemeComponent = route.scheme?.lowercased() ?? ""
let hostComponent = route.host?.lowercased() ?? ""
let pathComponents = route.pathComponents.filter { $0 != "/" }

let routeComponents = [schemeComponent, hostComponent] + pathComponents
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,22 +57,22 @@ class Route_TrieRouter_DescriptionTests: XCTestCase {
XCTAssertEqual(
router.description,
"""
├──┬ schemeB
│ ├──┬ hostB
├──┬ schemeb
│ ├──┬ hosta
│ │ └──● AnyRouteHandler<String>(P)
│ │
│ ├──┬ hostb
│ │ └──┬ path
│ │ ├──┬ *
│ │ │ └──● AnyRouteHandler<String>(R)
│ │ │
│ │ └──● AnyRouteHandler<String>(Q)
│ │
│ ├──┬ hostA
│ │ └──● AnyRouteHandler<String>(P)
│ │
│ └──┬ *
│ └──● AnyRouteHandler<String>(O)
├──┬ schemeA
│ ├──┬ hostC
├──┬ schemea
│ ├──┬ hostc
│ │ └──┬ *
│ │ └──┬ yet
│ │ └──┬ another
Expand Down
22 changes: 22 additions & 0 deletions Tests/AlicerceTests/DeepLinking/Route+TrieRouter_RouteTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,18 @@ class Route_TrieRouter_RouteTests: XCTestCase {
XCTAssertRouteSucceeds(initial: [("/", testHandler)], route: "://")
}

func testRoute_WithCaseInsensitiveMatchingScheme_ShouldSucceed() {
XCTAssertRouteSucceeds(initial: [("HTTP://", testHandler)], route: "http://")
XCTAssertRouteSucceeds(initial: [("HTTP://host/", testHandler)], route: "http://host/")
XCTAssertRouteSucceeds(initial: [("HTTP://host/path", testHandler)], route: "http://host/path")
XCTAssertRouteSucceeds(initial: [("HtTp://host/path", testHandler)], route: "http://host/path")

XCTAssertRouteSucceeds(initial: [("http://", testHandler)], route: "HTTP://")
XCTAssertRouteSucceeds(initial: [("http://host/", testHandler)], route: "HTTP://host/")
XCTAssertRouteSucceeds(initial: [("http://host/path", testHandler)], route: "HTTP://host/path")
XCTAssertRouteSucceeds(initial: [("http://host/path", testHandler)], route: "httP://host/path")
}

// MARK: host

func testRoute_WithMatchingHost_ShouldSucceed() {
Expand Down Expand Up @@ -163,6 +175,16 @@ class Route_TrieRouter_RouteTests: XCTestCase {
XCTAssertRouteSucceeds(initial: [("/", testHandler)], route: ":///")
}

func testRoute_WithCaseInsensitiveMatchingHost_ShouldSucceed() {
XCTAssertRouteSucceeds(initial: [("http://HOST/", testHandler)], route: "http://host/")
XCTAssertRouteSucceeds(initial: [("http://HOST/path", testHandler)], route: "http://host/path")
XCTAssertRouteSucceeds(initial: [("http://HosT/path", testHandler)], route: "http://host/path")

XCTAssertRouteSucceeds(initial: [("http://host/", testHandler)], route: "http://HOST/")
XCTAssertRouteSucceeds(initial: [("http://host/path", testHandler)], route: "http://HOST/path")
XCTAssertRouteSucceeds(initial: [("http://host/path", testHandler)], route: "http://hOSt/path")
}

// MARK: single level path

func testRoute_WithMatchingSingleLevelPath_ShouldSucceed() {
Expand Down

0 comments on commit ae73565

Please sign in to comment.