1

This question relates to a somewhat more specific case than the one discussed in How can I create a RESTful calculator?

It should be assumed that the values to be calculated are not simple integers, but large and complex puzzles. Such a puzzle can also contain several subpuzzles. Both can be stored/read as resources on/from a server, like:

GET /myApi/puzzle/{puzzleID}
GET /myApi/puzzle/{puzzleID}/subpuzzle/{subpuzzleID}

Afterwards, clients can trigger a calculation of them on the server. As in the above link, the resources would be located in the body of a POST request. Instead of getting and sending the puzzles, i want to refer to the already existing ones on the server. My current solution is to reference them via their URI.

This request triggers a calculation of the puzzle (and all contained subpuzzles) with ID=123:

Request:
POST /myApi/puzzleSolver
Content-Type: text/plain

/myApi/puzzle/123

This request triggers just a calculation of the subpuzzle with ID=321 in the aforementioned puzzle:

Request:
POST /myApi/puzzleSolver
Content-Type: text/plain

/myApi/puzzle/123/subpuzzle/321

Is it advisable to directly specify the resource URI in the request body - am I missing any pitfalls? Is there a better alternative, e.g. to use the puzzleID and subpuzzleID?

5
  • What is the point of /myApi/puzzleSolver? Why don't you just request the result of the puzzle itself, something like /myApi/puzzle/123/result It seems like a puzzleSolver resource is completely unnecessary? Unless I'm missing something Sep 6, 2019 at 14:33
  • @CormacMulhall: I considered this approach in the beginning, but this would create an unpleasant redundancy in my case (/myApi/puzzle/123/result and /myApi/puzzle/123/subpuzzle/321/result). I could also think of even more deeply nested scenarios, e.g. a calculator for the electricity consumption of countries, communities, villages and individual houses. It is definitely also a possibility, but due to the hierarchical structure, I prefer the approach with the puzzleSolver. Sep 6, 2019 at 14:59
  • It is not a redundancy though. In either system you will have a result resource for each puzzle and sub-puzzle. But with the puzzleSolver design that resource doesn't have a URL and is undiscoverable (ie you can't link or navigate to it). You POST to another faux-resource to get the resource you actually want. URLs are unique resource locators, your resources should all have their own URL that uniquely identifies them and only them. A God resource that can return lots of different resources is a REST anti-pattern. Anyway my 2 cents, if you don't like it you don't like it Sep 6, 2019 at 15:13
  • @CormacMulhall: Thank you for your reply. I will reconsider this approach. However, the client interaction in your solution is still unclear to me. As the calculation is a long-running task, I think a request with GET is inappropriate. First, the calculation should be triggered through a POST request, but the URL /myApi/puzzle/123/result feels wrong for that?! Despite, the URL can serve for a final GET request to get the result, as soon as the task is completed. That is my current (non-expert) view on this. Sep 6, 2019 at 19:13
  • I'm assuming once a puzzle is calculated it doesn't have to be calculated again, that the result can be cached. In that case if it takes longer than the length of a HTTP timeout to calculate the first time you could return a 503 to the GET with a Retry-After header that gives an estimate of when the server will be ready. Ultimately the client shouldn't care about any work the server is doing to produce the resource. It just cares about the resource. If it can't get it right now it only cares about when it can get it. REST is designed to de-couple client from server implementation Sep 7, 2019 at 8:39

2 Answers 2

1

Specifying a url is not a good way of identifying a resource.

Internally your puzzle solver code will be abstracted from the puzzle retrieval code. It may not even use a REST resource to retrieve the puzzles. Maybe it goes directly to a database. Maybe its using version 2 of the api and the path has changed.

The resource url domain, path and structure are not concerns of the puzzle calculator. It will call puzzleRepo.GetPuzzle(123) or something and therefore have to extract the puzzle id from your url. Therefore you should send just the ids of the puzzles in the body of the request

POST /api/CalculatePuzzleResult
{
   "PuzzleId":"123",
   "IncludeSubPuzzles" : true
   //whatever other data is required
}
5
  • True, it's likely that somebody has to parse the ID from the URL. IMO, better for the server who is the knowledge expert, than the client. Your solution forces two modules to understand the structure of the URL.
    – user949300
    Aug 30, 2019 at 15:09
  • the client knows what puzzle it wants to be solved. the solver doesnt know anything about the puzzle api
    – Ewan
    Aug 30, 2019 at 15:21
  • My point is that the solver defines the API (assuming I understand this question correctly, which I'm beginning to doubt :-) ). So the solver knows how to parse / extract the ID. Should the format of the URL change, only the solver code needs to change.
    – user949300
    Aug 30, 2019 at 18:31
  • even if the solver and the puzzle api are the same, it dosent nessecerally know the full path. say its behind an api gateway or something. plus even if the hosting layer understands the path, you wouldnt use the same path binding to decode paths as strings in the data
    – Ewan
    Aug 30, 2019 at 18:34
  • @Ewan: Thank you, your argument sounds very conclusive to me. The solver can't really do anything with the URL and usually only understands/needs the ID. Sep 2, 2019 at 19:30
1

Using the resource paths in requests looks very reasonable. It's immediately obvious what they mean, and parsing shouldn't be more difficult than alternative formats. If you want to unify stored and ad-hoc puzzles, you could use JSON payload somewhat like this:

(stored)

{
  "link":"/myApi/puzzle/123"
}

(ad-hoc)

{
  "field1":"puzzle data",
  ...
}

But that's just one possible way to do it. Another option would be to use different content-type values for links to stored puzzles versus ad-hoc puzzles, but I didn't spontaneously find a MIME type for resource links, so maybe there's no such thing.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.