Spend less time writing custom URL matching and parsing logic. Define any URL format you support using a single string, and let Corridor do the heavy lifting.
Suppose you want to handle a user-profile universal-link like: https://example.com/user/15127128.
(1) Create a route – a Codable struct that contains all the values you want to extract from the URL. Once the URL is matched, the userId will have a value of 15127128
struct ViewUserProfile: CorridorRoute {
let userId: Int
}
ViewUserProfile is the struct that we defined in the first example
"/user/:userId{int}" is the URL format. It matches URLs that start with /user and have an integer value after.
{ try corridorResponse($0, ViewUserProfile.self) } is a block that populates the route ViewUserProfile if the URL is matched.
URL format
A URL format is split into a path and a query:
Path: includes all the URL values separated by “/“
Query: all the key-value pairs after the URL’s last “/“
URL formats must start with a forward slash “/“
Formatting the path
Suppose you want to match URLs in the form /user/12891, that start with user and end with a number.
The URL format for this is: "/user/:userId{int}", where the number after user is represented as :userId{int}.
Each param you want to extract follows the form :paramName{baseType} or :paramName.
paramName is the same name as a variable in the route
baseType indicates the type of paramName
So :userId without an explicit base type would map to let userId: String in a route, while :userId{int} would map to let userId: Int in a route.
URL definitions must start with a forward slash “/“
Base type ‘string’ maps to a String
Base type ‘int’ maps to a Int
Formatting the query
Suppose you want to match URLs in the form /user?userId=12891, that begin with a user path, and have a numeric userId value in the params.
The URL format for this is: "/user/?:userId{int}", where everything after ? is part of the query.
Optionals:
Now suppose that the userId value was optional, so /user&userId=12891 and /user would map to the same route.
The URL format for this is: "/user/?:userId{int?}"
Literals:
Now suppose that we wanted to match URLs in the form /user&userId=12891&sourceType=email, where the (‘sourceType’, ‘email’) pair was present in the query.
The URL format for this is: "/user/?:userId{int}&:sourceType{'email'}"
URL formats must separate consecutive query params with an ampersand ‘&’
Support custom base types
The URL definition "/user/:userId{int}?:nickname{string}" contains built-in base types: "int", "string", and "bool".
Each base type maps to a Swift type:
"int" -> Int
"string" -> String
"bool" -> Bool
Any base type can be enclosed by square brackets to represent a comma separated list of base values. Example: "[int]" -> [Int].
What if you want to use a base type that isn’t one of the built-in ones? Here’s an example:
(1) Define a base type named “uint” that converts values to UInt:
private struct CorridorTypeUInt: CorridorTypeProtocol {
let name = "uint"
func convertToType(from value: String) -> Any? {
return UInt(value)
}
}
Base type names must be alphabetic, and cannot be identical to any of the existing built-in base type names
(2) Instantiate CorridorTypes with the custom base type:
let baseTypes = CorridorTypes(customTypes: [CorridorTypeUInt()])
(3) Instantiate the router with the baseTypes
let router = CorridorRouter(corridorTypes: baseTypes)
Now, for the usage:
struct ViewUserProfile: CorridorRoute {
let userId: UInt
let nickname: String?
}
Corridor
Spend less time writing custom URL matching and parsing logic. Define any URL format you support using a single string, and let Corridor do the heavy lifting.
Suppose you want to handle a user-profile universal-link like:
https://example.com/user/15127128
.(1) Create a route – a Codable struct that contains all the values you want to extract from the URL. Once the URL is matched, the userId will have a value of
15127128
(2) Register the format:
"/user/:userId{int}"
Now, for the usage:
(3) Call
attemptMatch(_:URL)
with the urlhttps://example.com/user/15127128
to get a matched-response(4) Switch on the result’s
route
:15127128
Voila!Overview
See an example router that uses
Corridor
inside theExample
folderRoute
A struct that conforms to
CorridorRoute
. Its variables correspond to values contained in a URL. It’s created when a URL is matched.Router
Routers facilitate the process of matching a URL to a route:
Let’s register a type of URL:
"/user/:userId{int}"
is the URL format. It matches URLs that start with/user
and have an integer value after.{ try corridorResponse($0, ViewUserProfile.self) }
is a block that populates the routeViewUserProfile
if the URL is matched.URL format
A URL format is split into a path and a query:
Formatting the path
Suppose you want to match URLs in the form
/user/12891
, that start withuser
and end with a number.The URL format for this is:
"/user/:userId{int}"
, where the number afteruser
is represented as:userId{int}
.Each param you want to extract follows the form
:paramName{baseType}
or:paramName
.paramName
is the same name as a variable in the routebaseType
indicates the type ofparamName
So
:userId
without an explicit base type would map tolet userId: String
in a route, while:userId{int}
would map tolet userId: Int
in a route.Formatting the query
Suppose you want to match URLs in the form
/user?userId=12891
, that begin with auser
path, and have a numericuserId
value in the params.The URL format for this is:
"/user/?:userId{int}"
, where everything after?
is part of the query.Optionals:
Now suppose that the
userId
value was optional, so/user&userId=12891
and/user
would map to the same route.The URL format for this is:
"/user/?:userId{int?}"
Literals:
Now suppose that we wanted to match URLs in the form
/user&userId=12891&sourceType=email
, where the (‘sourceType’, ‘email’) pair was present in the query.The URL format for this is:
"/user/?:userId{int}&:sourceType{'email'}"
Support custom base types
The URL definition
"/user/:userId{int}?:nickname{string}"
contains built-in base types:"int"
,"string"
, and"bool"
. Each base type maps to a Swift type:"int" -> Int
"string" -> String
"bool" -> Bool
What if you want to use a base type that isn’t one of the built-in ones? Here’s an example:
(1) Define a base type named “uint” that converts values to UInt:
(2) Instantiate
CorridorTypes
with the custom base type:(3) Instantiate the router with the baseTypes
Now, for the usage:
(4) Call
attemptMatch(_:URL)
with the urlwww.example.com/8971/?nickname=Bob
8971
Voila!Match global query params
What if a query parameter such as a tracking id, or user id is contained in many of your URLs?
Suppose your URLs contained a query param
sourceUserId
to track the user who clicked on the URL.You could include
let sourceUserId: String?
in all your routes, but doing so is tedious and error-prone. CorridorGlobalParams to the rescue!(1) Create a struct that conforms to
CorridorGlobalParams
(2) Create a mapping
(3) Instantiate the router with the mapping
Now, for the usage:
(4) Call
attemptMatch(_:URL)
with the urlwww.example.com/news_feed/?sourceUserId=abc123
abc123
Voila!Installation
Corridor supports multiple methods for installing the library in a project.
CocoaPods
To integrate Corridor into your Xcode project using CocoaPods, specify it in your
Podfile
:Also include on a separate line in your
Podfile
:Carthage
To integrate Corridor into your Xcode project using Carthage, specify it in your
Cartfile
:Run
carthage
to build the framework and drag the builtCorridor.framework
into your Xcode project.Swift Package Manager
To integrate Corridor into your Xcode project using Swift Package Manager, add it to the
dependencies
value of yourPackage.swift
:Contribute
License
Corridor is released under the Apache 2.0 license. See LICENSE for details.