Exposing database query parameters via REST interface - rest

I have the basics of a REST service done, with "standard" list and GET/POST/PUT/DELETE verbs implemented around my nouns.
However, the client base I'm working with also wants to have more powerful operations. I'm using Mongo DB on the back-end, and it'd be easy to expose an "update" operation. This page describes how Mongo can do updates.
It'd be easy to write a page that takes a couple of JSON/XML/whatever arguments for the "criteria" and the "objNew" parts of the Mongo update function. Maybe I make a page like http://myserver.com/collection/update that takes a POST (or PUT?) request, with a request body that contains that data. Scrub the input for malicious querying and to enforce security, and we're done. Piece of cake.
My question is: what's the "best" way to expose this in a RESTful manner? Obviously, the approach I described above isn't kosher because "update" isn't a noun. This sort of thing seems much more suitable for a SOAP/RPC method, but the rest of the service is already using REST over HTTP, and I don't want users to have to make two different types of calls.
Thoughts?

Typically, I would handle this as:
url/collection
url/collection/item
GET collection: Returns a representation of the collection resource
GET collection/item: Returns a representation of the item resource
(optional URI params for content-types: json, xml, txt, etc)
POST collection/: Creates a new item (if via XML, I use XSD to validate)
PUT collection/item: Update an existing item
DELETE collection/item: Delete an existing item
Does that help?

Since as you're aware it isn't a good fit for REST, you're just going to have to do your best and invent a standard to make it work. Mongo's update functionality is so far removed from REST, I'd actually allow PUTs on the collection. Ignore the parameters in my examples, I haven't thought too hard about them.
PUT collection?set={field:value}
PUT collection?pop={field:1}
Or:
PUT collection/pop?field=1

Related

How should I design a REST API

I'm thinking about a REST API design. There are several tables in my database. For example Customer and Order.
Of course - each Order has its Customer (and every customer can have many Orders).
I've decided to provide such an interface
/api/v1/Customers/ -- get list of Customers, add new Customer
/api/v1/Customers/:id: -- get Customer with id=:id:
/api/v1/Orders/ -- get list of Orders, add new Order
/api/v1/Orders/:id: -- get Order with id=:id:
It works flawlessly. But my frontend has to display a list of orders with customer names. With this interface, I will have to make a single call to /api/v1/Orders/ and then another call to /api/v1/Customer/:id: for each record from the previous call. Or perform two calls to /api/v1/Orders/ and /api/v1/Customers/ and combine them on the frontend side.
It looks like overkill, this kind of operation should be done at the database level. But how can/should I provide an appropriate interface?
/api/v1/OrdersWithCustomers
/api/v1/OrdersWithCustomers/:id:
Seems weir. Is it a right way to go
There's no rule that says you cannot "extend" the data being returned from a REST API call. So instead of returning "just" the Order entity (as stored in the backend), you could of course return an OrderResponseDTO which includes all (revelant) fields of the Order entity - plus some from the Customer entity that might are relevant in your use case.
The data model for your REST API does not have to be an exact 1:1 match to your underlying database schema - it does give you the freedom to leave out some fields, or add some additional information that the consumers of your API will find helpful.
Great question, and any API design will tend to hit pragmatic reality at some point like this.
One option is to include a larger object graph for each resource (ie include the customer linked to each order) but use filter query parameters to allow users to specify what properties they require or don't require.
Personally I think that request parameters on a restful GET are fine for either search semantics when retrieving a list of resources, or filtering what is presented for each resource as in this case
Another option for your use case might be to look into a GraphQL approach.
How would you do it on the web?
You've got a web site, and that website serves documents about Customers, and documents about Orders. But your clients aren't happy, because its too much boring, mistake-prone work to aggregate information in the two kinds of documents.
Can we please have a document, they ask, with the boring work already done?
And so you generate a bunch of these new reports, and stick them on your web server, and create links to make it easier to navigate between related documents. TA-DA.
A "REST-API" is a facade that makes your information look and act like a web site. The fact that you are generating your representations from a database is an implementation details, deliberately hidden behind the "uniform interface".

Why we need GraphQL when we can query for a specific field in REST?

