If your route path starts with /api/
consider combining it with your unique app name like /api/myapp/... to avoid collisions
with system routes.
PocketBase routing is built on top of the standard Go
net/http.ServeMux.
The router can be accessed via the app.OnServe() hook allowing you to register custom endpoints
and middlewares.
Every route has a path, handler function and eventually middlewares attached to it. For example:
There are several routes registration methods available, but the most common ones are:
The router also supports creating groups for routes that share the same base path and middlewares. For example:
The example registers the following endpoints
(all require authenticated user access):
Each router group and route could define middlewares in a similar manner to the
regular app hooks via the Bind/BindFunc methods, allowing you to perform various BEFORE or AFTER
action operations (e.g. inspecting request headers, custom access checks, etc.).
Because PocketBase routing is based on top of the Go standard router mux, we follow the same pattern
matching rules. Below you could find a short overview but for more details please refer to
net/http.ServeMux.
In general, a route pattern looks like [METHOD ][HOST]/[PATH]
(the METHOD prefix is added automatically when using the designated GET(),
POST(), etc. methods)).
Route paths can include parameters in the format {`{paramName}`}.
You can also use {`{paramName...}`} format to specify a parameter that targets more than one path
segment.
A pattern ending with a trailing slash / acts as anonymous wildcard and matches any requests
that begins with the defined route. If you want to have a trailing slash but to indicate the end of the
URL then you need to end the path with the special
{`{$}`} parameter.
If your route path starts with /api/
consider combining it with your unique app name like /api/myapp/... to avoid collisions
with system routes.
Here are some examples:
In the following examples e is usually
*core.RequestEvent
value.
The request auth state can be accessed (or set) via the RequestEvent.Auth field.
Alternatively you could also access the request data from the summarized request info instance
(usually used in hooks like the OnRecordEnrich where there is no direct access to the request)
.
Body parameters can be read either via
e.BindBody
OR through the parsed request info (requires manual type assertions).
The e.BindBody argument must be a pointer to a struct or map[string]any.
The following struct tags are supported
(the specific binding rules and which one will be used depend on the request Content-Type):
json (json body)- uses the builtin Go JSON package for unmarshaling.xml (xml body) - uses the builtin Go XML package for unmarshaling.form (form data) - utilizes the custom
router.UnmarshalRequestData
method.
NB! When binding structs make sure that they don't have public fields that shouldn't be bindable and it is advisable such fields to be unexported or define a separate struct with just the safe bindable fields.
For all supported methods, you can refer to
router.Event
.
The core.RequestEvent comes with a local store that you can use to share custom data between
middlewares and the route action.
Middlewares allow inspecting, intercepting and filtering route requests.
All middleware functions share the same signature with the route actions (aka.
{`func(e *core.RequestEvent) error`}) but expect the user to call e.Next() if they
want to proceed with the execution chain.
Middlewares can be registered globally, on group and on route level using the
Bind
and BindFunc methods.
Here is a minimal example of what a global middleware looks like:
RouterGroup.Bind(middlewares...)
/
Route.Bind(middlewares...)
registers one or more middleware handlers.
Similar to the other app hooks, a middleware handler has 3 fields:
Id (optional) - the name of the middleware (could be used as argument for
Unbind)
Priority (optional) - the execution order of the middleware (if empty fallbacks to
the order of registration in the code)
Func (required) - the middleware handler function
Often you don't need to specify the Id or Priority of the middleware and for
convenience you can instead use directly
RouterGroup.BindFunc(funcs...)
/
Route.BindFunc(funcs...)
.
Below is a slightly more advanced example showing all options and the execution sequence (2,0,1,3,4):
To remove a registered middleware from the execution chain for a specific group or route you can make use
of the
Unbind(id) method.
Note that only middlewares that have a non-empty Id can be removed.
The
apis
package exposes several middlewares that you can use as part of your application.
apis.DefaultRateLimitMiddlewarePriority - 1 so that the rate limit can be applied
properly based on the loaded auth state.
All PocketBase applications have the below internal middlewares registered out of the box (sorted by their priority):
apis.DefaultWWWRedirectMiddlewareId
apis.DefaultWWWRedirectMiddlewarePriority
apis.DefaultCorsMiddlewareId
apis.DefaultCorsMiddlewarePriority
--origins
flag but for more advanced customization it can be also replaced entirely by binding with
apis.CORS(config) middleware or registering your own custom one in its place.
apis.DefaultActivityLoggerMiddlewareId
apis.DefaultActivityLoggerMiddlewarePriority
apis.DefaultPanicRecoverMiddlewareId
apis.DefaultPanicRecoverMiddlewarePriority
apis.DefaultLoadAuthTokenMiddlewareId
apis.DefaultLoadAuthTokenMiddlewarePriority
Authorization header and populates the related auth
record into the request event (aka. e.Auth).
apis.DefaultSecurityHeadersMiddlewareId
apis.DefaultSecurityHeadersMiddlewarePriority
X-XSS-Protection,
X-Content-Type-Options,
X-Frame-Options) to the response (can be overwritten by other middlewares or from
inside the route action).
apis.DefaultRateLimitMiddlewareId
apis.DefaultRateLimitMiddlewarePriority
apis.DefaultBodyLimitMiddlewareId
apis.DefaultBodyLimitMiddlewarePriority
apis.BodyLimit(limitBytes) middleware.
PocketBase has a global error handler and every returned error from a route or middleware will be safely
converted by default to a generic ApiError to avoid accidentally leaking sensitive
information (the original raw error message will be visible only in the Dashboard > Logs or when
in --dev mode).
To make it easier returning formatted JSON error responses, the request event provides several
ApiError methods.
Note that ApiError.RawData() will be returned in the response only if it is a map of
router.SafeErrorItem/validation.Error items.
This is not very common but if you want to return ApiError outside of request related
handlers, you can use the below
apis.* factories:
apis.Static()
serves static directory content from fs.FS instance.
Expects the route to have a {"{path...}"} wildcard parameter.
apis.RecordAuthResponse()
writes standardized JSON record auth response (aka. token + record data) into the specified request body.
Could be used as a return result from a custom auth route.
apis.EnrichRecord()
and
apis.EnrichRecords()
helpers parses the request context and enrich the provided record(s) by:
defaultExpands and/or ?expand query parameter is set)
If you want to register standard Go http.Handler function and middlewares, you can use
apis.WrapStdHandler(handler)
and
apis.WrapStdMiddleware(func)
functions.
The official PocketBase SDKs expose the internal send() method that could be used to send requests
to your custom route(s).