REST Url ID Placement for Resources with Collectio

2019-07-20 05:36发布

Is this a good structure for REST URLs?

Assuming:

GET /account  <- get list of accounts
GET /account/1234 <- get account 1234

etc.

If the account resource has a collection that I want to interface, is this a good idea?

GET /account/1234/note <- get notes for account 1234
POST /account/1234/note <- add note to account 1234
DELETE /account/1234/note/321 <- delete note 321 on account 1234

Especially that last one gives me pause; typically I wouldn't require both the entity ID and the parent ID when deleting.

Or maybe something like this would be better?

GET /account-note/1234 <- get notes for account 1234
POST /account-note/1234 <- add note to account 1234
DELETE /account-note/321 <- delete note 321 on account 1234 (b/c note 321 is on account 1234)

But then I'd end up with a pretty shallow URL set.

Thanks

3条回答
姐就是有狂的资本
2楼-- · 2019-07-20 06:17

There's nothing wrong with your first api. In large part, the idea of the RESTful interface is to go with the natural tree structure of the web, and your first approach is in keeping with that. It's also going to be a structure that does the API's job of abstracting away implicit constraints of your datastore, because the second approach implicitly assumes that the id of note is globally unique. This may be true now, and will probably remain true, but it's also exactly the kind of bug that suddenly appears with disastrous consequences when, down the line, some kind of major db change happens.

I'd go with your first scheme. It's a familiar rest pattern, it's intuitive, and it's not going to blow up in a weird way down the line. Also, in response to @Corwin01 minimize the query params--they're not so RESTful.

查看更多
狗以群分
3楼-- · 2019-07-20 06:19

Mind you, my experience is with JAX-RS and Jersey, so I'm not sure what the exact differences are.

However, this is what I would do:

    @GET
    @Path ("/account/note/{id}")
    public void displayNotes(@PathParam ("accountId") String accountId)
    {
      //do stuff
    }

    @POST
    @Path ("/account/note")
    public void addNote(@FormParam ("accountId") String accountId)
    {
      //do stuff
    }

    @POST
    @Path ("/account/note/delete")
    public void deleteNote(@FormParam ("accountId") String accountId, @FormParam ("noteId") String noteId)
    {
      //do stuff
    }

This way, you don't have cluttered and confusing URLs that the user doesn't need to see anyways, especially if the user tries to navigate there on their own. Which is ok for displaying the accounts, but would confuse them for the URLs that POST, since they would get a 404 and not understand why.

Keep it simple, and just user @FormParams since the user doesn't need to see that anyways.

查看更多
可以哭但决不认输i
4楼-- · 2019-07-20 06:21

I referenced this question in my comments on another question and between the feedback I got there and my own research this is what I've come up with.

Firstly, the question is sort of flawed. RESTful APIs, or to use the perferable term Hypermedia APIs should include the urls of related actions so that the interface is discoverable and changes won't break existing clients, therefore the exact structure has significantly less importance than I was placing on it, these can be changed later.

Secondly, the note in the example will be retrieved as part of an account query, maybe something like this:

<account>
   ...
   <notes>
      <note>
         ...
         <link href="/account-note/123" rel="note">
      </note>
   </notes>
</account>

The client will never be assembling urls to the account on their own, the client will use the link provided. Since the note ID is globally unique in this case, there is no need to include the key twice. Hence the answer to the question is no, the first example is not a good REST url structure, the second one is better. (Although still maybe not the best...)

查看更多
登录 后发表回答