# Parameters - Vapor Docs

Skip to content


# Routing Parameters

Traditional web frameworks leave room for error in routing by using strings for route parameter names and types. Vapor takes advantage of Swift's closures to provide a safer and more intuitive method for accessing route parameters.

Seealso

Route parameters refer to segments of the URL path (e.g., `/users/:id`). For query parameters (e.g., `?foo=bar`) see request query parameters.

## Type Safe

To create a type safe route simply replace one of the parts of your path with a `Type`.

    drop.get("users", Int.parameter) { req in
        let userId = try req.parameters.next(Int.self)
        return "You requested User #\(userId)"
    }

This creates a route that matches `users/:id` where the `:id` is an `Int`. Here's what it would look like using manual route parameters.

    drop.get("users", ":id") { request in
        guard let userId = request.parameters["id"]?.int else {
            throw Abort.badRequest
        }

        return "You requested User #\(userId)"
    }

Here you can see that type safe routing saves ~3 lines of code and also prevents runtime errors like misspelling `:id`.

## Parameterizable

Any type conforming to `Parameterizable` can be used as a parameter. By default, all Vapor Models conform.

Using this, our previous example with users can be further simplified.

    drop.get("users", User.parameter) { req in
        let user = try req.parameters.next(User.self)

        return "You requested \(user.name)"
    }

Here the identifier supplied is automatically used to lookup a user. For example, if `/users/5` is requested, the `User` model will be asked for a user with identifier `5`. If one is found, the request succeeds and the closure is called. If not, a not found error is thrown.

Here is what this would look like if we looked the model up manually.

    drop.get("users", Int.parameter) { req in
        let userId = try req.parameters.next(Int.self)
        guard let user = try User.find(userId) else {
            throw Abort.notFound
        }

        return "You requested \(user.name)"
    }

### Protocol

You can conform your own types to `Parameterizable`.

    import Routing

    extension Foo: Parameterizable {
        /// This unique slug is used to identify
        /// the parameter in the router
        static var uniqueSlug: String {
            return "foo"
        }

        static func make(for parameter: String) throws -> Foo {
            /// custom lookup logic here
            /// the parameter string contains the information
            /// parsed from the URL.
            ...
        }
    }

Now you can use this type for type safe routing.

    drop.get("users", "nickname", Foo.parameter) { req in
        let foo = try req.parameters.next(Foo.self)
        ...
    }

### Groups

Type-safe parameters also work with groups.

    let userGroup = drop.grouped("users", User.parameter)
    userGroup.get("messages") { req in
        let user = try req.parameters.next(User.self)

        ...
    }