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.
Related
Lets assume we have some main-resource and a related sub-resource with 1-n relation;
User of the API can:
list main-resources so GET /main-resources endpoint.
list sub-resources so GET /sub-resources endpoint.
list sub-resources of a main-resource so one or both of;
GET /main-resources/{main-id}/sub-resources
GET /sub-resouces?main={main-id}
create a sub-resource under a main-resource
POST /main-resource/{main-id}/sub-resouces: Which has the benefit of hierarchy, but in order to support this one needs to provide another set of endpoints(list, create, update, delete).
POST /sub-resouces?main={main-id}: Which has the benefit of having embedded id inside URL. A middleware can handle and inject provided values into request itself.
create a sub-resource with all parameters in body POST /sub-resources
Is providing a URI with main={main-id} query parameter embedded a good way to solve this or should I go with the route of hierarchical URI?
In a true REST environment the spelling of URIs is not of importance as long as the characters used in the URI adhere to the URI specification. While RFC 3986 states that
The path component contains data, usually organized in hierarchical form, that, along with data in the non-hierarchical query component (Section 3.4), serves to identify a resource within the scope of the URI's scheme and naming authority (if any). The path is terminated by the first question mark ("?") and number sign ("#") character, or by the end of the URI. (Source)
it does not state that a URI has to have a hierarchical structure assigned to it. A URI as a whole is a pointer to a resource and as such a combination of various URIs may give the impression of some hierarchy involved. The actual information of whether URIs have some hierarchical structure to it should though stem from link relations that are attached to URIs. These can be registered names like up, fist, last, next, prev and the like or Web linking extensions such as https://acme.org/rel/parent which acts more like a predicate in a Semantic Web relation basically stating that the URI at hand is a parent to the current resource. Don't confuse rel-URIs for real URIs though. Such rel-URIs do not necessarily need to point to an actual resource or even to a documentation. Such link relation extensions though my be defined by media-types or certain profiles.
In a perfect world the URI though is only used to send the request to the actual server. A client won't parse or try to extract some knowledge off an URI as it will use accompanying link relation names to determine whether the URI is of relevance to the task at hand or not. REST is full of such "indirection" mechanism in order to help decoupling clients from servers.
I.e. what is the difference between a URI like https://acme.org/api/users/1 and https://acme.org/api/3f067d90-8b55-4b60-befc-1ce124b4e080? Developers in the first case might be tempted to create a user object representing the data returned by the URI invoked. Over time the response format might break as stuff is renamed, removed and replaced by other stuff. This is what Fielding called typed resources which REST shouldn't have.
The second URI doesn't give you a clue on what content it returns, and you might start questioning on what benefit it brings then. While you might not be aware of what actual content the service returns for such URIs, you know at least that your client is able to process the data somehow as otherwise the service would have responded with a 406 Not Acceptable response. So, content-type negotiation ensures that your client will with high certainty receive data it is able to process. Maintaining interoperability in a domain that is likely to change over time is one of RESTs strong benefits and selling points. Depending on the capabilities of your client and the service, you might receive a tailored response-format, which is only applicable to that particular service, or receive a more general-purpose one, like HTML i.e.. Your client basically needs a mapping to translate the received representation format into something your application then can use. As mentioned, REST is probably all about introducing indirections for the purpose of decoupling clients from servers. The benefit for going this indirection however is that once you have it working it will work with responses issued not only from that server but for any other service that also supports returning that media type format. And just think a minute what options your client has when it supports a couple of general-purpose formats. It then can basically communicate and interoperate with various other services in that ecosystem without a need for you touching it. This is how browsers operate on the Web for decades now.
This is exactly why I think that this phrase of Fielding is probably one of the most important ones but also the one that is ignored and or misinterpreted by most in the domain of REST:
A REST API should spend almost all of its descriptive effort in defining the media type(s) used for representing resources and driving application state, or in defining extended relation names and/or hypertext-enabled mark-up for existing standard media types. (Source)
So, in a true REST environment the form of the URI is unimportant as clients rely on other mechanisms to determine whether to use that URI or not. Even for so called "REST APIs" that do not really care about the true meaning of REST and treat it more like old-school RPC the question at hands is probably very opinionated and there probably isn't that one fits all solution. If your framework supports injecting stuff based on the presence of certain query parameters, use that. If you prefer the more hierarchical structure of URIs, go for those. There isn't a right or wrong in such cases.
According to the URI standard when you have a hierarchical relationship between resources, then better to add it to the path instead of the query. https://datatracker.ietf.org/doc/html/rfc3986#page-22 Sometimes it is better to describe the relation itself, not just the sub-resource, but that happens only if the sub-resource can belong to multiple main resources, which is n:m relationship.
I am modeling blogging REST API which has resources Blog, Post and Comment with following URLs:
/api/blogs
/api/blogs/{blogId}
/api/blogs/{blogId}/posts
and I create separate endpoint for all Posts in and their Comment`s:
/api/posts
/api/posts/{postId}
/api/posts/{postId}/comments
Given that I have postId, what is the RESTful way to get Blog for a specific Post? I have three ideas:
1. /api/posts/{postId}/blog
2. /api/blogs/parent-of-post/{postId}
3. /api/blogs?postId={postId}
To me the 1. URL looks more "prettier" but the 2. option looks more "logical" since that endpoint (eg. /api/blogs/*) is generally for blogs resources.
The third option uses query string as parameter but the issue I have with it is that this endpoint would return different type of body depending on the parameter. Eg. without parameter /api/blogs returns a collection of Blog resources, while with parameter postId it would return just single instance of Blog. I am not sure if this is good thing to do (especially because I am using ASP.NET Core and C# which has strongly typed return objects, so implementation might be awkward).
what is the RESTful way to get Blog for a specific Post?
Real answer: anything you want.
REST doesn't care what spelling conventions you use for your resource identifiers. As long as your identifiers conform to the production rules described by RFC 3986, you are good to go.
/api/blogs?postId={postId}
This is a perfectly normal choice, and turns out to be a really convenient one when you want to use general purpose web browsers, because HTML forms already have standards that make it easy to create URI with this shape.
Your other two choices are fine; they lose a point for not being HTML form friendly, but it's still easy enough to describe these identifiers using a URI template.
The third option uses query string as parameter but the issue I have with it is that this endpoint would return different type of body depending on the parameter
General purpose API consumers do NOT assume that two resources are alike just because the spellings of their identifiers overlap each other.
Which is to say, from the outside, there is no implied relationship between
/api/blogs
/api/blogs/1
/api/blogs?postId=2
so the fact that they return different bodies really isn't going to be a surprise to a general purpose consumer.
Now, your routing framework may not support returning different types from the handlers for these resources (or, more likely, may not have any "nice" way to do the routing automatically), but that's an implementation detail deliberately hidden behind the REST API facade.
Similarly, the human beings that read your access log might prefer one spelling to another, to reduce their own cognitive load.
I have been reading about the best practices for designing API's for REST services that will be exposed to customers. For example, we should use Nouns to name all the URI's exposed. Further the verbs should obey the semantics of the HTTP commands. For example, a GET request should never modify the resource, instead PUT request should be used here. I was asked this question during an interview and couldn't answer this satisfactorily-- I am designing a calculator that provides following functions, add, multiply, divide, subtract on two operands. How do I expose these methods to clients following REST principles. What URI to use for these operations? And I am not sure whether to map an add operation to GET,PUT or POST. Same for the other operations (divide, multiply etc). What are the guidelines here ?
What are the guidelines here ?
How would you do it with a web site?
That should be your first heuristic any time somebody asks you about REST. REST is an
architectural style, designed for "long-lived network-based applications that span multiple organizations". The reference application for this architectural style is the World Wide Web.
I am designing a calculator that provides following functions, add, multiply, divide, subtract on two operands. How do I expose these methods to clients following REST principles.
There are three pieces of information that the client has, which need to be communicated to the server - the operation and the two operands. One the web, the usual way to collect that sort of information is to provide a form. In this case, it might be a dropdown list of operations, and a couple of text controls to accept numbers. Because a pure function is a safe, we would probably use GET as the form method. So the HTML processing rules would take the values described by the form and transcribe them as key value pairs in the query part.
So the url would look something like
/22520c7f-6207-490e-99c9-bd1bb37f4056?op=add&firstArg=6&secondArg=9
The key generalization is to realize that the HTML form is playing the role of a URI Template - the server passes the template to the client, the client fills in the details and uses the result as the target of the request.
What this implies is that if you wanted to replace HTML with some other media type, you would need to specify a description for URI Templates, some mechanism for describing the acceptable ranges and what values might be reasonable defaults.
What URI to use for these operations?
With REST? absolutely does not matter. That's part of the point -- the client treats URI as opaque values.
URI are just identifiers; you can think of them like variable names in a program. The machines just don't care what the spellings are (so long as those spellings are consistent with RFC 3986).
Since the spelling doesn't matter, you can use whatever the local spelling conventions happen to be. A lot of people favor "hackable" URI -- the spelling of the identifier communicates useful information to the human reader.
URI are identifiers of resources; "any information that can be named can be a resource". This motivates some of the "nouns not verbs" noise -- the resources are web pages, or documents, or images, or scripts, or ... the "resource" concept is deliberately vague, so that it can be used flexibly.
I am not sure whether to map an add operation to GET,PUT or POST.
The key is to look at the semantics of the client's request. Anytime what you are doing is a query/lookup, something that is OK for the machine to do automatically for the user, then you are looking at safe semantics, and the method is likely to be GET or HEAD (special circumstances).
If we were asking the server to change the representations of its own resources, then PUT and POST come into play.
In this case, all of these operations are just doing lookups, so GET is appropriate.
(An interesting thing to note is that the none of these operations depend on server state; they are pure functions. So it might make sense to serve the client with code on demand -- javascript or some reasonable replacement -- and use the client's processor to perform the calculations rather than doing a bunch of round trips across the network).
I think one issue with the term REST is that it can have a different meaning to different people. It's possible that the interviewer has a different understanding of REST. When something like this comes up, my first inclination is to try to figure out what REST means to them. Do they mean hypermedia? Do they care about the verbs and nouns being used correctly as you mentioned? Or is in their mind REST just some HTTP endpoint that returns JSON. All of these are possible.
I would be inclined to answer the question as follows I think:
GET /add/1/2
GET /multiply/5/6
etc..
Others with much more experience than myself have answered with examples of good ways to do this.
I'd just like to point out what a really excellent question this is. I'm reading a paper by Richard Taylor and others from UC Irvine. Richard Taylor was Roy Fielding's advisor back when Fielding described REST in his PhD thesis. In a discussion comparing REST and SOAP, the paper includes this:
"...the closer the service semantics are to those of content, the more likely the service is to have a rich REST API.
...
the division between REST and SOAP may reflect a lack of design guidance; how can
services that are not content-centric, such as auction bidding
... be cleanly constructed in a REST-consistent manner?"
When they say "closer to content" they mean that the service looks more like some dynamic or static information to be retrieved by the end user, as opposed to a service looks like something that actively performs some function or calculation for the user.
They go on to provide additional guidance on this - but I haven't finished reading the paper yet, so I'll let you look that up for yourself. :-)
Search the web for: From Representations to Computations: The Evolution of
Web Architectures, Richard N. Taylor, UCI
Simple question I'm having trouble finding an answer to..
If I have a REST web service, and my design is not using url parameters, how can I specify two different keys to return the same resource by?
Example
I want (and have already implemented)
/Person/{ID}
which returns a person as expected.
Now I also want
/Person/{Name}
which returns a person by name.
Is this the correct RESTful format? Or is it something like:
/Person/Name/{Name}
You should only use one URI to refer to a single resource. Having multiple URIs will only cause confusion. In your example, confusion would arise due to two people having the same name. Which person resource are they referring to then?
That said, you can have multiple URIs refer to a single resource, but for anything other than the "true" URI you should simply redirect the client to the right place using a status code of 301 - Moved Permanently.
Personally, I would never implement a multi-ID scheme or redirection to support it. Pick a single identification scheme and stick with it. The users of your API will thank you.
What you really need to build is a query API, so focus on how you would implement something like a /personFinder resource which could take a name as a parameter and return potentially multiple matching /person/{ID} URIs in the response.
I guess technically you could have both URI's point to the same resource (perhaps with one of them as the canonical resource) but I think you wouldn't want to do this from an implementation perspective. What if there is an overlap between IDs and names?
It sure does seem like a good place to use query parameters, but if you insist on not doing so, perhaps you could do
person/{ID}
and
personByName/{Name}
I generally agree with this answer that for clarity and consistency it'd be best to avoid multiple ids pointing to the same entity.
Sometimes however, such a situation arises naturally. An example I work with is Polish companies, which can be identified by their tax id ('NIP' number) or by their national business registry id ('KRS' number).
In such case, I think one should first add the secondary id as a criterion to the search endpoint. Thus users will be able to "translate" between secondary id and primary id.
However, if users still keep insisting on being able to retrieve an entity directly by the secondary id (as we experienced), one other possibility is to provide a "secret" URL, not described in the documentation, performing such an operation. This can be given to users who made the effort to ask for it, and the potential ambiguity and confusion is then on them, if they decide to use it, not on everyone reading the documentation.
In terms of ambiguity and confusion for the API maintainer, I think this can be kept reasonably minimal with a helper function to immediately detect and translate the secondary id to primary id at the beginning of each relevant API endpoint.
It obviously matters much less than normal what scheme is chosen for the secret URL.
I'm doing some research to help me develop a REST API and this is one topic I haven't seen discussed in depth anywhere.
If I have a user in the system, is it better to identify the user using a numeric identifier
/users/1
Or using a string identifier?
/users/RSmith
I can see hypothetical potential pros and cons to each approach, string identifiers are more human readable, less discoverable (can't be incremented to find valid users), and don't require storing another numeric id in the database (I wouldn't want to expose database ids through the API). Numeric identifiers have no inherent meaning and due to that, can be guaranteed to be immutable, whereas with a string id the user might want to rename the resource, thus changing the resource URI.
Is there a REST best practice here or does the best approach vary to system to system? If the latter, are there any additional pros and cons associated with each method?
As you know, strictly speaking, there is no advantage between both approaches. Yes, string identifies may be easier for people to remember, but apart from that, REST does not enforce "pretty" URLs (or IDs), because most of the time URLs are accessed by programs following the hyperlinks.
Thus, human friendly URLs should only be used for bootstrapping resources that may be remembered by humans. Also, ID guessing should not be a problem because either:
You have to restrict access to URLs based on any authentication method, or:
You have to use randomized/unguessable URLs that are not "public".
So which one to use? Most of the time, it does not matter, as IDs are not accessed directly. If you have to ensure people remember their URLs for some reason, try to do them human-friendly, but try to avoid resource-name change and apply some other means of authentication so that even guessed URLs don't get access to unauthorized places.
Only advantage of this: /users/RSmith is that it's more human friendly. From RESTfull perspective it doesn't matter because both are valid resource identifiers. Everything else depends on your system requrements.