开发者

Am I designing this WCF RESTful interface correctly?

开发者 https://www.devze.com 2023-04-05 04:13 出处:网络
I am creating a WCF webservice with WcF Authentication Service and the first set of functions I need is to manage an inbox for a client. The client will be determined by the authentication.

I am creating a WCF webservice with WcF Authentication Service and the first set of functions I need is to manage an inbox for a client. The client will be determined by the authentication.

This is my attempt at a RESTful design of the API:


https://api.mydomain.com/v1/inbox/messages (GET)

Returns a page of results in the inbox with an optional search filter applied

  • Count - number of records per page
  • Page - page to start on
  • Sort - (optional) field to sort on
  • Search - (optional) text to search for

https://api.mydomain.com/v1/inbox/mark (POST)

Marks one or more messages read or unread

  • Action - MarkRead or MarkUnread
  • MessageIDs - list of Message IDs to mark

https://api.mydomain.com/v1/inbox/archive (POST)

Archives one or more messages

  • MessageIDs - list of Message IDs to archive

Am I doing this right? If 开发者_C百科not, what would be a better way to design this interface?


Martin Fowler has a good summary of the Richardson Maturity Model and what it takes to make a RESTful service. Jan referenced one of Roy Fielding's posts, but there are some steps to take care of in addition to hypermedia (and HATEOAS).

With reference to the Richardson model, I think your API would need some changes to get to "Level 3" (duh duh duhhhh). The /v1/inbox/messages collection looks sound, and only supporting GET indicates that it's a read-only resource to the user. However POSTing actions and IDs to the /v1/inbox/mark and /v1/inbox/archive is only tunneling RPC-style services over HTTP - "Level 0" in the article.

I'd suggest something like the following as being a naive, non-hypermedia (i.e. "Level 2") API:

  • To retrieve a list of summary information of all of the messages (in all folders):

    GET /v1/messages HTTP/1.1
    Host: api.mydomain.com
    

    Response:

    content-type: text/xml
    
    <?xml version="1.0"?>
    <messages>
      <message subject="Subject" unread="true" id="1234" folder="inbox" />
      <message subject="Hello, world" unread="false" id="24" folder="inbox" />
      ...
    </messages>
    
  • To retrieve a full message:

    GET /v1/messages/1234 HTTP/1.1
    Host: api.mydomain.com
    

    Response:

    content-type: text/xml
    
    <?xml version="1.0"?>
    <message subject="Subject" unread="true" id="1234" folder="inbox">
      Hi, this is the message.
    </message>
    
  • To edit a message (e.g. to mark it as read and move it to the archive folder):

    POST /v1/inbox/messages/1234 HTTP/1.1
    Host: api.mydomain.com
    content-type: text/xml
    
    <?xml version="1.0"?>
    <message id="1234" unread="false" folder="archive" />
    

    Note: here I'm intentionally using POST instead of PUT to indicate a partial update.

Other things that stand out as needing attention are:

  • Hypermedia responses and media types. Frankly this is better explained by others (e.g. the REST In Practice book, or the InfoQ Coffee Cup example by the same authors), but in short your responses should indicate to the client what other actions might be possible from the response to their most recent request, and allow them to discover the entire API from just a single URI. As an example, there is an implication of folders collections above. If GET /v1/messages/1234 returned:

    <message subject="Subject" unread="true" id="1234" folder="inbox" >
      Message text here.
    
      <link rel="folder" href="http://api.mydomain.com/v1/folders/inbox" />
    </message>
    

    then the client would have a concrete example of a URI to try an OPTIONS on, and a good idea of what might be there.

  • Response codes and content: 200 OK is obvious. Respond with 403 Forbidden if the user is not authorized to view a particular message, 404 Not Found if the message ID doesn't exist. Every time you return an error, give the client some indication of how to correct their request (if at all possible).


Regarding to read/unread part I do not think you need a post. I think you need put method https://api.mydomain.com/v1/inbox/messageId/Read https://api.mydomain.com/v1/inbox/messageId/Unread

Post needed when creating a new record and you want to update

For archive part I am agree. Just remember to return result for the archiving process.


Roy's POST is helpful when facing such questions: http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven

Hence: focus on defining media type(s) instead of coupling your clients to predefined sets of URIs. They need not be registered, to be useful, BTW.

Maybe also see http://www.nordsc.com/ext/classification_of_http_based_apis.html#http-type-one

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号