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:

  • Confusion Between Noun vs. Verb in Rest URLs
  • GitHub's usage of verbs (POST /gists/:id/star, DELETE /gists/:id/star): https://stackoverflow.com/a/19648997/1847482
  • Good point on needing to look for 'another object type': https://stackoverflow.com/a/2022938/1847482

  • 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

    上一篇: 如何建模改变状态的链接关系

    下一篇: 在RESTful URL中使用动词和形容词的替代方法