質問

I am working on a ticketing system. The user in system are organised in one level hierarchical way. There are many teams and each team has one manager and each user in the team has one and only one manager. A ticket can be created by any user in team. I have the following use case:

  1. A user can see only the tickets created by him
  2. A manager can see all the tickets created by the team

For case(1) I am thinking about the following API endpoint:

/api/tickets vs /api/users/:id/tickets

For case(2) I am thinking on the following pattern:

/api/tickets?manager=true vs /api/users/:id/tickets

for the later case on the server side I can check if the user is the manager, if yes then he gets to see all the tickets of his team else just his own.

In both the cases the first choice is possible because Spring maintains its own session of authenticated user hence sending user id in each request feels redundant but I read that the endpoints are designed in stateless fashion.

So, the question is which scheme makes more sense and should I rely on the framework like Spring to provide me the details or I should design my API endpoints in a stateless fashion although it seems redundant?

役に立ちましたか?

解決

Deciding on the correct RESTful URL design

Remember:

  1. REST doesn't care what spellings you use for your identifiers.
  2. "Resources" are integration resources, not domain entities.

So, the question is which scheme makes more sense and should I rely on the framework like Spring to provide me the details or I should design my API endpoints in a stateless fashion although it seems redundant?

If you were creating a web site, how would you do it? From there, think about how you would do it with a machine readable web site. Presto! you have yourself a REST api.

You would probably have some sort of a home page, with a link on it saying something like "My Tickets". For the operators, it would be a view with perhaps a heading and a list element with their own tickets in it. For the managers, it might be the same view, but with an additional link to another page that includes the overview of the teams tickets, or it might be the original view with additional elements that show the team's work.

A key idea of REST is that the client and server have a common understanding of the media type, which is to say the processing rules, which can include support for optional elements. The server guides the client by choosing which elements to provide in the representation.

This suggests that a given entity in your domain model might have more than one "current" representation. So you could achieve that with two different resources, each of which doing a particular mapping from the current state to a representation.

So Bob's requests could be redirected to the resource for individual contributors

GET /myTickets
Authorization: "Bob"

302 Found
Location: /03ea42b9-58ad-47cf-bff0-47619253a362

But Alice's requests could be redirected to the resource for managers

GET /myTickets
Authorization: "Alice"

302 Found
Location /ac78f4ee-752f-4c3c-adfa-54ead639823f

Just like the way we do things in the web, the clients don't care what the spellings of the URI should be; they just follow the links that are provided to them.

So in your first example

GET /api/tickets
Authorization: ...

302 Found
Location: /api/users/:id/tickets

Is perfectly fine. For managers, you could analogously do

GET /api/tickets
Authorization: ...

302 Found
Location: /api/managers/:id/tickets

/api/tickets?manager=true

REST doesn't care about spelling, but relative references do; dot-segments are fine for paths, but there's no analogous spelling that allows you to move around on the path while preserving the query. In other words, if you have a lot of related resources, it's more useful to have them share a common path than a common query.

GET /api/tickets?manager=true
Authorization: ...

302 Found
Location: /api/managers/:id/tickets

Is perfectly fine too.

他のヒント

VoiceOfUnreason did cover most of the parts you asked with one question remaining:

What about the Spring issue? if the RESTful URLs needs to be stateless then I need to tell in the URL who is the user, right? because suppose in future I decide to not to use Spring or not store session then I have to change the whole URL scheme, makes sense?

Yes this would be the case, if you would remove the session part you would have to redesign the endpoints. In the answer above you see actually how VoiceOfUnreason solved this.

Logging into the application with an authorization might provide the user with the link to the location of his tickets. In his example the controller might check a) the authorization and b) check the rules of the user. In turn it returns either /api/{manager|user}/:user_id/tickets. So a request of a specific user with the authorization code will always point to the user's tickets.

Other viable options might be...

  • Building a single tickets endpoint with the following parameter tickets?user_id=x - After logging in your API will return a link to either /tickets for managers or /tickets?user_id=xif its a normal user to see his tickets.
  • Build /tickets and /users endpoints with:
    • /tickets providing a list of all tickets if you are a manager (and a redirect to /users/:id/tickets if not.)
    • /tickets/:id providing a lone ticket
    • /users/:id/tickets providing the tickets you created

Your options here are basically open ended, you just have to pick your poison and stick with it. Also there was a question on Stackoverflow about session use in RESTful services, you should check out the discussion here

Additionally you could also take a look at the HATEOAS architecture paradigm. It basically describes that client and server can be decoupled by providing further information on which actions are possible. This can be roughly seen as building something akin to a state machine and might clear up some confusion as well. This is also roughly what VoiceOfUnreason already did with the Found responses.

ライセンス: CC-BY-SA帰属
所属していません softwareengineering.stackexchange
scroll top