GraphQL's principle aim is to solve overfetching problem as faced by many REST APIs and it does that by querying for only specific fields as mentioned in the query.
But in REST APIs, if we use the fields parameter, it also does the same thing. So why need GraphQL if REST can solve overfetching like this?
The option to fetch partial fields is only one of the key features of GraphQL, but not the only one.
One other important advantage is the 'graphic' nature of the model. By treating your schema as a graph (that is, several resources tied together by fields), it allows you to fetch a complex response, constructed of several data types in a single API call. This is a flexibility that you don't have in a standard REST API
Both these features can obviously be done by rest as well, but GraphQL gives it in a much simpler and more intuitive way.
Take a look at this post, there's a fairly good explanation there of the advantages (and disadvantages) of GraphQL.
https://www.altexsoft.com/blog/engineering/graphql-core-features-architecture-pros-and-cons/
When you have a REST setup, you're typically returning a whole JSON representation for each endpoint. This includes all fields that you may or may not need which leads to more data usage or more HTTP calls (if you divide your RESTful API up, that is).
GraphQL on the other hand gives you exactly what you're asking for when you query with a single POST/GET request.

REST Best practise for filtering and knowing the result is singular: List or single?

Variety of REST practises suggest (i.e. 1, 2, 3) to use plurals in your endpoints and the result is always a list of objects, unless it's filtered by a specific value, such as /users/123 Query parameters are used to filter the list, but still result in a list, nevertheless. I want to know if my case should 'abandon' those best practices.
Let's use cars for my example below.
I've got a database full of cars and each one has a BuildNumber ("Id"), but also a model and build year which combination is unique. If I then query for /cars/ and search for a specific model and year, for example /cars?model=golf&year=2018 I know, according to my previous sentence, my retrieve will always contain a single object, never multiple. My result, however, will still be a list, containing just one object, nevertheless.
In such case, what will be the best practise as the above would mean the object have to be extracted from the list, even though a single object could've been returned instead.
Stick to best practises and export a list
Make a second endpoind /car/ and use the query parameters ?model=golf&year=2018, which are primarily used for filtering in a list, and have the result be a single object, as the singular endpoint states
The reason that I'm asking this is simply for the cleanness of the action: I'm 100% sure my GET request will result in single object, but still have to perform actions to extract it from the list. These steps should've been unnecessary. Aside of that, In my case I don't know the unique identifier, so cars/123 for retrieving a specific car isn't an option. I know, however, filters that will result in one object and one specific object altogether. The additional steps simply feel redundant.
1: https://learn.microsoft.com/en-us/azure/architecture/best-practices/api-design
2: https://blog.mwaysolutions.com/2014/06/05/10-best-practices-for-better-restful-api/
3: https://medium.com/hashmapinc/rest-good-practices-for-api-design-881439796dc9
As you've specifically asked for best practices in regards to REST:
REST doesn't care how you specify your URIs or that semantically meaningful tokens are used inside the URI at all. Further, a client should never expect a certain URI to return a certain type but instead rely on content-type negotiation to tell the server all of the capabilities the client supports.
You should furthermore not think of REST in terms of object orientation but more in terms of affordance and statemachines where a client get served every information needed in order to make an educated decision on what to do next.
The best sample to give here is probably to take a close look at the Web and how it's done for HTML pages. How can you filter for a specific car and how it will be presented to you? The same concepts that are used in the Web also apply to REST as both use the same interaction model. In regards to your car sample, the API should initially return some control-structures that teach a client how a request needs to be formed and what options could be filtered for. In HTML this is done via forms. For non-HTML based REST APIs dedicated media-types should be defined that translate the same approach to non-HTML structures. On sending the request to the server, your client would include all of the supported media-types it supports in an Accept HTTP header, which informs the server about the capabilities of the client. Media-types are just human-readable specification on how to process payloads of such types. Such specifications may include hints on type information a link relation might return. In order to gain wide-usage of media-types they should be defined as generic as possible. Instead of defining a media-type specific for a car, which is possible, it probably would be more convenient to use an existing or define a new general data-container format (similar to HTML).
All of the steps mentioned here should help you to design and implement an API that is free to evolve without having to risk to break clients, that furthermore is also scalable and minimizes interoperability concerns.
Unfortunately your question targets something totally different IMO, something more related to RPC. You basically invoke a generic method via HTTP on an endpoint, similar like SOAP, RMI or CORBA work. Whether you respect the semantics of HTTP operations or not is only of sub-interest here. Even if you'd reached level 3 of the Richardson Maturity Model (RMM) it does not mean that you are compliant to REST. Your client might still break if the server changes anything within the response. The RMM further doesn't even consider media-types at all, hence I consider it as rather useless.
However, regardless if you use a (true) REST or RPC/CRUD client, if retrieving single items is your preference instead of feeding them into a collection you should consider to include the URI of the items of interest instead of its data directly into the collection, as Evert also has suggested. While most people seem to be concerned on server performance and round-trip-times, it actually is very elegant in terms of caching. Further certain link-relation names such as prefetch may inform the client that it may fetch the targets payload early as it is highly possible that it's content will be requested next. Through caching a request might not even have to be triggered or sent to the server for processing, which is probably the best performance gain you can achieve.
1) If you use query like cars/where... - use CARS
2) If you whant CAR - make method GetCarById
You might not get a perfect answer to this, because all are going to be a bit subjective and often in a different way.
My general thought about this is that every item in my system will have its own unique url, for example /cars/1234. That case is always singular.
But this specific item might appear as a member in collections and search results. When /cars/1234 apears in these, they will always appear as a list with 1 item (or 0 or more depending on the query).
I feel that this is ultimately the most predictable.
In my case though, if a car appears as a member of a search or colletion, it's 'true url' will still be displayed.

