Resource Routes
Organize structured resource APIs on top of route.Group
The resource package provides a REST-style API organization layer on top of route.Group. It is not a Provider and does not need runa.Install; it is usually used directly during route registration.
Resource fits admin panels, management APIs, and REST-style resource APIs. It helps keep route names, summaries, tags, permission metadata, and OpenAPI metadata consistent across a group of routes.
Install
go get github.com/duxweb/runa/resource
You still need the HTTP transport when using Resource in an HTTP application:
go get github.com/duxweb/runa/route
Create a Resource
users := resource.New(route.Default().Group("/admin"), "/users").
Name("user").
Summary("User").
Tags("User")
This creates a /users resource under the /admin group.
Standard actions
users.List[ListInput, []UserOutput](listUsers)
users.Show[ShowInput, UserOutput](showUser)
users.Create[CreateInput, UserOutput](createUser)
users.Edit[EditInput, UserOutput](editUser)
users.Store[StoreInput, UserOutput](storeUser)
users.Delete[DeleteInput, runa.Map](deleteUser)
Default action paths:
| Method | Path | Action | Common use |
|---|---|---|---|
| GET | /users |
list | List records |
| GET | /users/{id} |
show | Detail |
| POST | /users |
create | Create |
| PUT | /users/{id} |
edit | Full edit |
| PATCH | /users/{id} |
store | Partial save |
| DELETE | /users/{id} |
delete | Delete |
Complete small example
type ShowInput struct {
ID string `param:"id"`
}
type UserOutput struct {
ID string `json:"id"`
Name string `json:"name"`
}
users := resource.New(route.Default().Group("/admin"), "/users").
Name("user").
Summary("User").
Tags("User")
users.Show[ShowInput, UserOutput](func(ctx *route.Context, input *ShowInput) (*UserOutput, error) {
return &UserOutput{ID: input.ID, Name: "Runa"}, nil
})
The registered path is:
GET /admin/users/{id}
Custom actions
users.Post[ImportInput, ImportOutput]("import", "/import", importUsers)
This registers:
POST /admin/users/import
The action name is import, and the route name is built from Resource Name("user"), such as user.import.
Route metadata
Resource applies name, summary, tags, permission markers, document domains, and other metadata to every route.
users.Name("system.user").Doc("admin").Meta("permission", "system.user")
You can also mark a resource to skip authentication or permission checks:
users.SkipAuth()
users.SkipPermission()
Whether those markers take effect depends on how your auth and permission middleware reads route metadata.
Relationship with OpenAPI
Resource itself does not generate OpenAPI. It writes schema and metadata into routes. After installing openapi.Provider(...), OpenAPI can read that information.
Resource vs CRUD
| Tool | What it solves |
|---|---|
resource |
Organizes a group of resource routes and metadata |
crud |
Builds list, detail, create, edit, delete, and other data APIs on top of Resource and Store |
Use Resource when you only want consistent route structure. Use CRUD when you also want to reduce repeated data API logic.
Common mistakes
Treating Resource as a Provider
resource does not need app.Install(resource.Provider()). It is a route-registration helper.
Not planning route names
Name("user") affects generated route names such as user.list and user.show. Choose names by business domain from the start.
Confusing Resource and CRUD
Resource organizes routes. CRUD connects Store and generates data APIs.