A few questions about RESTful APIs and why some of the best-practices are rarely implemented - api

In most tutorials, documentation, articles etc. about RESTful I come across a few of the same points, but yet I rarely ever see these 'What makes it RESTful' points implemented.
For example, I've read this many times:
Content type
Using HTTP headers
Accept: application/json, text/plain
Extension in the URL
Not RESTful, URLs are not the place for Content-Type
I have never come across an API where I have seen this implemented. Every API I have ever used has always required me to append XML or JSON to the end of the URL. Are they doing it wrong?
Versioning
Version media types
application/vnd.something.v1+json
Custom header
X-API-Version: 1
Version in URL
/v1/resouce
Not RESTful, by putting the version in the URL you create separate resources
If you need to introduce non-backwards-compatible functionality surely creating a seperate resource is the correct thing to do?
Once again, in all versions of APIs I've used, they use v1, v2 in the URL (such as google, imgur etc.)
By not implementing these points, would my API not be considered RESTful?
To clarify these points would be much appreciated.

1) Using accept header or using format specific URLs are both valid in a RESTful system. The article you are citing is wrong.
2) Saying v1/resource is not RESTful is also incorrect. You cannot look at a URI and make a conclusion about its RESTfulness. Adding a v1 at the root of your URL is probably not a great thing to do if you are trying to incremental evolve your system. In effect it declares a whole new URL space and obsoletes the old one. That's pretty drastic. RESTFul systems try and enable incremental and evolutionary change to a system. So doing /resource/v2 is actually much more compatible with that goal.
The unfortunate phenomena at work here is that many developers who are learning about REST discover that the vast majority of systems out there that claim to be doing REST are not actually conforming to the constraints of REST. So they quickly develop a zeal for telling everyone what is and is not RESTful. Many of these people have not yet fully understood the constraints and end up making up new ones that don't exist. The "RESTFul URL" fallacy is a classic. "POST must create a resource" is another common one.
My guidance to anyone learning REST is, if someone tells you that something is not RESTful, you ask them what constraint it is violating and what is the practical impact of ignoring that constraint. If they can't answer that, then politely ignore them.

The true definition of REST is obviously in the doctoral dissertation written by Roy Fielding in 2002. Do all of the API's out there that call themselves RESTful follow the guidelines specified by Fielding? The answer is no. The definition of REST has been watered down by some to just mean anything that does not use SOAP. I would worry less about what is RESTful and more about what is good practices. It is a good practice to specify the content type in the header of the request. It is also a good practice to version your API's. A good resource for information on API best practices is from the guys at Apigee as they have a lot of experience in this area. Check out their webinar on RESTful API Design where they ask if you are a pragmatist or a RESTafarian.

Related

Why does HATEOAS not specify a schema for the request body

A question for this already exists, but is more tech focused and doesnt have answers: Representing a request body on HATEOAS link
I like HATEOAS. I love using it in my frontend to check if I can perform some actions by checking if a link exists instead of having business logic.
But what I do not understand is how HATEOAS can truly be useful in other scenario's. What if you have an "AddItemToBasket" link which would need a request body with some properties in it. The frontend would still need to know what this request body looks like. But HATEOAS doesn't tell you this.
This means you still have a dependency on API knowledge. I think lots of applications solve this problem with generated API clients/graphql, but that makes HATEOAS a hard sell.
Why use HATEOAS if we can't use the URL and http method, because it doesn't offer the full picture.
REST builds on standards (uniform interface constraint) and currently there is no standard way to do this. There is a Hydra W3C WorkGroup writing a standard about how to describe Hypermedia APIs. They use RDF, standard vocabs like schema.org and you can write your API specific vocab they call documentation. As far as I understand their model you can give parameters in the documentation for operations represented by hyperlinks. You can use for example XSD to add constraints like numbers, etc. to the parameters. It takes a lot more effort than normally to write this kind of formal documentation and as far as I understand there are currently no general REST clients which could profit from these, so it does not make much sense currently to write such an API, but it is possible if you want to.
As of why to use HATEOAS, it makes your API flexible and backward compatible. For example if somebody does not have permission for an operation, you simply don't send a hyperlink for it in the response. You can always add new operations and the existing clients don't have to support them, they can just focus on what they already know and they won't break because something extra is added. They don't have to know about the URI structures and the methods, which can freely change if the only thing they depend on is the operation type and the parameters.

Pure HTML vs frameworks to define HATEOAS API?