Proper route pattern for RESTful collections with additional resources

I have been doing RESTful APIs for quite a bit (exposing and consuming 3rd parties) and I see two following patterns popping up here and there. Each has pros and cons and neither is "clean" in my opinion.
So the situation is: you have a collection resource (e.g. "assets") and you want to expose some additional resources within a collection (e.g. subresources of the collection itself, not the asset, like aggregated view endpoint or some commands).
Two patterns I see are:
People create a RESTful collection resource like /assets/${asset-id} and expose everything else they need like GET /assets/owned, GET /assets/summary, POST /assets/recheck-inventory. This looks neat and concise but introduces a clash between ${asset-id} and nouns of sub-resource URLs (e.g. asset12345 and summary are in the same place in the URL).
Others do /assets/items/${asset-id} and expose everything like GET /assets/owned, GET /assets/summary and so on. This is cleaner from routing perspective and a bit more future-proof, but adds an extra noun in the route, which leads to confusion when people are trying to do POST /assets for example.
The "best practice" guidelines I went through thus far avoid the question altogether. I also understand that REST is a convention and not the standard, and there is a universal "it depends" answer. Still, I feel like there got to be a generic recommendation here.
Hence the question is: which of two you would use?
UPDATE: to clarify, let us assume that:
/assets/owned contains entities of different types, not assets, so it is not a query and you can GET/POST/DELETE items in it.
/assets/summary is an aggregation document (e.g. report with quantities for example)
/assets/recheck-inventory is a command (i.e. POST only)
Also, we want to stick with REST principles:
route's path shall identify an entity and its state uniquely.
query parameters alter which elements are returned, but do not change the payload format.
headers are for protocol-level information and do not change service logic (i.e. presentation, security, caching, etc.)
I don't like these approaches either, but be aware, that REST does not put constraint on how to design URI structure, so you can do whatever you feel right. Apparently the developers of these webservices felt this approach right.
I would do something like the following with your URIs, since I like flat URIs much better.
/assets/items/${asset-id}
-> /assets/${asset-id}
/assets/owned
-> /assets/?owned
-> /assets/?owned=true
/assets/summary
-> /assets-summary
-> /assets/ + "Prefer: return=minimal"
You can find more about the prefer header here, but be aware, that you need to register it by the vary header if you want it to be a secondary cache key.

"Why" does Backbone NOT have a save (PUT/POST) method for its collections - is it unRESTful?

I asked a question a while back i.e. "How save an entire backbone collection?". However what intrigues me is that why is a save method not offered? Is it unRESTful to save (PUT/POST) entire collections or is it uncommon to do so in the REST-land?
GET: /MySite/Collections - allowed by collection.fetch()
POST: /MySite/Collections - for the model(s) in the collection to be Posted when calling model.save()
PUT: /MySite/Collections/{id} - for the model(s) to be updated individually
GET: /MySite/Collections/{id} - to fetch an individual model throuth model.fetch()
So why not allow for POST/PUT an entire collection of resources? It is convenient sometimes and although one can wrap/hack out some code using collection.toJSON why not include it? I'm just curious about its absence and the rationale for the same. Frameworks not having the capability of a few things usually implies bad programming/design and are thus left out. Is saving an entire collection 'bad practice'?
The wikipedia article about REST does mention CRUD verbs for collection.
But, in my opinion, a Collection is not a resource, it is not an entity, and it has not state. It is, instead, a bunch of resources. And if there would be an UPDATE command for a Collection it would be nothing else but a multiple UPDATE commands over multiple Models. Having the possibility of multiple UPDATE commands in only one request would be helpful but I think this is not a job for the REST implementation.
Also there will be problems of ambiguity, for example in a Collection that contains already saved Models with id and so on, and others that not, what will a POST command mean?... or an UPDATE command?...
No talking about the increase of the complexity in the server side where, if this Collection REST support should be taken like standard, we should to work the double to accomplish the casuistic.
Summarizing: I don't see any case where the need of a Collection REST command can't be solved with the actual, simpler, only-Model REST commands, so keeping the things as simple as possible I think is a good habit.