General thoughts about one Rest Endpoint and two Consumers - rest

Consider the following situation:
You have one Endpoint, for example ../api/Samples
All Samples have the Attributes: Name, App.
You have two Apps which will consume the Samples Endpoint
The First App (A1) wants all Samples.
The Second App (A2) wants only a Subset of the Samples. To be exact only the Samples which have 'A2' standing in the 'App' Attribute.
What is the most REST-conform and common sense way to realize this?
So far I thought of three ways:
Create two Endpoints: ../api/A1Samples and ../api/A2Samples
This seems like overhead. What if more Apps come later? The Controller must be duplicated even if most of the code is identical.
Send the App Type within the URL: ../api/Samples/A1 or A2
Would be easier to maintain if more Apps come later. But doesn't this reject the thought of REST?
Send the App Type within the Accept Header: ../api/Samples and in the Header: App-Type: A1 or A2
In my case it seems this isn't easy to implement in ASP.NET Core v1.1 but should be the most syntactically correct way.
Can someone approve or reject my thoughts? Maybe even extend the list or state the usually used solution for this case?

If one of the applications requires all samples, it could simply consume /api/Samples directly; for the other one, have an extensible way to specify filters (even if that is just a few GET parameters) - if this is really an "App" attribute that exists on the Sample object then ?App=A2 would make sense, if it is some other attribute then specify those attributes directly.
This is more REST-ful than your /Samples/A1 and /Samples/A2 idea because it directly specifies the attribute being queried for (A1 doesn't use ?App=A1 because as you said Application 1 consumes the entire list of sample objects) rather than knowledge of what application is querying it, any similarity is simply due to the (I suspect contrived) structure of the example.
REST isn't just about something as simple as "use path parameters in all cases" - filtering a result list is a clear case for using query parameters instead.

Related

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.

Complex requests with REST API

I am wondering if it is possible to adhere to REST principles when creating what will essentially amount to a BI tool.
In my scenario I have high data volume with 100,000's of IDs (frankly more than this but for the sake of this example let's go with that.). These are presented in a traditional table that allows for necessary features when accessing large data sets such as pagination. The user also has the ability to filter by one, or many of these ID's to drill down the data set as they see fit.
It is theoretically possible that the user would want to filter on 100 of the ID's, thus rendering a GET URI incredibly long. Which as I understand it would kind of break the resource identification principle of a REST API. Not to mention could potentially bump into the character limit in a GET request for certain browsers since the ID's may be quite long. Normally I would just use a POST since I can add all of the applied filters in the body and generate a where clause on the server.
Since a POST in a REST API is supposed to
Create a new entry in the collection.
By definition it would appear, at least to me that generating a complex query for something like this would mean that a REST API is not possible. Or does this perhaps mean that I am approaching the solution wrong (totally plausible).
It would seem that in my scenario using a GET simply isn't possible due to the potential length of the parameters. Thus I am forced to use a POST. Though using a POST as I am seems to violate REST style, which isn't the end of the world. I mostly just wanted to double check that I am not missing something and there is not a solution using a GET.
To follow the resources principle, make a search like resource. POST your ids in a body wto this endpoint and it will prepare a list of results for you and redirect you to searchresults/{id}.
See for example: https://gooroo.io/GoorooTHINK/Article/16583/HTTP-Patterns---Bouncer/25829#.W3aBsugzaUk

what's the real added value in REST routes?

