2

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.

Community
  • 1
  • 1
A. Ly
  • 33
  • 6

3 Answers3

3

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.

Steve H.
  • 6,912
  • 2
  • 30
  • 49
2

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.

Jonathan W
  • 3,759
  • 19
  • 20
0

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!

shahshi15
  • 2,772
  • 2
  • 20
  • 24
  • My examples are about messages, but it can return all related calculated data of related resources of a "case". All these calculated data results are returned as generic as possible, but the results are aimed to create analysis tools (like graphs and stuff). For every graph-style they need another results. That's why I seperated this for every case by: _/analysis/a-graph-data-result-style_ – A. Ly Dec 18 '13 at 08:56
  • That's the point, you shouldn't. As Steve mentioned above, urls should not be declarative. If you want your return types to be graph style related, you could have something like this as well: GET http://example.com/analysis/{graph-style}/cases/{id}/messages?receiver=testuser1&sender=testuser2 Looking at the urls clients can easily determine that the data model might not change (here the data format is always going to be that of "messages") but the data itself will change depending on the graph-style they ask the data for. – shahshi15 Dec 18 '13 at 16:15
  • But in most cases, you, as a service provider, SHOULD NOT have to worry about what kind of graph style the client is implementing. Facebook/Google probably has a gazillion applications developed by clients each implementing their own set of graphs (depending on the usecase ofcourse). If they start providing graph style custom data for EACH client, that wouldn't make sense for any service provider. – shahshi15 Dec 18 '13 at 16:20
  • That is a good point. So I'm thinking how the URL should look like when I want to get the calculated data from the messages. One of the possibilities is to let the client calculate this data by getting all the messages: example.com/cases/{id}/messages and then calculate to the result set I want (like my example). Actually it could be heavy for the client side. So what is the best solution to make a RESTful query to get the result set with the attributes "sender", "receiver", "amount_messages"? Data objects are including ALL sender/receiver combinations (with amount_messages) inside a "case". – A. Ly Dec 18 '13 at 21:12
  • I don't think I understand your concern. If you want to handle the logic of calculating this data by yourself, you still could. Your calculations and logic handling has nothing to do with the REST urls you design/structure. They both are totally independent. It's a matter of how your clients would know what url is for what (with the urls designs i mentioned above) – shahshi15 Dec 18 '13 at 22:39