✎ Edit on GitHub

# Controllers

Controllers help you organize related functionality into a single place. They can also be used to create RESTful resources.

## Basic

A basic controller looks like the following:

    final class HelloController {
        func sayHello(_ req: Request) throws -> ResponseRepresentable {
            guard let name = req.data["name"] else {
                throw Abort.badRequest
            }
            return "Hello, \(name)"
        }
    }

Simple controllers don't need to conform to any protocols. You are free to design them however you see fit.

### Registering

The only required structure is the signature of each method in the controller. In order to register this method into the router, it must have a signature like `(Request) throws -> ResponseRepresentable`. `Request` and `ResponseRepresentable` are made available by importing the `HTTP` module.

    let hc = HelloController()
    drop.get("hello", handler: hc.sayHello)

Since the signature of our `sayHello` method matches the signature of the closure for the `drop.get` method, we can pass it directly.

### Type Safe

You can also use controller methods with type-safe routing.

    final class HelloController {
        ...

        func sayHelloAlternate(_ req: Request, _ name: String) -> ResponseRepresentable {
            return "Hello, \(name)"
        }
    }

We add a new method called `sayHelloAlternate` to the `HelloController` that accepts a second parameter `name: String`.

    let hc = HelloController()
    drop.get("hello", String.self, handler: hc.sayHelloAlternate)

Since this type-safe `drop.get` accepts a signature `(Request, String) throws -> ResponseRepresentable`, our method can now be used as the closure for this route.

## Resources

Controllers that conform to `ResourceRepresentable` can be easily registered into a router as a RESTful resource. Let's look at an example of a `UserController`.

    final class UserController {
        func index(_ request: Request) throws -> ResponseRepresentable {
            return try User.all().makeNode().converted(to: JSON.self)
        }

        func show(_ request: Request, _ user: User) -> ResponseRepresentable {
            return user
        }
    }

Here is a typical user controller with an `index` and `show` route. Indexing returns a JSON list of all users and showing returns a JSON representation of a single user.

We could register the controller like so:

    let users = UserController()
    drop.get("users", handler: users.index)
    drop.get("users", User.self, handler: users.show)

But `ResourceRepresentable` makes this standard RESTful structure easy.

    extension UserController: ResourceRepresentable {
        func makeResource() -> Resource<User> {
            return Resource(
                index: index,
                show: show
            )
        }
    }

Conforming `UserController` to `ResourceRepresentable` requires that the signatures of the `index` and `show` methods match what the `Resource<User>` is expecting.

Here is a peek into the `Resource` class.

    final class Resource<Model: StringInitializable> {
        typealias Multiple = (Request) throws -> ResponseRepresentable
        typealias Item = (Request, Model) throws -> ResponseRepresentable

        var index: Multiple?
        var store: Multiple?
        var show: Item?
        var replace: Item?
        var modify: Item?
        var destroy: Item?
        var clear: Multiple?
        var aboutItem: Item?
        var aboutMultiple: Multiple?

        ...
    }

Now that `UserController` conforms to `ResourceRepresentable`, registering the routes is easy.

    let users = UserController()
    drop.resource("users", users)

`drop.resource` will take care of registering only the routes that have been supplied by the call to `makeResource()`. In this case, only the `index` and `show` routes will be supplied.

> Note: `drop.resource` also adds useful defaults for OPTIONS requests. These can be overriden.

## Folder

Controllers can go anywhere in your application, but they are most often stored in the `Controllers/` directory.

### Modules

If you are building a large application, you may want to create your controllers in a separate module. This will allow you to perform unit tests on your controllers. For more information on creating modules, visit the documentation for the Swift Package Manager.