AFAIU, RESTful API use http nomenclature to organize API.
From an exemple taken best practices you'll end up with:
http://api.college.com/students/3248234/courses/physics
What's the real advantage, from more naïve approach such as:
http://api.college.com/course_show?STUDENTID=3248234&COURSETYPE=physics
http://api.college.com/ratings_show?STUDENTID=3248234&COURSETYPE=physics
From my view point, first uri mixes stuffs: objects (students, courses) and their params (id for students, type for course). I fell it's a mess.
Moreover, we don't really know what's shown. It is the course taken by this student ? Or the rating our student achieved ? We can suspect that ratings would have been added at the end like .../courses/physics/ratings, but we can't be sure, since the last word is a parameters, not an object.
Second approach is more object oriented, like Course.show(**kwargs), and anyway has the advantage to separate function (or call it method) and parameters (or call it arguments).
Additional point, with this semantic, you can do CRUD but can be more detailed in your interface, like /course_delete or /course_suspend or /course_postpone
So two questions:
1- what's the real advantage of REST nomenclature on web API routing ? Isn't just hype ?
2- from security viewpoint, in my exemples, I suspect first url is less secure than second (flask had a problem with that if I remember well), is it correct ?
what's the real advantage of REST nomenclature on web API routing ? Isn't just hype ?
REST doesn't care what spelling you use for your identifiers.
URI Templates are a convenient way to generalize identifiers for different resources; this convenience is most frequently seen in mapping resource identifiers to implementations in the server, but are also sometimes seen as a means to describe a family of identifiers to a client that understands hypermedia representations.
Judicious use of path segments when describing a hierarchy of resources, allows you to take advantage of the client's ability to resolve relative references.
from security viewpoint, in my exemples, I suspect first url is less secure than second (flask had a problem with that if I remember well), is it correct ?
No? Neither of them offers any security at all; they are just identifiers.

REST: How best to handle large lists

It seems to me that REST has clean and clear semantics for basic CRUD and for listing resources, but I've seen no discussion of how to handle large lists of resources. It doesn't scale to dump an entire database table over the network in a resource-oriented architecture (imagine a customer table with a million customers!), especially if you only need a few items. So it seems that some semantics should exist to filter, map and reduce a list of resources on the server-side.
So, do you know any tried and true ways to do the following kinds of requests in REST:
1) Retrieve just the count of the resources?
I could imagine doing something like GET /api/customer?result=count
Is that how it's usually done?
I could also imagine modifying the URL (/api/count/customer or /api/customer/count, for example), but that seems to either break the continuity of the resource paths or inflict an ugly hack on the expected ID field.
2) Filter the results on the server-side?
I could imagine using query parameters for this, in a context-specific way (such as GET /api/customer?country=US&state=TX).
It seems tricky to do it in a flexible way, especially if you need to join other tables (for example, get customers who purchased in the last 6 months).
I could imagine using the HTTP OPTIONS method to return a JSON string specifying possible filters and their possible values.
Has anyone tried this sort of thing?
If so, how complex did you get (for example, retrieving the items purchased year-to-date by female customers between 18 and 45 years old in Massachussetts, etc.)?
3) Mapping to just get a limited set of fields or to add fields from joined tables?
4) More complicated reductions than count (such as average, sum, etc.)?
EDIT: To clarify, I'm interested in how the request is formulated rather than how to implement it on the server-side.
I think the answer to your question is OData! OData is a generic protocol for querying and interacting with information. OData is based on REST but extends the semantics to include programatic elemements similar to SQL.
OData is not always URL-based only as it use JSON payloads for some scenarios. But it is a standard (OASIS) so it well structured and supported by many APIs.
A few general links:
https://en.wikipedia.org/wiki/Open_Data_Protocol
http://www.odata.org/
The most common ways of handling large data sets in GET requests are (afaict) :
1) Pagination. The request would be something like GET /api/customer?country=US&state=TX&firstResult=0&maxResults=50. This way the client has the freedom to choose the size of the data chunk he needs (this is often useful for UI-based clients).
2) Exposing a size service, so that the client gets to know how large the data set is before actually requesting it. The service would be something like
GET /api/customer/size?country=US&state=TX
Obviously the two can (and imho should) be used together, so that when/if a client (be it mobile or web or whatever) waints to fill its UI with content, he can choose what's the best data chunk size based also on the size of whole data set (e.g. to avoid creating 100 pages for the user to navigate).

