A. Ly
A. Ly

Reputation: 33

REST resource related data

I've created a REST API and I think I'm stuck with a RESTful issue.

It's related with the following questions:

I have a resource called "cases". Cases have also related data, like users and messages. The problem is that I want to get the related queried users and messages data from a case, but I'm not sure with the URI design. There are also different kinds of related/calculated data. These related data should be used to create data visualization.

How I get cases/users/messages are RESTful though:

http://example.com/cases (and with id for a single case)
http://example.com/cases/{id}/users (same idea as above)
http://example.com/cases/{id}/messages (same idea as above)

My first thoughts to create related resources are (I think URI looks wrong, it's maybe getting a bit RPC?):

Related data 1:

http://example.com/cases/{id}/analysis/messages-network-traffic

{
    "sender": "an user jack", 
    "receiver": "an user steph", 
    "amount_messages": 51
}, 
{
    "sender": "an user test", 
    "receiver": "an user test4", 
    "amount_messages": 3
}
...

Related data 2:

http://example.com/cases/{id}/analysis/messages-timeline?receiver=testuser1&sender=testuser2
{
    "amount_messages": 24, 
    "timestamp": 1387321576
}, 
{
    "amount_messages": 50, 
    "timestamp": 1387321576
}
...

Are these correct thinking of URI design (I think it's kind of RPC though), or how should I do? Because I don't see any reason to CREATE a report resource like the related questions. The data is just a calculation of the existing resources.

Thank you in advance.

Upvotes: 2

Views: 2012

Answers (3)

Jonathan W
Jonathan W

Reputation: 3799

I realize you've already accepted an answer here, but I feel that both answers miss the mark a bit.

Designing a RESTful solution to your problem has nothing to do with what your URLs look like and everything to do with providing links to relations as part of the representation itself. You need to use a media type that allows you to express these link relations. HTML does, but XML and JSON do not by themselves. My personal favorite is HAL over JSON.

Here's what your example might look like using HAL over JSON:

Request:

GET /cases/1 HTTP/1.1
Host: example.com

Response:

HTTP/1.1 200 OK
Content-Type: application/hal+json;profile=vnd/com.example-v1

{
  _links: {
    "self": {
      href: "/cases/1"
    },
    "users": {
      href: "/cases/1/users"
    },
    "newest_user": {
      href: "/users/371629"
    },
    "messages": {
      href: "/cases/1/messages"
    }
  },
  "case-name": "Foo",
  "case-created-date": "2013-11-01"
  ..... <more case attributes here>
} 

Notice that the link to "newest_user" points to a single user, and that the reference is opaque (i.e., you wouldn't have been able to guess it without the server giving you that value). Technically, all URLs should be treated as opaque in an architecture like this (even if some of them are human readable and organized in the resource/id/subresource sort of way).

So when you go to write your API guide, you can specify what each of the link relations mean (users, newest_user, and messages in this case), and clients will know what they get when they follow each link, regardless of what the URL looks like.

By the way, this type of information is known in REST world as Hypermedia As The Engine Of Application State, a.k.a. "the hypermedia constraint." It's a requirement of the uniform interface constraint of REST.

Upvotes: 2

shahshi15
shahshi15

Reputation: 2987

Your these urls seem fine :

http://example.com/cases (and with id for a single case)

http://example.com/cases/{id}/users (same idea as above)

http://example.com/cases/{id}/messages (same idea as above)

In terms of your related data and how to query them, I'd suggest that first of all you should decide on the return data structure, considering the fact that in both cases you are returning "messages" (although containing somewhat different data). What I would do is, I would have a common json structure for both related resources urls something along the lines of

{"sender": "an user test",

"receiver": "an user test4",

"amount_messages": 3,

"timestamp": 12312421424}

And my resource urls would look somewhat like this:

GET http://example.com/cases/{id}/messages

GET http://example.com/cases/{id}/messages?receiver=testuser1&sender=testuser2

I don't understand the reason for that "/analysis" in the url. It's a bit more redundant (unless ofcourse there is a very specific reason for it). The clients who are going to use your apis are expecting the return data to be generic, especially when they are trying to do filter queries on the same resource. In your case, we are either listing "message traffic" (which I would call listing "all messages") OR listing "message traffic" WHERE sender is FOO and receiver is BAR (which I would call filtering the "all messages" data by sender and receiver information.

Keeping the return data model consistent helps client developers to generate POJOs (in java land) and/or consistent data models on their side as well.

I hope this helps ! good luck!

Upvotes: 0

Steve H.
Steve H.

Reputation: 6947

Just because you can provide an implementation doesn't mean it makes sense to do so. For example, performing a PUT on http://example.com/cases probably doesn't make sense. You would PUT instead to http://example.com/cases/1 or something like that. A specific instance. Likewise, performing a POST on http://example.com/cases/1 probably doesn't make sense either. It is up to you to decide the semantics of your application, using the syntax of REST.

I don't see anything wrong with your REST design- As long as the endpoints are named in a 'declarative' fashion, then it is OK. If they had some 'procedural' name, like: http://example.com/cases/goDoSomething, that would be a cause for concern.

Remember your REST design is the "language" your clients use to talk to your services, so design that language so that communication is declarative and suited for the task at hand. Design for the USERS, not for your own convenience in the backend.

Upvotes: 3

Related Questions