4.1 KiB
Executable File
Router
The most basic feature of any web application is the ability to interpret a request sent to a URL, then send back a response. In order to do this, your application has to be able to distinguish one URL from another.
Like most web frameworks, Strapi provides a router: a mechanism for mapping URLs to controllers. Routes are rules that tell Strapi what to do when faced with an incoming request.
Routes can be found in ./api/<apiName>/config/routes.json
.
Route format
Each route consists of an address (as a key) and a target (as an object value).
The address is a URL path and a specific HTTP method. The target is defined by an object with a
controller
and an action
. When the router receives an incoming request, it checks the address
of all routes for matches. If a matching route is found, the request is then passed to its target.
{
"routes": {
"VERB /endpoint/:param": {
"controller": "controllerName",
"action": "actionName"
}
}
}
For example to manage your Post
records with a CRUD, your route should look like this:
{
"routes": {
"GET /post": {
"controller": "Post",
"action": "find"
}
"GET /post/:id": {
"controller": "Post",
"action": "findOne"
},
"POST /post": {
"controller": "Post",
"action": "create"
},
"PUT /post/:id": {
"controller": "Post",
"action": "update"
},
"DELETE /post/:id": {
"controller": "Post",
"action": "delete"
}
}
}
Route parameters
Route paths will be translated to regular expressions used to match requests. Query strings will not be considered when matching requests.
Route parameters are captured and added to ctx.params
or ctx.request.body
.
By taking the previous example, your Post
controller should look like this:
module.exports = {
// GET request
find: function *() {
try {
this.body = yield Post.find(this.params);
} catch (error) {
this.body = error;
}
},
findOne: function *() {
try {
this.body = yield Post.findOne(this.params);
} catch (error) {
this.body = error;
}
},
// POST request
create: function *() {
try {
this.body = yield Post.create(this.request.body);
} catch (error) {
this.body = error;
}
},
// PUT request
update: function *() {
try {
this.body = yield Post.update(this.params.id, this.request.body);
} catch (error) {
this.body = error;
}
},
// DELETE request
delete: function *() {
try {
this.body = yield Post.destroy(this.params);
} catch (error) {
this.body = error;
}
}
};
Router prefix
Keep in mind routes can automatically be prefixed in ./config/general.json
with the prefix
key.
Let an empty string if you don't want to prefix your API. The prefix must starts with a /
, e.g. /api
.
Policies and route process
Just because a request matches a route address doesn't necessarily mean it will be passed to that route's target directly. The request will need to pass through any configured policies first. Policies are versatile tools for authorization and access control. They let you allow or deny access to your controllers down to a fine level of granularity.
Policies are defined in the policies
directory of every of your APIs.
Each policy file should contain a single function. When it comes down to it, policies are really just functions which run before your controllers. You can chain as many of them together as you like. In fact they're designed to be used this way. Ideally, each middleware function should really check just one thing.
For example to access DELETE /post/:id
, the request will go through the isAdmin
policy first.
If the policy allows the request, then the delete
action from the Post
controller is executed.
{
"routes": {
"DELETE /post/:id": {
"controller": "Post",
"action": "delete",
"policies": ["isAdmin"]
}
}
}
Do not forget to yield next
when you need to move on.