REST returning an object graph

I am new to the REST architecural design, however I think I have the basics of it covered.
I have a problem with returning objects from a RESTful call. If I make a request such as http://localhost/{type A}/{id} I will return an instance of A from the database with the specified id.
My question is what happens when A contains a collection of B objects? At the moment the XML I generate returns A with a collection of B objects inside of it. As you can imagine if the B type has a collection of C objects then the XML returned will end up being a quite complicated object graph.
I can't be 100% sure but this feels to be against the RESTful principles, the XML for A should return the fields etc. for A as well as a collection of URI's to the collection of B's that it owns.
Sorry if this is a bit confusing, I can try to elaborate more. This seems like a relatively basic question, however I can't decide which approach is "more" RESTful.
Cheers,
Aidos
One essential RESTful principle is that everything has a URI.
You have URI's like this.
/A/ and /A/id/ to get a list of A's and a specific A. The A response includes the ID's of B's.
/B/ and /B/id/ to get a list of B's and a specific B. The B response includes the ID's of C's.
/C/ and /C/id/ to get a list of C's and a specific C.
You can, through a series of queries, rebuild the A-B-C structure. You get the A, then get the relevant B's. When getting a B, you get the various C's that are referenced.
Edit
Nothing prevents you from returning more.
For example, you might have the following kinds of URI's.
/flat/A/id/, /flat/B/id/ and /flat/C/id/ to return "flat" (i.e., no depth) structures.
/deep/A/id/, /deep/B/id/ and /deep/C/id/ to return structures with complete depth.
The /deep/A/id/ would be the entire structure, in a big, nested XML document. Fine for clients that can handle it. /flat/A/id/ would be just the top level in a flat document. Best for clients that can't handle depth.
There's nothing saying your REST interface can't be relational.
/bookstore/{bookstoreID}
/bookstore/{bookstoreID}/books
/book/{bookID}
Basically, you have a 1:1 correspondence with your DB schema.
Except for Many-to-Many relations forming child lists. For example,
/bookstore/657/books should return a list of book IDs or URLs. Then if you want a specific book's data you can invoke the 3rd URL.
This is just off the top of my head, please debate the merits.
Make a flat Universe that you expose to the world.
Even when I use SOAP, which can easily handle hierarchical object graphs up to whatever depth, I flatten the graph and link everything with simple IDs (you could even use your database IDs, although the idea is that you want you don't want to expose your PKs to the world).
Your object universe inside your app is not necessarily the same one you expose to the world. Let A have children and let B have children, but there's no need to reflect that in the REST request URLs.
Why flatten? Because then you can do things like fetch the objects later by ID, or send them in bursts (both the same case, more or less)... And better than all that, the request URIs don't change when the object hierarchy changes (object 37252 is always the same, even when it's been reclassed).
Edit: Well, you asked for it... Here's the architecture I ended up using:
package: server - contains the superclasses that are shared between the front-end server and the back-end server
package: frontEndServer - contains a Server interface which the front-end server must adhere to. The interface is nice because if you decide to change from SOAP to a straight Web client (that uses JSON or whatever, as well), you've got the interface all laid out. It also contains all the implementations for the frontEnd classes that will be tossed to the client, and all the logic for the interaction between classes except how to talk to the client.
package: backEndServer - contains a Server interface which the back-end server will adhere to. An example of a Server implementation would be one that talks to a MySql DB or one that talks to an XML DB, but the Server interface is neutral. This package also contains all the classes that the implementations of the Server interface use to get work done, and all the logic for the backend except for persistence.
then you have implementation packages for each of these... which include stuff like how to persist for the backend and how to talk to the client for the front end. The front-end implementation package might know, for instance, that a user has logged in, whereas the frontEndServer just knows that it has to implement methods for creating users and logging in.
After beginning to write this up I realize that it would take a while more to describe everything, but here you have the gist of it.