{"metadata":{"image":[],"title":"","description":""},"api":{"url":"","auth":"required","results":{"codes":[]},"settings":"","params":[]},"next":{"description":"","pages":[]},"title":"Routing","type":"basic","slug":"routing","excerpt":"","body":"Routes in Vapor can be defined in any file that has access to your instance of `Application`. This is usually in the `main.swift` file.\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Basic\"\n}\n[/block]\nThe most basic route includes a method, path, and closure.\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"app.get(\\\"welcome\\\") { request in \\n    return \\\"Hello\\\"\\n}\",\n      \"language\": \"swift\"\n    }\n  ]\n}\n[/block]\nThe standard HTTP methods are available including `get`, `post`, `put`, `patch`, `delete`, and `options`.\n\nYou can also use `any` to match all methods.\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Request\"\n}\n[/block]\nThe first parameter passed into your route closure is an instance of Request. This contains the method, URI, body, and more. Learn more about Request in the Request section of this guide.\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"let method = request.method\",\n      \"language\": \"swift\"\n    }\n  ]\n}\n[/block]\n\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"JSON\"\n}\n[/block]\nTo respond with JSON, simply wrap your data structure with `JSON()`\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"app.get(\\\"version\\\") { request in\\n    return JSON([\\\"version\\\": \\\"1.0\\\"])\\n}\",\n      \"language\": \"swift\"\n    }\n  ]\n}\n[/block]\n\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Response Representable\"\n}\n[/block]\nAll routing closures can return a `ResponseRepresentable` data structure. By default, Strings and JSON conform to this protocol, but you can add your own.\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"public protocol ResponseRepresentable {\\n    func makeResponse() -> Response\\n}\",\n      \"language\": \"swift\"\n    }\n  ]\n}\n[/block]\nVisit the Response section to learn more.\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Parameters\"\n}\n[/block]\nParameters are described by passing the type of data you would like to receive.\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"app.get(\\\"hello\\\", String) { request, name in \\n    return \\\"Hello \\\\(name)\\\"\\n}\",\n      \"language\": \"swift\"\n    }\n  ]\n}\n[/block]\nWhen you add a parameter type, like `String`, the closure will be required to contain another input variable. This variable will be the same type. In this case, `String`.\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"String Initializable\"\n}\n[/block]\nAny type that conforms to `StringInitializable` can be used as a parameter. By default, `String` and `Int` conform to this protocol, but you can add your own.\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"struct User: StringInitializable {\\n    ...\\n}\\n\\napp.get(\\\"users\\\", User) { request, user in \\n    return \\\"Hello \\\\(user.name)\\\"\\n}\",\n      \"language\": \"swift\"\n    }\n  ]\n}\n[/block]\nUsing Swift extensions, you can extend your existing types to support this behavior.\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"extension User: StringInitializable {\\n    init?(from string: String) throws {\\n        guard let int = Int(string) else {\\n            return nil //Will Abort.InvalidRequest\\n        }\\n\\n        guard let user = User.find(int) else {\\n            throw UserError.NotFound\\n        }\\n\\n        self = user\\n    }\\n}\",\n      \"language\": \"swift\"\n    }\n  ]\n}\n[/block]\nYou can throw your own errors or return `nil` to throw the default error. Learn more about errors in the Error Handling section of this guide.\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Groups\"\n}\n[/block]\nPrefix a group of routes with a common string using `grouped(_: String)`.\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"app.grouped(\\\"v1\\\") { v1 in\\n    v1.get(\\\"users\\\") { request in\\n        return User.all\\n    }\\n}\",\n      \"language\": \"swift\"\n    }\n  ]\n}\n[/block]\n\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Grouped Middleware\"\n}\n[/block]\nIn addition to grouping by endpoints, one can also group middleware to only apply to routes in scope.\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"app.grouped(AuthMiddleware(), UserMiddleware()) { group in \\n    group.get(\\\"token\\\") { req in\\n\\t\\t\\treturn getToken(req)\\n    }\\n}\",\n      \"language\": \"swift\"\n    }\n  ]\n}\n[/block]\n\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Caveats\"\n}\n[/block]\nType-safe routing supports up to five parameters.\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"app.get(\\\"users\\\", User, \\\"posts\\\", Post, \\\"comments\\\") { request, user, post in \\n    //this is the maximum\\n}\",\n      \"language\": \"swift\"\n    }\n  ]\n}\n[/block]\nExceeding five parameters is unlikely if you use `app.group` and `app.host`. You can also include slashes in fixed route sections.\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"app.get(\\\"v1/users\\\", User, \\\"resources/written/posts\\\", Post) { request, user, post in \\n    //only four parameters used here\\n}\",\n      \"language\": \"swift\"\n    }\n  ]\n}\n[/block]\nAdditionally, due to a [bug](https://bugs.swift.org/browse/SR-899) in the compiler, `.self` is sometimes required after type names. To circumvent this, you can trick the compiler by using:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"let Int = Swift.Int.self\\nlet String = Swift.String.self\",\n      \"language\": \"swift\"\n    }\n  ]\n}\n[/block]\nSupport the Swift evolution [pull request](https://github.com/apple/swift-evolution/pull/197) to fix this behavior.\n\nUpdate: This has since been [approved](https://github.com/apple/swift-evolution/blob/master/proposals/0090-remove-dot-self.md)\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Custom Routing\"\n}\n[/block]\nVapor still supports traditional routing for custom use-cases or long URLs.\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"app.get(\\\"users/:user_id\\\") { request in\\n    request.parameters[\\\"user_id\\\"] // Optional<String>\\n}\",\n      \"language\": \"swift\"\n    }\n  ]\n}\n[/block]","updates":["574b855d989455170051581f","5761c762a7c9f729009a75ed"],"order":2,"isReference":false,"hidden":false,"sync_unique":"","link_url":"","link_external":false,"_id":"5768701b72cd4c0e000fad1f","project":"57086fe855a4690e005de407","version":{"version":"0.12","version_clean":"0.12.0","codename":"Client Clyde","is_stable":false,"is_beta":true,"is_hidden":false,"is_deprecated":true,"categories":["5768701b72cd4c0e000fad19","5768701b72cd4c0e000fad1a","5768701b72cd4c0e000fad1b","5768701b72cd4c0e000fad1c"],"_id":"5768701b72cd4c0e000fad18","releaseDate":"2016-06-20T22:37:15.641Z","__v":1,"createdAt":"2016-06-20T22:37:15.641Z","project":"57086fe855a4690e005de407"},"githubsync":"","parentDoc":null,"__v":0,"category":{"sync":{"isSync":false,"url":""},"pages":[],"title":"Guide","slug":"getting-started","order":1,"from_sync":false,"reference":false,"_id":"5768701b72cd4c0e000fad1a","createdAt":"2016-04-09T04:31:52.489Z","__v":0,"version":"5768701b72cd4c0e000fad18","project":"57086fe855a4690e005de407"},"createdAt":"2016-04-09T19:55:35.272Z","user":"57086f3d447c410e00221bd1"}
Routes in Vapor can be defined in any file that has access to your instance of `Application`. This is usually in the `main.swift` file. [block:api-header] { "type": "basic", "title": "Basic" } [/block] The most basic route includes a method, path, and closure. [block:code] { "codes": [ { "code": "app.get(\"welcome\") { request in \n return \"Hello\"\n}", "language": "swift" } ] } [/block] The standard HTTP methods are available including `get`, `post`, `put`, `patch`, `delete`, and `options`. You can also use `any` to match all methods. [block:api-header] { "type": "basic", "title": "Request" } [/block] The first parameter passed into your route closure is an instance of Request. This contains the method, URI, body, and more. Learn more about Request in the Request section of this guide. [block:code] { "codes": [ { "code": "let method = request.method", "language": "swift" } ] } [/block] [block:api-header] { "type": "basic", "title": "JSON" } [/block] To respond with JSON, simply wrap your data structure with `JSON()` [block:code] { "codes": [ { "code": "app.get(\"version\") { request in\n return JSON([\"version\": \"1.0\"])\n}", "language": "swift" } ] } [/block] [block:api-header] { "type": "basic", "title": "Response Representable" } [/block] All routing closures can return a `ResponseRepresentable` data structure. By default, Strings and JSON conform to this protocol, but you can add your own. [block:code] { "codes": [ { "code": "public protocol ResponseRepresentable {\n func makeResponse() -> Response\n}", "language": "swift" } ] } [/block] Visit the Response section to learn more. [block:api-header] { "type": "basic", "title": "Parameters" } [/block] Parameters are described by passing the type of data you would like to receive. [block:code] { "codes": [ { "code": "app.get(\"hello\", String) { request, name in \n return \"Hello \\(name)\"\n}", "language": "swift" } ] } [/block] When you add a parameter type, like `String`, the closure will be required to contain another input variable. This variable will be the same type. In this case, `String`. [block:api-header] { "type": "basic", "title": "String Initializable" } [/block] Any type that conforms to `StringInitializable` can be used as a parameter. By default, `String` and `Int` conform to this protocol, but you can add your own. [block:code] { "codes": [ { "code": "struct User: StringInitializable {\n ...\n}\n\napp.get(\"users\", User) { request, user in \n return \"Hello \\(user.name)\"\n}", "language": "swift" } ] } [/block] Using Swift extensions, you can extend your existing types to support this behavior. [block:code] { "codes": [ { "code": "extension User: StringInitializable {\n init?(from string: String) throws {\n guard let int = Int(string) else {\n return nil //Will Abort.InvalidRequest\n }\n\n guard let user = User.find(int) else {\n throw UserError.NotFound\n }\n\n self = user\n }\n}", "language": "swift" } ] } [/block] You can throw your own errors or return `nil` to throw the default error. Learn more about errors in the Error Handling section of this guide. [block:api-header] { "type": "basic", "title": "Groups" } [/block] Prefix a group of routes with a common string using `grouped(_: String)`. [block:code] { "codes": [ { "code": "app.grouped(\"v1\") { v1 in\n v1.get(\"users\") { request in\n return User.all\n }\n}", "language": "swift" } ] } [/block] [block:api-header] { "type": "basic", "title": "Grouped Middleware" } [/block] In addition to grouping by endpoints, one can also group middleware to only apply to routes in scope. [block:code] { "codes": [ { "code": "app.grouped(AuthMiddleware(), UserMiddleware()) { group in \n group.get(\"token\") { req in\n\t\t\treturn getToken(req)\n }\n}", "language": "swift" } ] } [/block] [block:api-header] { "type": "basic", "title": "Caveats" } [/block] Type-safe routing supports up to five parameters. [block:code] { "codes": [ { "code": "app.get(\"users\", User, \"posts\", Post, \"comments\") { request, user, post in \n //this is the maximum\n}", "language": "swift" } ] } [/block] Exceeding five parameters is unlikely if you use `app.group` and `app.host`. You can also include slashes in fixed route sections. [block:code] { "codes": [ { "code": "app.get(\"v1/users\", User, \"resources/written/posts\", Post) { request, user, post in \n //only four parameters used here\n}", "language": "swift" } ] } [/block] Additionally, due to a [bug](https://bugs.swift.org/browse/SR-899) in the compiler, `.self` is sometimes required after type names. To circumvent this, you can trick the compiler by using: [block:code] { "codes": [ { "code": "let Int = Swift.Int.self\nlet String = Swift.String.self", "language": "swift" } ] } [/block] Support the Swift evolution [pull request](https://github.com/apple/swift-evolution/pull/197) to fix this behavior. Update: This has since been [approved](https://github.com/apple/swift-evolution/blob/master/proposals/0090-remove-dot-self.md) [block:api-header] { "type": "basic", "title": "Custom Routing" } [/block] Vapor still supports traditional routing for custom use-cases or long URLs. [block:code] { "codes": [ { "code": "app.get(\"users/:user_id\") { request in\n request.parameters[\"user_id\"] // Optional<String>\n}", "language": "swift" } ] } [/block]