RRuna

Request & Response

Typed input/output and common response helpers

Runa supports regular handlers and typed Input / Output handlers. Beginners can start with regular handlers, then move business APIs to typed handlers when request and response shapes become important.

Regular Handler

route.Default().Get("/", func(ctx *route.Context) error {
    return ctx.Text("ok")
})

The regular handler signature is:

func(ctx *route.Context) error

It is direct and works well for home pages, health checks, and simple callbacks.

Typed input

type ListUsersInput struct {
    Page int    `query:"page" default:"1"`
    Size int    `query:"size" default:"20"`
    Name string `query:"name"`
}

Common sources:

tag Source Example
param Path parameter /users/{id}
query Query string ?page=1
json JSON body POST JSON
form Form body application/x-www-form-urlencoded
header Header X-Token
cookie Cookie session_id
default Default value Used when the input is missing

Both param and path can read path parameters. The docs use param consistently.

Typed output

type UserOutput struct {
    ID   string `json:"id"`
    Name string `json:"name"`
}

route.Get[ListUsersInput, []UserOutput](
    route.Default(),
    "/users",
    func(ctx *route.Context, input *ListUsersInput) (*[]UserOutput, error) {
        users := []UserOutput{{ID: "1", Name: "Runa"}}
        return &users, nil
    },
)

Typed handlers return a pointer to the output object and an error. If there is no error, Runa renders the output automatically.

Input validation

Input structs can implement Validate:

type CreateUserInput struct {
    Name  string `json:"name"`
    Email string `json:"email"`
}

func (input *CreateUserInput) Validate(v *validate.Validator) {
    v.Field("Name").Required("name is required").MinLen(2, "name must contain at least 2 characters")
    v.Field("Email").Required("email is required").Email("email format is invalid")
}

Typed routes run validation automatically after binding input.

Common responses

return ctx.Text("ok")
return ctx.HTML("<h1>ok</h1>")
return ctx.JSON(runa.Map{"ok": true})
return ctx.Blob("application/octet-stream", body)

Status code

Routes can set a success status code:

route.Default().Post("/users", createUser).Status(201)

Handlers can also set the status on the current response:

return ctx.Status(201).JSON(runa.Map{"created": true})

Which style to use

Scenario Recommended style
Health checks and simple text Regular handler
Business APIs Typed Input / Output
OpenAPI generation Typed Input / Output
Request field validation Typed Input + Validate

Common mistakes

Fields are not bound

Make sure struct fields are exported. name string cannot be set by reflection; use Name string.

Tags are placed on the wrong source

Use param:"id" for path parameters, query:"page" for query strings, and json:"name" for JSON bodies.

Edit this page