mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-12-20 01:03:23 +03:00
f802128cfc
no issue - email analytics may be desirable to fully switch off in certain circumstances, when that happens we want to prevent related background jobs from running and expose the feature flag via the config endpoint in the Admin API so that clients can adjust accordingly |
||
---|---|---|
.. | ||
canary | ||
shared | ||
v2 | ||
index.js | ||
README.md |
API Versioning
Ghost supports multiple API versions. Each version lives in a separate folder e.g. api/v2, api/v3, api/canary etc. Next to the API folders there is a shared folder, which contains shared code, which all API versions use.
Stages
Each request goes through the following stages:
- input validation
- input serialisation
- permissions
- query
- output serialisation
The framework we are building pipes a request through these stages in respect of the API controller configuration.
Frame
Is a class, which holds all the information for request processing. We pass this instance by reference. Each function can modify the original instance. No need to return the class instance.
Structure
{
original: Object,
options: Object,
data: Object,
user: Object,
file: Object,
files: Array
}
Example
{
original: {
include: 'tags'
},
options: {
withRelated: ['tags']
},
data: {
posts: []
}
}
API Controller
A controller is no longer just a function, it's a set of configurations.
Structure
edit: function || object
edit: {
headers: object,
options: Array,
data: Array,
validation: object | function,
permissions: boolean | object | function,
query: function
}
Examples
edit: {
headers: {
cacheInvalidate: true
},
// Allowed url/query params
options: ['include']
// Url/query param validation configuration
validation: {
options: {
include: {
required: true,
values: ['tags']
}
}
},
permissions: true,
// Returns a model response!
query(frame) {
return models.Post.edit(frame.data, frame.options);
}
}
read: {
// Allowed url/query params, which will be remembered inside `frame.data`
// This is helpful for READ requests e.g. `model.findOne(frame.data, frame.options)`.
// Our model layer requires sending the where clauses as first parameter.
data: ['slug']
validation: {
data: {
slug: {
values: ['eins']
}
}
},
permissions: true,
query(frame) {
return models.Post.findOne(frame.data, frame.options);
}
}
edit: {
validation() {
// custom validation, skip framework
},
permissions: {
unsafeAttrs: ['author']
},
query(frame) {
return models.Post.edit(frame.data, frame.options);
}
}