Skip to content

Controller

Controller responsible for directing and coordinating the flow of data and operations within an application. The controller are defined in controllers directory. You can define the payload request and response in a controller.

Here is the default Raiden's controller.

go
package controllers

import (
    "github.com/sev-2/raiden"
)

type HelloWorldRequest struct {
}

type HelloWorldResponse struct {
    Message string `json:"message"`
}

type HelloWorldController struct {
    raiden.ControllerBase
    Payload *HelloWorldRequest
    Result  HelloWorldResponse
}

func (c *HelloWorldController) Get(ctx raiden.Context) error {
    c.Result.Message = "Welcome to raiden"
    return ctx.SendJson(c.Result)
}

Routing

All routings are automatically generated by controllers based on their location within the controllers directory. The folder structure directly dictates the URL path.

Static Routes

For example, a controller located at controllers/status.go will automatically be accessible at the /status endpoint.

Dynamic Routes

Folders prefixed with an underscore (_) denote dynamic route segments. The name after the underscore becomes the parameter name, which can be accessed within the controller using ctx.GetParam("parameterName").

For example, a controller located at controllers/rest/v1/users/_id/custom.go will be accessible at /rest/v1/users/{id}. Inside the controller, you can retrieve the id like this:

go
id := ctx.GetParam("id").(string)

HTTP Verb

You can use Get, Post, Put, Patch, Delete, Options, or Head on function name to use specific HTTP verb request.

For example, if you want to use Post and Delete request.

go
func (c *HelloWorldController) Post(ctx raiden.Context) error { 
    c.Result.Message = "Data has been inserted."
    return ctx.SendJson(c.Result)
}

func (c *HelloWorldController) Delete(ctx raiden.Context) error { 
    c.Result.Message = "Data has been deleted."
    return ctx.SendJson(c.Result)
}

Type

There are several options for the controller type: custom, rest, rpc. These types influence the controller's behavior and generated functionalities, while the route itself is determined by the folder structure.

For example, a custom type controller:

go
type HelloWorldController struct {
    raiden.ControllerBase
    Payload *HelloWorldRequest
    Result  HelloWorldResponse
}

INFO

The rpc type only available for Post verb.

Lifecycle Hooks

Each controller handler supports Before and After hooks. These hooks run before and after the main handler method, allowing you to add logic like authorization checks, logging, or response transformations.

Available hooks:

HookDescription
BeforeAll / AfterAllRuns before/after any HTTP method handler
BeforeGet / AfterGetRuns before/after Get handler
BeforePost / AfterPostRuns before/after Post handler
BeforePut / AfterPutRuns before/after Put handler
BeforePatch / AfterPatchRuns before/after Patch handler
BeforeDelete / AfterDeleteRuns before/after Delete handler
BeforeOptions / AfterOptionsRuns before/after Options handler
BeforeHead / AfterHeadRuns before/after Head handler

Example

go
type HelloWorldController struct {
    raiden.ControllerBase
    Payload *HelloWorldRequest
    Result  HelloWorldResponse
}

func (c *HelloWorldController) BeforeGet(ctx raiden.Context) error {
    // Authorization check before Get handler
    userRole := ctx.Get("role")
    if userRole != "admin" {
        return ctx.SendErrorWithCode(403, fmt.Errorf("forbidden"))
    }
    return nil
}

func (c *HelloWorldController) Get(ctx raiden.Context) error {
    c.Result.Message = "Welcome to raiden"
    return ctx.SendJson(c.Result)
}

func (c *HelloWorldController) AfterGet(ctx raiden.Context) error {
    // Log after Get handler
    fmt.Println("Get handler completed")
    return nil
}

RestController

RestController provides automatic CRUD operations for a model by proxying requests to the Supabase REST API. You don't need to write individual Get, Post, Put, Patch, or Delete handlers.

go
type ProductsController struct {
    raiden.RestController
    Model   models.Products
    Payload *ProductsRequest
    Result  ProductsResponse
}

With RestController, the following endpoints are automatically available:

MethodDescription
GETRetrieve data (list or single)
POSTInsert new data
PUTReplace existing data
PATCHUpdate existing data
DELETEDelete data

You can still override any handler or add Before/After hooks to customize behavior:

go
func (c *ProductsController) BeforePost(ctx raiden.Context) error {
    // Validate payload before insert
    return nil
}

Released under the MIT License.