Alternatives of using verbs and adjectives in RESTful URL
I want to add actions to my REST API that would move 'resources' between different 'stores'.
For instance, suppose my resources are normally accessed by the following URL:
/resources
/resources/{resourceId}
Now suppose I want to 'deactivate' some resource, ie conceptually move it to another sub-folder. The most straightforward way to allow this would be as followed.
'Deactivate' the resource, ie cause it to be unavailable under /resources. Conceptually, it 'moves' the object to the '/resources/deactivated/' subfolder:
POST /resources/{resourceId}/deactivate
Or alternatively:
POST /resources/deactivated/{resourceId}
Get all the deactivated objects:
GET /resources/deactivated
Reverse the 'deactivate' action, ie conceptually move the object from the '/resources/deactivated/' subfolder back to the main one ('/resources').
Either
POST /resources/{resourceId}/reactivate
Or
POST /resources/deactivated/{resourceId}/restore
This API seems rather intuitive for me. But it seems to violate the 'prefer nouns' rules that I have seen in many best practices-articles on REST API: I use verbs and adjectives instead of nouns!
Note that I might have parameters for all the endpoints, eg GET /resources/deactivated?createdBefore=01022017
Are there any better alternatives for my REST API? Ie more RESTful, but not less intuitive ones?
Good resources that I could find on the topic:
First of all, remember that REST stands for Re presentational S tate T ransfer.
It is all about resources and their state. Operations such as activate, deactivate and move are all about replacing the current state of the resource with a new representation and you don't need verbs in the URL to express such operations.
For example, to replace a status of a resource, you can send a new representation of the resource in the payload of a PUT
request:
PUT /api/resources/[id]/status HTTP/1.1
Host: example.org
Content-Type: application/json
{ "status" : "active" }
It can be understood as replace the status of the resource identified by [id]
with the one sent in the request payload.
Then you could have the following to get the resources with a particular status:
GET /api/resources?status=active HTTP/1.1
Host: example.org
Accept: application/json
It can be understood as give me a representation of all resources with the status active
.
To move a resource to another folder, for example, you could have:
PUT /api/resources/[id]/folder HTTP/1.1
Host: example.org
Content-Type: application/json
{ "target" : "draft" }
It can be understood as replace the folder of the resource identified by [id]
with the one sent in the request payload.
Is an active resource really that different than a deactivated resource? Consider just having a property that tracks active
ness. You can always filter them out, such as
GET /things?active=true
You can alter just that property with a microPUT
PUT /things/{id}/active
false
If a thing
and a deactivated-thing
are conceptually different, it's reasonable to have two separate endpoints. I would move between them using
POST `/deactivated-things`
{
"thing": "/things/12"
}
and
POST `/things`
{
"deactivated-thing": "/deactivated-things/12"
}
You should try to avoid a path having multiple meanings. For example, don't do this:
/resources/{id}
/resources/deactivated/{id}
Don't overload the meaning of the path segment after /resources
.
Thanks Cassio for emphasizing the 'changing the object state' approach.
My own answer for completeness:
PATCH /resources/{resourceId} with body {"active":false} -- deactivate a resource
PATCH /resources/{resourceId} with body {"active":true} -- restore a resource
GET /resources -- return all 'normal' resources
GET /resources?includeInactive=true -- return all resources including the deactivated ones
GET /resources/{resourceId} -- return the resource
(The resources retrieved by 'GET' will contain the attribute 'active=true/false').
Seems like a classic case for PATCH: REST API PATCH or PUT
链接地址: http://www.djcxy.com/p/40962.html上一篇: 如何建模改变状态的链接关系