When should one develop HATEOAS server RESTful API instead of using HTML (resource links, forms, etc.)?
Isn't HTML and a browser good enough as hypermedia engine?
Isn't HTML and a browser good enough as hypermedia engine?
HTML + HTTP + URI + Browser === The world wide web. So it's pretty good, no joke.
It's not without fault.
HTML's understanding of links is disappointingly limited. No support for idempotent writes. Uri Template support for GET only. I'm not super keen on how many different spellings there are for "link".
It's kind of verbose for a hypermedia format; don't get me wrong - built in text markup is brilliant when you are trying to document what is going on for a human being. But my impression thus far is that same structure starts to get in the way when as a human being you want to quickly review the semantic content that your automated agent is consuming.
I call your attention to this quote from RFC-4287
The primary use case that Atom addresses is the syndication of Web content such as weblogs and news headlines to Web sites as well as directly to user agents.
So a bunch of really smart guys, specifically trying to address use cases directly related to the web, decided to invest a bunch of effort into standardizing a new hypermedia format rather than using the one that was already ubiquitous in their problem domain.
And over the past 10+ years, that format has been widely adopted.
Without adoption, I'm not sure that HATEOAS has much benefit. You don't need a hypermedia api if you are controlling both sides of the conversation (example: javascript on the web -- hypermedia with code on demand capability downloading a client that has learned the protocol of a web api via some out of band channel).
Evidence would seem to suggest that HTML is not nearly as convenient a format as, for example, any of the JSON based hypermedia formats.
In conclusion: no, it's not good enough. It might be an acceptable place holder for the moment; but the JSON hypermedia tool sets are soon going to be sufficiently mature that HTML will be seen as a giant step in the wrong direction.

Does Swagger 2.0 enable impure REST API design?

The current Swagger spec claims that Swagger is used to describe and document RESTful APIs. I think this is not the case rather I think Swagger is useful for simply describing a HTTP API for a few reasons:
The Swagger spec has elements like Path and Definition but they don't clearly map to the REST data elements like resource, representation, and media types. My thought is that to effectively describe a REST API, you should be required to define the explicit REST data elements in the context of your API.
Hyperlinks are not first class objects in the Swagger spec and thus hyperlinks and their critical descriptive attribute, link relation, can easily be left out. In fact, hyperlinks are not mentioned at all.
HTTP paths are at the front-and-center which seems to be a clear violation of a point Fielding made in his famous blog post:
A REST API must not define fixed resource names or hierarchies (an obvious coupling of client and server)
Essentially, I think APIs defined using the Swagger 2.0 spec leads you to design an API that isn't constrained by HATEOAS which would violate REST.
Is this correct or am I missing something?
I absolutely agree. Swagger is not well suited for defining truly REST compliant APIs. The problem is that people define REST in a lot of different ways. The Richardson Maturity Model helps describe these different definitions.
Level 0 REST APIs pipe all requests through one URI and one HTTP method. This level includes any API that uses HTTP no matter how limited. In practice, people rarely call this REST anymore, but it does happen (probably for marketing reasons).
Level 1 REST APIs employ many URIs, but still only use one HTTP method (usually POST). Again, in practice, this rarely called REST anymore, but there was a time when it was common.
Level 2 REST APIs are where the concepts of resources and uniform interface are introduced. These APIs have URIs that represent resources and use the HTTP methods to perform CRUD operations on those resources. In practice, people started referring to this as RESTful to distinguish it from Level 1. I credit Ruby on Rails for popularizing this interpretation of REST, but I can't back that up. In any case, when Swagger claims to be for describing RESTful APIs, Level 2 is the definition they are referring to.
Level 3 REST APIs are fully compliant with the REST architectural style. In particular, they are characterized by using HATEOAS. All of the concerns you laid out in your question aren't taken into account until this level. In practice, some people have started calling these Hypermedia APIs to distinguish them from the now entrenched definition of RESTful as referring to the Level 2 definition.
I would say that your understanding of REST is more "mature" than that used by Swagger and therefore, you will only be frustrated trying to use it (I speak from experience). My personal choice for defining Hypermedia APIs is JSON Hyper-Schema. It can't match all the great tools Swagger has, but it allows me to write APIs at Level 3. That's more than I can say for any of the popular API definition languages out there.

REST API design for cloning a resource [duplicate]

