EnGoPy
EnGoPy

Reputation: 353

Rest api url design exceptions

I read some articles and posts regarding to correct (clean) url desing for rest endpoints. Anyway there are some doubts and unclear cases for me which I would like to discuss or be advised.

Situation

Lets say we have got a service, which has got registered users. To every users admin can attach custom notes which some text.

The problem which I would like to be advised is just simply CRUD endpoints, which might be trivial problem.

We will have 4 related endpoints:


POST (create)
According to some guidelines we might to design URL like:
/users/{userId}/notes
And send a payload containing details. No problems here


GET (read)
Similar case:
/users/{userId}/notes
As a response we receive list of notes attached to specific user. No problems here


UPDATE (update)
Similar case:
/users/{userId}/notes
As a payload server receive API object with all note details.
Here I have my first doubts. Since I receive note object which contains userId: value- should I go strictly with that URL pattern? userId is redundant in that case. Of course I can receive that value in PathVariable and in payload also, but is it a correct way? The same situation appear in many other CRUD's, that's why I would like to know "good practices"
API object:

{
    "id": 1,
    "userId": 2,
    "text": "Some message"
}

DELETE (delete)
Similar case:
/users/{userId}/notes/{noteId}
In fact for delete I would need only noteId information. As I think - /users/notes/{noteId} would be enough, but that's mean for DELETE operation I would have different URL. It's similar situation like in UPDATE case.


Question

Should I stick strictly to URL naming convention and use /users/{userId}/notes? What is a good practice for simply CRUD operations?

Upvotes: 0

Views: 79

Answers (2)

VoiceOfUnreason
VoiceOfUnreason

Reputation: 57239

You should review Webber 2011.

In REST, we don't have "endpoints", we have "resources". Your resource model is, in effect, a collection of documents, each with a unique identifier, than can be read (GET) and written (POST/PUT/PATCH).

Useful work in your domain model is a side effect that happens when somebody edits one of your resources.

Machines don't care what spelling conventions we use for our resource identifiers, so we usually choose a spelling that will make things easy for human beings; usually this means that the identifier is closely related to the name of the document.


Since I receive note object which contains userId: value- should I go strictly with that URL pattern?

Yes.

The broad point (emphasized by Webber in the talk linked above) is that HTTP is an application protocol; general purpose components can do useful work provided that we include the right description of what is going on in the request/response metadata.

In particular, the application has caching, and cache-invalidation. If you correctly identify which resource is being changed, caches can automatically invalidated previously cached responses.

This is one reason why we identify specific resources that are being modified by a request, rather than just POSTing all of our edits to a single generic resource.


Should I stick strictly to URL naming convention and use /users/{userId}/notes?

Yes; this is, in effect, like having a single web page that holds the notes for each user, with admins editing that web page (adding and removing notes).

Upvotes: 1

Harsh Gundecha
Harsh Gundecha

Reputation: 1197

  • Since this is an opinionated question so there's no one single answer to it.
  • But for the sake of good design this is what i prefer, as long as i can have unique ID for an entity like for notes in your case, it should be seen as an independent entity only.
  • suppose you need to play with entity X, you only need ID of X if you choose X/{id} and not IDs of all the things of which X might be child of, so again simply relying of ID of X is much simpler then relying on IDs of everyone from top parent up to X.
  • Imagine if you go towards users/{id}/notes/{id} design and then in future your notes require to add support for comments and likes and what not, In which case now urls will become users/{id}/notes/{id}/comment/{id} and this could go on since almost everything will be connected to a user by some logic.
  • Plus, depending upon language/framework building routes that are these much connected and nested could be complex to work with, specially for other team members.

Upvotes: 0

Related Questions