None of this is authoritative (as REST has no exact meaning). But from the original paper on REST a full (not ending in /) URL names a resource, while one ending in a slash
'/' is a resource group (probably not worded like that).
A GET of a URL with a slash on the end is supposed to list the resources available.
GET http://example.com/dogs/ /* List all the dogs resources */
A PUT on a URL with a slash is supposed to replace all the resources.
PUT http://example.com/dogs/ /* Replace all the dogs resources */
A DELETE on a URL with a slash is supposed to delete all the resources
DELETE http://example.com/dogs/ /* Deletes all the dogs resources */
A POST on a URL with a slash is supposed to create a new resource can then be subsequently accessed. To be conformant the new resource should be in this directory (though lots of RESTful architectures cheat here).
POST http://example.com/dogs/ /* Creates a new dogs resource (notice singular) */
etc.
The wiki page on the subject seems to explain it well:
See example https://en.wikipedia.org/wiki/Representational_state_transfer#Applied_to_Web_services.
Disclaimer
Despite the question has been scoped as REST, the truth is that it has nothing to do with REST.
Long story short, how to map the request parameters to an specific query language is implementation details. So, for now, lets leave REST aside.
Is the above implementation/concept correct?
For us to say whether is correct or not, we would need to be familiar with the project and its requirements. So far, what we can say is: the solution is not flexible.
Flexible in the sense of scaling in the long run. Every new filter
would take you (at least) to modify the controller
, the service layer and maybe the data access layer too. From the management standpoint, is hard to buy so much work for so little feature. In other words, the maintenance looks expensive.
Nevertheless, it depends on how often you add new parameters to the query.
So what am I doing wrong here?
You are missing two possible abstractions.
- The one that maps a dynamic set of request parameters to an specific model of the API.
- The one that maps the previous model to your specific query language.
Note: Some frameworks makes #1 optional.
Right now the mapping is hardcoded as a if/else
block. Too rigid for scaling well.
Instead, It could be similar to:
myController(req,res){
var query = new QueryParametersMapper(req);
var page = new PageParametersMapper(req);
var sort = new SortParametersMapper(req);
var dataSet = myRepository.find(query, page, sort);
// etc...
}
What's the correct way of handling queries?
Making the mapping more dynamic and reusable.
At this point, my first advice would be look for libraries compatible with your framework or programming language.
My second advice would be, pick the one that supports Convention over configuration.
Even if It doesn't prevent you from making changes, at least (I'm sure) the costs of the changes will be lesser than they are now.*
* If we consider the code given as example in the question.
Best Answer
If, instead of api endpoints, these were web pages on a web site, how would you arrange them?
If you guessed wrong, or worse yet had to somehow do it more than one way, what would you do?
In most cases, the answer is: you would create more documents, and add extra links to help people reliably find the document that is best for them.
Think about it: how many different Hemingway web pages are there on the internet?
Your REST API is an attempt to disguise your domain model as a web site. Let the web be your guide.