Skip to main content

Routes

🏗 Work in progress

The content of this page might not be fully up-to-date with Strapi 5 yet.

Requests sent to Strapi on any URL are handled by routes. By default, Strapi generates routes for all the content-types (see REST API documentation). Routes can be added and configured:

  • with policies, which are a way to block access to a route,
  • and with middlewares, which are a way to control and change the request flow and the request itself.

Once a route exists, reaching it executes some code handled by a controller (see controllers documentation).

Simplified Strapi backend diagram with routes highlighted
The diagram represents a simplified version of how a request travels through the Strapi back end, with routes highlighted. The backend customization introduction page includes a complete, interactive diagram.

Implementation

Implementing a new route consists in defining it in a router file within the ./src/api/[apiName]/routes folder (see project structure).

There are 2 different router file structures, depending on the use case:

Configuring core routers

Core routers (i.e. find, findOne, create, update, and delete) correspond to default routes automatically created by Strapi when a new content-type is created.

Strapi provides a createCoreRouter factory function that automatically generates the core routers and allows:

  • passing in configuration options to each router
  • and disabling some core routers to create custom ones.

A core router file is a JavaScript file exporting the result of a call to createCoreRouter with the following parameters:

ParameterDescriptionType
prefixAllows passing in a custom prefix to add to all routers for this model (e.g. /test)String
onlyCore routes that will only be loaded

Anything not in this array is ignored.
Array
exceptCore routes that should not be loaded

This is functionally the opposite of the only parameter.
Array
configConfiguration to handle policies, middlewares and public availability for the routeObject

./src/api/[apiName]/routes/[routerName].js (e.g './src/api/restaurant/routes/restaurant.js')

const { createCoreRouter } = require('@strapi/strapi').factories;

module.exports = createCoreRouter('api::restaurant.restaurant', {
prefix: '',
only: ['find', 'findOne'],
except: [],
config: {
find: {
auth: false,
policies: [],
middlewares: [],
},
findOne: {},
create: {},
update: {},
delete: {},
},
});

Generic implementation example:

./src/api/restaurant/routes/restaurant.js

const { createCoreRouter } = require('@strapi/strapi').factories;

module.exports = createCoreRouter('api::restaurant.restaurant', {
only: ['find'],
config: {
find: {
auth: false,
policies: [],
middlewares: [],
}
}
});

This only allows a GET request on the /restaurants path from the core find controller without authentication.

Creating custom routers

Creating custom routers consists in creating a file that exports an array of objects, each object being a route with the following parameters:

ParameterDescriptionType
methodMethod associated to the route (i.e. GET, POST, PUT, DELETE or PATCH)String
pathPath to reach, starting with a forward-leading slash (e.g. /articles)String
handlerFunction to execute when the route is reached.
Should follow this syntax: <controllerName>.<actionName>
String
config

Optional
Configuration to handle policies, middlewares and public availability for the route

Object

Dynamic routes can be created using parameters and regular expressions. These parameters will be exposed in the ctx.params object. For more details, please refer to the PathToRegex documentation.

Caution

Routes files are loaded in alphabetical order. To load custom routes before core routes, make sure to name custom routes appropriately (e.g. 01-custom-routes.js and 02-core-routes.js).

Example of a custom router using URL parameters and regular expressions for routes

In the following example, the custom routes file name is prefixed with 01- to make sure the route is reached before the core routes.

./src/api/restaurant/routes/01-custom-restaurant.js

module.exports = {
routes: [
{ // Path defined with an URL parameter
method: 'POST',
path: '/restaurants/:id/review',
handler: 'restaurant.review',
},
{ // Path defined with a regular expression
method: 'GET',
path: '/restaurants/:category([a-z]+)', // Only match when the URL parameter is composed of lowercase letters
handler: 'restaurant.findByCategory',
}
]
}

Configuration

Both core routers and custom routers have the same configuration options. The routes configuration is defined in a config object that can be used to handle policies and middlewares or to make the route public.

Policies

Policies can be added to a route configuration:

  • by pointing to a policy registered in ./src/policies, with or without passing a custom configuration
  • or by declaring the policy implementation directly, as a function that takes policyContext to extend Koa's context (ctx) and the strapi instance as arguments (see policies documentation)
./src/api/restaurant/routes/restaurant.js

const { createCoreRouter } = require('@strapi/strapi').factories;

module.exports = createCoreRouter('api::restaurant.restaurant', {
config: {
find: {
policies: [
// point to a registered policy
'policy-name',

// point to a registered policy with some custom configuration
{ name: 'policy-name', config: {} },

// pass a policy implementation directly
(policyContext, config, { strapi }) => {
return true;
},
]
}
}
});

Middlewares

Middlewares can be added to a route configuration:

  • by pointing to a middleware registered in ./src/middlewares, with or without passing a custom configuration
  • or by declaring the middleware implementation directly, as a function that takes Koa's context (ctx) and the strapi instance as arguments:
./src/api/restaurant/routes/restaurant.js

const { createCoreRouter } = require('@strapi/strapi').factories;

module.exports = createCoreRouter('api::restaurant.restaurant', {
config: {
find: {
middlewares: [
// point to a registered middleware
'middleware-name',

// point to a registered middleware with some custom configuration
{ name: 'middleware-name', config: {} },

// pass a middleware implementation directly
(ctx, next) => {
return next();
},
]
}
}
});

Public routes

By default, routes are protected by Strapi's authentication system, which is based on API tokens or on the use of the Users & Permissions plugin.

In some scenarios, it can be useful to have a route publicly available and control the access outside of the normal Strapi authentication system. This can be achieved by setting the auth configuration parameter of a route to false:

./src/api/restaurant/routes/restaurant.js

const { createCoreRouter } = require('@strapi/strapi').factories;

module.exports = createCoreRouter('api::restaurant.restaurant', {
config: {
find: {
auth: false
}
}
});