This question already has answers here:
What is the restful way to represent a resource clone operation in the URL?
(5 answers)
Closed 7 years ago.
I am writing a YAML document using swagger to design a RESTful API method for cloning a resource. I have a few options and don't know which would be best. Please can someone advise?
Options:
Relinquishing the responsibility of cloning the resource object to the consumer (where the consumer assigns values to properties on a new object and then creates a new object), the process would need to consist of two requests to the API: a GET against a resource for the source object and then a POST to that resource for creating the new one. This feels like the consumer has too much responsibility.
Using the WebDAV HTTP extensions which provides a COPY method (see here). It would appear that this is exactly what I would like for cloning. However, I would like to stick to the standard methods as much as possible
POSTing to /{resource}?resourceIdToClone={id} where resourceIdToClone is an optional parameter. This would conflict with an API path that I already have for creating the resource, where I add a schema to the POST body. It would mean using a POST to /{resource}/ for creating and cloning, and that would violate SRP.
Adding a new resource called 'CloneableResource' and performing a POST to /CloneableResource/{resource_type}/{resource_source_id}. For the example of cloning a sheep, you'd make a POST to /CloneableResource/Sheep/10. This way, it would be possible to stick to using the standard HTTP methods, there'd be no conflict with any other resource paths (or SRP violation). However, I would be adding a new and potentially superfluous type to the domain. I also can't think of a scenario when a consumer would want to perform anything other than a POST to this resource, so it seems like a code smell to me.
A GET against /resource/{id}?method=clone. One of the advantages here is that no additional resource is required and it may be determined by a simple optional querystring parameter. I'm aware that one of the risks here is that it can be dangerous to provide post or delete capabilities using a GET method if the URL is in a web page as it may be crawled by a search engine.
Thanks for any help!
Most of these options are perfectly good choices. A lot of it just your style choice in the end. Here are my comments on each of your options.
Relinquishing the responsibility of cloning the resource object to the consumer
In general I don't really have a problem with this solution. This option is very straight forward for a user to understand and implement. It might be better than coming up with some proprietary cloning functionality that your users have to learn how to use.
Using the WebDAV HTTP extensions which provides a COPY method
I like to stick to the standard methods as well. I would not use COPY, but I wouldn't appalled if you did.
POSTing to /{resource}?resourceIdToClone={id}
This is a perfectly good solution. From a REST standpoint, you don't really have a conflict with the rest of your API. The URI with a query parameter identifies a different resource than the URI without the query parameter. Query parameters are a URI feature for identifying resources that you can not be referenced hierarchically. However, it might be difficult to separate these in your code because of the way most REST frameworks work. You could do something similar to this except with a hierarchical URI such as /{resource}/clone. You could POST to this URI and pass the resource_source_id in the body.
Adding a new resource called 'CloneableResource' and performing a POST to /CloneableResource/{resource_type}/{resource_source_id}
There is nothing wrong with this approach from a REST standpoint, but I think adding a new type is both unnecessary and clutters the API. However, I disagree with your intuition there could be problem with having a resource that has only a POST operation. It happens. In the real world, not everything fits nicely into GET, PUT, or DELETE.
A GET against /resource/{id}?method=clone
This is the only option of the 5 that I can not condone. It seems from your description that you already understand why this is a bad idea, so I'm not sure why you are considering it. However, all you have to do to make this a good solution is to change GET to POST. It then becomes very similar to the #3 solution. The URI could also be hierarchical instead of using a query parameter. POST /resource/{id}/clone would work just as well.
I hope this was helpful. Good luck with your decision.
If you want to COPY a resource, then, yes, COPY is an obvious choice.
(and yes, it would be good to pull the definitions of COPY and MOVE out of RFC 4918 to untangle them from WebDAV).
Influenced by project requirements and the range of preferences amongst members in my team, option 1 will serve us best at this stage.
Conforming to the standard HTTP methods will simplify and clarify my API
There will be a single, consistent approach to cloning a resource. This outweighs the issue I have with designating the cloning work to the consumer.

In what forms do APIs come in, and how to write them?

APIs are getting more and more popular and are used by developers to ease the process of developing applications to multiple platforms AND allow them to give other developers the ability to integrate their application's functionality into their own applications.
I've used APIs countless times before, but I'm now at the stage of developing my own applications. And as a developer who strives to create multi-platform applications - I need to use an API.
I'm going to use the RESTful approach as it's recommended the most.
After reading and looking for some background information, I came across: REST API Tutorial (which is really good site!), I learned that APIs basically receive HTTP requests, and return data in JSON/XML format.
However, there were 2 questions left unanswered to me:
In what form do APIs come in? Are APIs actually files? a set of commands......?
How do I actually write APIs? I'm talking about the server-side, data-handling code, and not the application/language-specific code (for sending out HTTP requests etc...)
It'd be great if someone could help me and answer the questions above as I have zero experience with APIs.
Any help is appreciated - much thanks!!
Just a quick from-the-gut answer: They are whatever you want them to be!
Off the top of my head, I would define an API as requiring two main elements:
Some documentation which makes it quite clear how to use the logic your systems prvides
Some way to call those systems. That may be as simple as a web-site that accepts POST-messages, and checks them for certain variables and values in order to perform specific tasks.
In short, it should be entirely up to you. Just make sure you provide simple, clear and acurate documentation.
UPDATE, as an asnwer to the comment below:
That is how I interpret it, and it would seem that Wikipedia is more or less in agreement with me. PHP would be a perfect example: You could for instance create a PHP-file which processes a POST, and instead of outputting html, outputs XML with the resulting data needed. Then a third party app could POST to your PHP application, and receive and process the resulting XML.
Apis come as a response to a http request. It is a plain text response that u can use encoded via json or xml as you described.
There are a plenty of frameworks to help you develop and API.
In Ruby u can use grape or rais-api or even rails itself.
There is a lot more available, but this are the ones im most used to use.