Skip to content


Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
This branch is 18 commits ahead of kjessup:master.

Latest commit


Git stats


Failed to load latest commit information.
Latest commit message
Commit time

URL Routing

Get Involed with Perfect!

Star Perfect On Github Stack Overflow Follow Perfect on Twitter Join the Perfect Slack

Swift 3.0 Platforms OS X | Linux License Apache PerfectlySoft Twitter Slack Status

This example illustrates how to set up URL routing to direct requests to your custom handlers.

To use the example with Swift Package Manager, type swift build and then run .build/debug/URLRouting.

To use the example with Xcode, run the URL Routing target. This will launch the Perfect HTTP Server.

Navigate in your web browser to http://localhost:8181/. Experiment with the URL routes which are added.


We are transitioning to using JIRA for all bugs and support related issues, therefore the GitHub issues has been disabled.

If you find a mistake, bug, or any other helpful suggestion you'd like to make on the docs please head over to and raise it.

A comprehensive list of open issues can be found at

Enabling URL Routing

The following code is taken from the example project and shows how to create and add routes to a server.

var routes = Routes()

routes.add(method: .get, uris: ["/", "index.html"], handler: indexHandler)
routes.add(method: .get, uri: "/foo/*/baz", handler: echoHandler)
routes.add(method: .get, uri: "/foo/bar/baz", handler: echoHandler)
routes.add(method: .get, uri: "/user/{id}/baz", handler: echo2Handler)
routes.add(method: .get, uri: "/user/{id}", handler: echo2Handler)
routes.add(method: .post, uri: "/user/{id}/baz", handler: echo3Handler)

// Test this one via command line with curl:
// curl --data "{\"id\":123}" --header "Content-Type:application/json"
routes.add(method: .post, uri: "/raw", handler: rawPOSTHandler)

// Trailing wildcard matches any path
routes.add(method: .get, uri: "**", handler: echo4Handler)

// Routes with a base URI

// Create routes for version 1 API
var api = Routes()
api.add(method: .get, uri: "/call1", handler: { _, response in
	response.setBody(string: "API CALL 1")
api.add(method: .get, uri: "/call2", handler: { _, response in
	response.setBody(string: "API CALL 2")

// API version 1
var api1Routes = Routes(baseUri: "/v1")
// API version 2
var api2Routes = Routes(baseUri: "/v2")

// Add the main API calls to version 1
api1Routes.add(routes: api)
// Add the main API calls to version 2
api2Routes.add(routes: api)
// Update the call2 API
api2Routes.add(method: .get, uri: "/call2", handler: { _, response in
	response.setBody(string: "API v2 CALL 2")

// Add both versions to the main server routes
routes.add(routes: api1Routes)
routes.add(routes: api2Routes)

// Check the console to see the logical structure of what was installed.

// Create server object.
let server = HTTPServer()

// Listen on port 8181.
server.serverPort = 8181

// Add our routes.

do {
    // Launch the HTTP server
    try server.start()
} catch PerfectError.networkError(let err, let msg) {
    print("Network error thrown: \(err) \(msg)")

Handling Requests

The example EchoHandler consists of the following.

func echoHandler(request: HTTPRequest, _ response: HTTPResponse) {
	response.appendBody(string: "Echo handler: You accessed path \(request.path) with variables \(request.urlVariables)")

Using Apache

The following Apache conf snippet can be used to pipe requests for non-existent files through to Perfect when using the URL routing system.

	RewriteEngine on
	RewriteCond %{REQUEST_FILENAME} !-f
	RewriteCond %{REQUEST_FILENAME} !-d
	RewriteRule (.*) - [L,NS,H=perfect-handler]

Further Information

For more information on the Perfect project, please visit


Perfect Example Module: URL Routing








No releases published


No packages published


  • Swift 100.0%