Skip to content

Controller

Kripth edited this page Jan 10, 2019 · 4 revisions

A controller maps paths to methods.

A controller is a public class annotated with @Controller that contains public functions annotated with @Route (@Get, used in the example, is an alias for @Route("GET")).

Forget the /s

Controller and Route (and its aliases) can optionally take as arguments a path, not separated by / but by argument. If a path is added to @Controller, all the routes in the class will start with the controller's path.

@Controller
class Controller {

	// will route to /example
	@Get("example")
	getExample() {}

}
@Controller("controller")
class Controller {

	// will route to /controller
	@Get
	getIndex() {}
	
	// will route to /controller/example/example
	@Get("example", "example")
	getExample() {}

}

Custom attributes

Routes can optionally have custom attributes that contains a test function which is called before the route's function is and determine whether the route's function will be called.

An example of a custom attributes are Auth, which checks whether the client is logged in and/or has the given roles and returns a 401 Unauthorized if it does not, AuthRedirect which does the same as Auth except it redirects the client to the given location on failure and Async, which just sets the response as asynchronous.

An example of custom attribute that checks whether the client has a cookie called password that is needed to enter a certain route:

struct NeedPassword {

    string password;

    bool test(Context context) {
        if(auto password = "password" in context.request.cookies) {
            return *password == this.password;
        } else {
            return false;
        }
    }

}

@Controller
class NeedPasswordController {

    @NeedPassword("~secret_code~")
    @Get("secret-page")
    getSecretPage(Response response) {
        response.body = "Welcome to the secret page.";
    }

}

The Context, which must be the first an only parameter of the test function, contains the current request, response and session of the client.

Arguments

A route can optionally take as arguments one or more of the following classes:

  • Request: contains informations about the client's request.
  • Response: contains informations about the response, like headers and body.
  • Session: informations about the client's session (code documentation).
  • View: utility that can be used to compile diet files (code documentation).
  • Annotated parameters.

Annotated parameters

Annotated parameters are parameters with special annotations that are used to get the request's informations more easily.

Path

@Path is used to get the result of a regular expression's capture in the path. For each capture group in the path a parameter annotated with @Path must also be present in the method's parameters.

@Get("user", "([a-zA-Z0-9_]+)")
getUser(Response response, @Path string username) {
	writeln(username);
}

In this case /user/Kripth will print Kripth, but /user/mark-white will result in a not found client error, because mark-white does not match the regular expression [a-zA-Z0-9_]+.

Paths don't have to be strings: they can be any type convertible from a string, like numbers or booleans. It's the programmer's job to make sure the input will be convertible from a string to the required type with a proper regular expression.

Param

@Param is used to get the query parameters from the url.

Like @Path it can be of any type convertible from a string. In this case no errors will be throws if the input is not convertible but a bad request client error will be returned to the client and the route's method will not even be called.

@Get("number")
getExample(Response response, @Param int number) {
	writeln("Your number: ", number);
}

In this case /number/92384 will print 92384, but /number/55.5 will result in bad request client error, because 55.5 cannot be converted to int.

Body

@Body is used to get the content of the request's body. The parameter must be a struct or a class callable with an empty constructor containing fields that will be validated before calling the route's function.

If the validation fails the server returns a 400 Bad Request client error and does not call the function, unless the function also has a parameter of type Validation: in that case the function is called even when the validation fails.

This wiki has a page about validation that describes how attributes can be used for custom validation of structs and classes.

You can’t perform that action at this time.