Subresource and path variable conflicts in REST?

2019-06-24 02:00发布

问题:

Is it considered bad practice to design a REST API that may have an ambiguity in the path resolution? For example:

GET /animals/{id}   // Returns the animal with the given ID
GET /animals/dogs   // Returns all animals of type dog

Ok, that's contrived, because you would actually just do GET /dogs, but hopefully it illustrates what I mean. From a path resolution standpoint, it seems like you wouldn't know whether you were looking for an animal with id="dogs" or just all the dogs

Specifically, I'm interested in whether Jersey would have any trouble resolving this. What if you knew the id to be an integer?

回答1:

"Specifically, I'm interested in whether Jersey would have any trouble resolving this"

No this would not be a problem. If you look at the JAX-RS spec § 3.7.2, you'll see the algorithm for matching requests to resource methods.

[E is the set of matching methods]...

Sort E using the number of literal characters in each member as the primary key (descending order), the number of capturing groups as a secondary key (descending order) and the number of capturing groups with non-default regular expressions (i.e. not ‘([^ /]+?)’) as the tertiary key (descending order)

So basically it's saying that the number or literal characters is the primary key of which to sort by (note that it is short circuiting; you win the primary, you win). So for example if a request goes to /animals/cat, @Path("/animals/dogs") would obviously not be in the set, so we don't need to worry about it. But if the request is to /animals/dogs, then both methods would be in the set. The set is then sorted by the number of literal characters. Since @Path("/animals/dogs") has more literal characters than @Path("/animals/"), the former wins. The capturing group {id} doesn't count towards literal characters.

"What if you knew the id to be an integer?"

The capture group allows for regex. So you can use @Path("/animals/{id: \\d+}"). Anything not numbers will not pass and lead to a 404, unless of course it is /animals/dogs.