Dynamic form with REST API - forms

I want to create a REST API which will be used by multiple clients (for now a web page and an Android app). On client side, I need a form which contains (among other data) several comboboxes: Country, Region (these values should be dependent on selected country) and Currency.
In database I store only codes, as I want the values to be translatable on client side.
What is the preferable way to fill the combobox values? So far i considered these options:
Call API for each field separately ex. /countries, regions/{countryId}, /currencies.
This requires multiple calls and recall the regions endpoint every time user changes country.
Call API once and get all possible values ex. /formData. I think downside of this is that the response might be a bit large.
Maybe don't call the API at all, instead store possible values on client side.
I considered the 3rd option the most, because I need to store the translations anyway, but there is need to implement some kind of logic to restrict the regions to given country.
Is there any method that is considered as "the correct" or a good practice?
Or maybe should I consider doing the internationalization of values returned by API on server side?

When you want to follow the REST prenciples
Representational state transfer (REST) is a software architectural style that describes a uniform interface between physically separate components, often across the Internet in a client-server architecture. REST defines four interface constraints:
Identification of resources
Manipulation of resources
Self-descriptive messages and
Hypermedia as the engine of application state
Source: https://en.wikipedia.org/wiki/Representational_state_transfer
The Option number 2 is a no go.
So Option 1 or 3 is the right way. You should consider what is more scalable for you.
How often will it be updated? How many languages u want to support?
For simple applications I would prefer option 1 + translations. So the API tells you exactly what it will be accepted.
UI will also not be invalid.
For complex applications I would go with option 3. You should already have some workflows for consistency with Backend and Frontend.
But dont forget to always valide the inputs on the backend side!
At the End you are the programmer. It depends and your use cases and what u already have. When your translations are frontend 100% only, why adding another translation service on the backend?

Related

REST API Design - adapter service - how to mark endpoints for different directions?

Let's imagine a web service X that has a single purpose - help to integrate two existing services (A and B) having different domain models. Some sort of adapter pattern.
There are cases when A wants to call B, and cases when B wants to call A.
How should endpoints of X be named to make clear for which direction each endpoint is meant?
For example, let's assume that the service A manages "apples". And the service B wants to get updates on "apples".
The adapter service X would have two endpoints:
PUT /apples - when A wants to push updated "apples" to B
GET /apples - when B wants read "apples" from A
(without awaiting a push from A)
Such endpoint structure as above is quite misleading. The endpoints are quite different and use different domain models: PUT-endpoint awaits model of A, and GET-endpoint return model of B.
I would appreciate any advice on designing the API in such a case.
I don't like my own variant:
PUT /gateway-for-A/apples
GET /gateway-for-B/apples
In my view, it is fine, but can be improved:
PUT /gateway-for-A/apples
GET /gateway-for-B/apples
Because
forward slashes are conventionally used to show the hierarchy between individual resources and collections: /gateway-for-A/apples
What can be improved:
it is better to use lowercase
remove unnecessary words
So I would stick with the foloowing URI:
PUT /a/apples
GET /b/apples
Read more here about Restful API naming conventions
First things first: REST has no endpoints, but resources
Next, in terms of HTTP you should use the same URI for updating the state of a resource and retrieving updates done to it as caching, which basically uses the effective URI of a resource, will automatically invalidate any stored responses for an URI if a non-safe operation is performed on it and forward the request to the actual server. If you split concerns onto different URIs you basically bypass that cache management performed for you under the hood completely.
Note further, HTTP/0.9, HTTP/1.0 and HTTP/1.1 itself don't have a "push" option. It is a request-response protocol and as such if a client is interested in getting updates done to a resource it should poll the respective resource whenever it needs updates. If you need above-mentioned push though you basically need to switch to Web Sockets or the like. While HTTP/2 introduced server push functionality, this effectively just populates your local 2nd level cache preventing the client from effectively requesting the resource and instead using the previously received and cached one.
Such endpoint structure as above is quite misleading. The endpoints are quite different and use different domain models: PUT-endpoint awaits model of A, and GET-endpoint return model of B.
A resource shouldn't map your domain model 1:1. Usually in a REST architecture there can be way more resources than there are entities in your domain model. Just think of form-like resources that explain a client on how to request the creation or update of a resource or the like.
On the Web and therefore also in REST architectures the representation format exchanged should be based on well-defined media-types. These media types should define the syntax and semantics of elements that can be found within an exchanged document of that kind. The elements in particular provide the affordance that tell a client in particular what certain elements can be used for. I.e. a button wants to be pressed while a slider can be dragged left or right to change some numeric values or the like. You never have to frequent any external documentation once support for that media type is added to your client and/or server. A rule of thumb in regards to REST is to design the system as if you'd interact with a traditional Web page and then apply the same concepts you used for interacting with that Web page and translate it onto the REST application domain.
Client and server should furthermore use content-type negotiation to negotiate which representation format the server should generate for responses so that clients can process them. REST is all about indirections that ultimately allow a server to change its internals without affecting clients that behave well negatively. Staying interoperable whilst changing is an inherent design decision of REST. If that is not important to you, REST is probably overkill for your needs and you probably should use something more (Web-) RPC based.
In regards to you actual question, IMO a messaging queue could be a better fit to your problem than trying to force your design onto a REST architecture.
I was hoping that there is a well-known pattern for adapter service (when two different services are being integrated without knowing each other formats)
I'd compare that case with communication attempts among humans stemming from different countries. I.e. imagine a Chines who speaks Mandarin trying to communicate with a Frech. Either the Chinese needs to be able to talk French, the French being able to talk in Mandarin, they both use an intermediary language such as English or they make use of a translator. In terms of trust and cost, the latter option might be the most expansive one of all of these. As learning laguages though is a time-consuming, ongoing process this usually won't happen quickly unless special support is added, by hiring people with that language skills or using external translators.
The beauty of REST is, servers and clients aren't limited to one particular representation format (a.k.a. language). In contrast to traditional RPC services, which limit themselves to one syntax, in REST servers and clients can support a multitude of media types. I.e. your browser knows how to process HTML pages, how to render JPG, PNG, GIF, ... images, how to embed Microsoft Word, Excel, ... documents and so forth. This support was added over the years and allows a browser to basically render a plethora of documents.
So, one option is to either create a translation service that is able to translate one representation to an other and then act as middleman in the process or you directly add support for the non yet understood media types to the service/client directly. The more media-types your client/servers are able to process, the more likely they will be to interoperate with other peers in the network.
The former approach clearly requires that the middleman service is able to at least support the two representation formats issued by A and B but on the other hand allows you to use services not directly under your control. If at least one of the services though is under your control, directly adding the not-yet-supported media type could be potentially less work in the end. Especially when certain library support for the media type is already available or can be obtained easily.
In a REST architecture clients and servers aren't build with the purpose of knowing the other one by heart. This is already a hint that there is a strong coupling between these two. They shouldn't be aware of the others "API" other than that they use HTTP as transport layer and URIs as their addressing scheme. All other stuff are negotiated and discovered on the fly. If they don't share the same language capabilities the server will responde with a 406 Not Accepttable response that informs a client that they don't speak the same languages and thus won't be able to communicate meaningfully.
As mentioned before, REST is all about introducing indirections to aid in the decoupling intent which allows servers to evolve freely in future without those changes breaking clients as these will just coop with the change. Therefore, eventual change in future is an inherent design concept. If at least one participant in a REST architecture doesn't respect these design concepts they are a potential candidate for introducing the problems traditional RPC services did in the past, like breaking clients on a required change, maintaining v2/3/4/.../n of various different APIs and scaling issues due to the direct coupling of client and servers.
Not sure why you need to distinguish it in the path and why the domain or subdomain is not enough for it:
A: PUT x.example.com/apples -> X: PUT b.example.com/apples
B: GET x.example.com/apples -> X: GET a.example.com/apples
As of the model, you want to do PUSH-PULL in a system which is designed for REQ-REP. Let's translate the upper: pushApples(apples) and pullApples() -> apples if this is all they do, then PUT and GET are just fine with the /apples URI if you ask me. Maybe /apples/new is somewhat more expressive if you need only the updates, but I would rather use if-modified-since header instead and maybe push with if-unmodified-since.
Though I think you should describe what the two service does, not what you do with the apples, which appear to be a collection of database entities instead of a web resource, which is several layers above the database. Currently your URIs describe the communication, not the services. For example why is X necessary, why don't they call each other directly? If you can answer that question, then you will understand what X does with the apples and how to name its operations and how to design the URIs and methods which describe them.

Rest API Localization - Headers vs Payload

We have one POST API live in production. Now we have a requirement to accept Localization information and proceed with execution accordingly.
e.g. if distanceUnit is "KM" then process all incoming data in Kilometers.
There are three options I could think of to accept localization information.
As a http header i.e. localization: {"distanceUnit": "km"}
As a part of payload itself.
Request parameter.
I like the 1st option as
it doesn't change api contract.
It's easier for other apis to send this info in case they need to be localized in future.
Localization is a part of content negotiation so I don't think it should be part of payload/query parameter.
Any opinions here would be helpful to zero in on 1st or second option.
Thanks.
While accept-language, as indicated by the proposed link Kit posted, may be attempting, this only supports registered languages, maintained by IANA, the standadization gremium of the Web, but not certain generic configuration options out of the box. It may be attempting to default to miles for i.e. Accept-Language: us and use km elsewhere, American scientists may have certain issues with your application then if they want to use km instead of miles. But if this might not be the case, this clearly could be an option you might consider. In regards to custom HTTP headers, I wouldn't recommend using those as the problem with custom HTTP headers in general is that arbitrary generic HTTP clients do not support these which somehow contradicts the idea why one should use a REST architecture.
Let us transfer your problem to the Web domain for a second and see how we usually solve that task there. As REST is basically just a generalized approach to the common way we humans interact with the Web, any concepts used on the Web also apply to a REST architecture. Thus, designing the whole interaction flow as if your application interacts on a typical Web page is just common practice (or at least should be).
On the Web a so called Web form is used to "teach" a Web client (a.k.a. Browser) what data the server expects as input. It not only teaches the client about the respective properties the server either expects or supports for a certain resource but also which HTTP method to use, about the target URI to send the request to and about the media-type to use, which implicitly is often just given as application/x-www-form-urlencoded but may also be multipart/form-data.
The usage of forms and links fall into the HATEOAS constraint where these concpets allow clients to progress through their task, i.e. of buying an item in a Web shop or administrating users in a system, without the need of ever having to consult an external documentation at all. Applications here basically just use the build-in hypermedia capabilities to progress through their tasks. Clients usually follow some kind of predefined processes where the server instructs clients on what they need to do in order to add an item to the shopping cart or on how to add or edit a user while still just operating on a generic HTML document that by itself isn't tailored to the respective task at hands. This approach allows Web clients to basically render all kinds of pages and users to interact with those generic pages. If something in that page representation changes your browser will automatically adept and render the new version on the next request. Hence, the system is able to evolve over time and adapt to changes easily. This is probably one of the core reasons why anyone wants to use a REST architecture basically.
So, back to the topic. On the Web a server would advertise to a client that it supports various localization information with above mentioned forms. A user might be presented a choice or dropdown option where s/he can select the appropriate option. The user usually does not care how this input is transferred to the server or about the internals of the server at all. All s/he cares for is that the data will be available after the request was submitted (in case of adding or updating a resource). This also holds true for application in a REST architecture.
You might see a pattern here. REST and the browsable Web are basically the same thing. The latter though focuses on human interaction while the primer one should allow applications to "surf the Web" and follow allong processes outlined by the server (semi-)automatically. As such it should be clear by now that the same concepts that apply to the browsable Web also apply to REST and applications in that REST architecture.
I like the 1st option as ... it doesn't change api contract
Clients shouldn't bind to a particular API as this creates coupling, which REST tries to avoid at all costs. Instead of directly binding to an API, the Web and as such also REST should use contracts build on hyper media types that define the admissible syntax and semantics of messages exchanged. By abstracting the contract away from the API itself to the media-type a client can support various contracts simultaneously. The generalization of the media-type furthermore allows to i.e. express various different things with the same media type and thus increase the likelihood for reusage and thus a better integration support into application layers.
Supporting various media-types is similar to speaking different languages. By being able to speak various languages you just increase the likelihood that you will be able to communicate with other people (services) out of the box without the need of learning those languages before. A client can tell a server via the Accept header which media-types it is able to "speak( (a.k.a. process) and the server will either respond with either of these or respond with a 406 Not Acceptable. That error response is, as Jim Webber put it, coordination data that at all times tells you whether everything went well or in case of failures gives you feedback on what went wrong.
In order to stay future-proof I therefore would suggest to design the configuration around hypertext enabled media types that support forms, i.e. HTML forms, applicaiton/hal-forms+json or application/ion+json. If in future you need to add further configuration options adding these is just a trivial task. Whether that configuration is exposed as own resource which you just link to, as embedded part within the resource or not return to the client at all is also a choice you have. If the same configuration may be used by multiple resources it would be benefitial to expose it as own resource and then just create a reference from the resource to that configuration but as mentioned these are design decisions you have to make.
If the POST request body is the only place where this is used, and you never have to do GET requests and automatically apply any conversion, my preference would probably go to adding it to the body.
It's nice to have a full document that contains all the information to describe itself, without requiring external out-of-band data to fully interpret its meaning.
You might like to define your schema to always include the unit in relevant parts of the document, for example:
distance: [5, 'km']
or, as you said, do it once at the top of the doc.

Single API, multple frontend clients

I'm currently redesigning an application where we have a single API (.NET Core 3.1) and two frontend (React) applications. In our current solution we share the same endpoints for both clients, meaning that there is an overhead of data sent from the API because both clients need different information.
I'm looking for a convenient way to split the API so we end up having two different responses, depending on which client is sending the request. I see a few options but I'm quite unfamiliar with pros and cons (besides the obvious ones) of these approaches since I never planned an application for multiple clients.
Single endpoint, different data returned depending on a header/query param
Split the API into two APIs (but where should common endpoints land? creating the third API is an overhead for us)
Split controllers into two when necessary (perhaps using partial classes?) and just implement GET api/resourceX/client1 separately from GET api/resourceX/client2
But maybe there already is a build-in solution for this in .NET Core that I'm not aware of? I tried looking for solutions but ended up getting nowhere near the answer - perhaps my keywords failed me.
This question is somewhat opinion based and you did not give us much details about how different the needs of the two clients are, but I try to answer it.
I have the assumption that you do a CRUD API and you just serve data from database without much transformation or processing in your code. This is ok, but keep in mind that REST should be built around operations and not around data types and CRUD if we use the WSDL terms. This is somewhat related to anemic domain model (defined by Martin Fowler).
If the users of the two clients are the same, then I would add more endpoints to cover the different types of queries. You can use URI templates for this e.g. /stuff?filter=xyz&view=verbose. If you want to support arbitrary queries, then it is better to use a standard solution for URI queries e.g. odata instead of building your own query language. You can use headers too, but as far as I know standard HTTP headers are a lot less flexible than URI queries.
If you have different user groups for different clients based on the privileges e.g. staff and customers, then you can serve different data for the same endpoint based on the privileges. Be aware that if you handle both regular users and admins with a single client, then the code of the client can contain hints about what is accessible for an admin. If this is an issue, then you need to split up the code of the client into multiple files and serve the admin files only for people with admin privileges. Setting the proper cache header is important in this case too. Another possible solution to have different clients for different user groups.
Be aware that in the case of real REST your server gives the URIs or URI templates to the clients just like a webserver gives the links and forms to the browser. This is because the URIs can change in time and it is a lot easier to keep backward compatibility this way. The clients know what a link does based on the metadata you send with the link e.g. IANA link relations, RDF vocabularies, etc. So the only URI you need to hardcode into your clients should be the root URI of the API. Most of the people don't try to meet with this REST constraint, because it requires somewhat different than the usual mindset to do it.

Rest api with generic User

I created a few Rest apis right now and I always preferred a solution, where I created an endpoint for each resource.
For example:
GET .../employees/{id}/account
GET .../supervisors/{id}/account
and the same with the other http methods like put, post and delete. This blows up my api pretty much. My rest apis in general preferred redundancy to reduce complexity but in this cases it always feels a bit cumbersome. So I create another approach where I work with inheritance to keep the "dry" principle.
In this case there is a base class User and via inheritance my employee and supervisor model extends from it. Now I only need one endpoint like
GET .../accounts/{id}
and the server decides which object is returned. Also while this thins out my api, it increases complexity and in my api documentation ( where I use spring rest docs ) I have to document two different Objects for the same endpoint.
Now I am not sure about what is the right way to do it ( or at least the better way ). When I think about Rest, I think in resources. So my employees are a seperate resource as well as my supervisors.
Because I always followed this approach, I tink I might be mentally run in it and maybe lost the objectivity.
It would be great if you can give my any objective advice on how this should be handled.
I built an online service that deals with this too. It's called Wirespec:
https://wirespec.dev
The backend automatically creates the url for users and their endpoints dynamically with very little code. The code for handling the frontend is written in Kotlin while the backend for generating APIs for users is written in Node.js. In both cases, the amount of code is very negligible and self-maintaining, meaning that if the user changes the name of their API, the endpoint automatically updates with the name. Here are some examples:
API: https://wirespec.dev/Wirespec/projects/apis/Stackoverflow/apis/getUserDetails
Endpoint: https://api.wirespec.dev/wirespec/stackoverflow/getuserdetails?id=100
So to answer your question, it really doesn't matter where you place the username in the url.
Try signing in to Wirespec with your Github account and you'll see where your Github username appears in the url.
There is, unfortunately, no wright or wrong answer to this one and it soley depends on how you want to design things.
With that being said, you need to distinguish between client and server. A client shouldn't know the nifty details of your API. It is just an arbitrary consumer of your API that is fed all the information it needs in order to make informed choices. I.e. if you want the client to send some data to the server that follows a certain structure, the best advice is to use from-like representations, such as HAL forms, Ion or even HTML. Forms not only teach a client about the respective properties a resource supports but also about the HTTP operation to use, the target URI to send the request to as well as the representation format to send the data in, which in case of HTML is application/x-www-form-urlencoded most of the time.
In regards to receiving data from the server, a client shouldn't attempt to extract knowledge from URIs directly, as they may change over time and thus break clients that rely on such a methodology, but rely on link relation names. Per URI there might be multiple link relation names attached to that URI. A client not knowing the meaning of one should simply ignore it. Here, either one of the standardized link relation names should be used or an extension mechanism as defined by Web linking. While an arbitrary client might not make sense from this "arbitrary string" out of the box, the link relation name may be considered the predicate in a tripple often used in ontologies where the link relation name "connects" the current resource with the one the link relation was annotated for. For a set of URIs and link relation names you might therefore "learn" a semantic graph over all the resources and how they are connected to each other. I.e. you might annotate an URI pointing to a form resource with prefetch to hint a client that it may load the content of the referenced URI if it is IDLE as the likelihood is high that the client will be interested to load that resource next anyway. The same URI might also be annotated with edit-form to hint a client that the resource will provide an edit form to send some data to the server. It might also contain a Web linking extension such as https://acme.org/ref/orderForm that allows clients, that support such a custom extension, to react to such a resource accordingly.
In your accounts example, it is totally fine to return different data for different resources of the same URI-path. I.e. resource A pointing to an employee account might only contain properties name, age, position, salery while resource B pointing to a supervisor could also contain a list of subordinates or the like. To a generic HTTP client these are two totally different resources even though they used a URI structure like /accounts/{id}. Resources in a REST architecture are untyped, meaning they don't have a type ouf of the box per se. Think of some arbitrary Web page you access through your browser. Your browser is not aware of whether the Web page it renders contains details about a specific car or about the most recent local news. HTML is designed to express a multitude of different data in the same way. Different media types though may provide more concrete hints about the data exchanged. I.e. text/vcard, applciation/vcard+xml or application/vcard+json all may respresent data describing an entity (i.e. human person, jusistic entity, animal, ...) while application/mathml+xml might be used to express certain mathematical formulas and so on. The more general a media type is, the more wiedspread usage it may find. With more narrow media types however you can provide more specific support. With content type negotiation you also have a tool at your hand where a client can express its capabilities to servers and if the server/API is smart enough it can respond with a representation the client is able to handle.
This in essence is all what REST is and if followed correctly allow the decoupling of clients from specific servers. While this might sound confusing and burdensome to implement at first, these techniques are intended if you strive for a long-lasting environment that still is able to operate in decateds to come. Evolution is inherently integrated into this phiolosophy and supported by the decoupled design. If you don't need all of that, REST might not be the thing you want to do actually. Buf if you still want something like REST, you for sure should design the interactions between client and server as if you'd intereact with a typical Web server. After all, REST is just a generalization of the concepts used on the Web quite successfully for the past two decades.

REST API Concepts

I'm trying to grasp the essence of REST API and i have some questions that i'd be happy if someone could clarify:
First
From Wikipedia:
it is a network of Web resources (a virtual state-machine) where the user progresses through the application by selecting resource identifiers such as http://www.example.com/articles/21 and resource operations such as GET or POST (application state transitions), resulting in the next resource's representation (the next application state) being transferred to the end user for their use.
What is the meaning of "application state"? As far as i understand, an application that exposes a REST API is stateless, so it doesn't have a "state" by definition? It just replies to client requests, which contain all the information needed by the server to respond to those requests. In other words, it doesn't hold any context. Am i correct?
Second
One of the 6 constraints is client-server architecture. Why is that a constraint? isn't it correct that every API is in a client-server architecture? eventually, API is Application Programming Interface. ??
Third
from here:
Using generic media types such as JSON is fundamentally not RESTful because REST requires the messages to be self-descriptive. Self-descriptiveness just means that the semantics of the data should travel with the data itself.
What is the original meaning behind the self-descriptiveness constraint, and does using a generic media-type violate this constraint?
Fourth
I've seen in many places that REST is not HTTP, and doesn't have to use HTTP as it's undelying protocol, it's just natural to use HTTP because the set of methods it has (GET, POST, PUT, DELETE). Can someone explain why is it natural for REST and give an example for another way to use REST other then HTTP?
As far as i understand, an application that exposes a REST API is stateless, so it doesn't have a "state" by definition?
No, the communication itself should be stateless. REST is an abbreviation for REpresentational State Transfer, so the term state is even included in the name itself.
It is probably easier to think here in terms of traditional Web pages. If you have a server that keeps client state in it, i.e. manages multiple clients sessions, what you end up is having a scaling issue sooner or later. You can't add a further server the client can connect to to retrieve the same information as the session is tide to the server it was communicating before. One might try to share the server state through a remote bus (i.e. Redis queues or the like) but this leads to plenty other challenges that are not easily solvable.
In the words of Fielding:
REST is software design on the scale of decades: every detail is intended to promote software longevity and independent evolution. Many of the constraints are directly opposed to short-term efficiency. Unfortunately, people are fairly good at short-term design, and usually awful at long-term design. Most don’t think they need to design past the current release. (Source)
In my sense statelessness is less a constraint on independent evolution than it is on system scalability though. If you just take client-server decoupling into account, based on content type negotiation, usage of HATEOAS and so on, statelessness is not really a blocker here, though it takes a way a lot of background complexities if you avoid sharing client state, i.e. its current session data, across your server landscape.
One of the 6 constraints is client-server architecture. Why is that a constraint? isn't it correct that every API is in a client-server architecture? eventually, API is Application Programming Interface. ??
What are the counterparts to client-server architectures? Applications that don't have to deal with other applications. If an application does not have to communicate with other applications you don't need to be that careful in your design for it having to adapt to changes or avoid any coupling between its components as it is always treated as one thing. As quoted above, REST is software design on the scale of decades. As such, the same services you put online should still work in years to come and in essence should have the freedom to evolve in future.
Interoperability is one of the core issues in client-server architectures. If two participants do not talk the same language or do have a different understanding of the domain, they will have a hard time communicating with each other. Just put a Chinese and a Frenchmen in the same room and watch them try to solve a particular issue. Unless they do understand a minimal language set, i.e. English, communication will be the main problem to solve that issue.
What is the original meaning behind the self-descriptiveness constraint, and does using a generic media-type violate this constraint?
I start by quoting this statement from an actually good blog post:
A self-descriptive message is one that contains all the information that the recipient needs to understand it. There should not be additional information in a separate documentation or in another message. (Source)
If you now take a closer look at the JSON spec It just defines the basic syntax but does not define any semantics. So, in essence you know that objects start and end with curly braces ({, }), that an object consists of a set of key and values where the key is a string value and the value may either be a string, a number, a boolean, a further object or an array and so on. But it doesn't tell you anything about the actual structure, which elements are shipped within a document and so on. XML i.e. has document type definitions (DTDs) and XML schemas that define which elements and attributes are in which order and what their admissible values are and the like. While JSON (Hyper-)Schema attempts to fill this gap, it still doesn't define the semantics of the fields fully, i.e. in which context which elements may appear and what not. JSON itself also lacks support for URLs/URIs and JSON hyper-schema now tries to add support for it at least.
If you take a look at HTML i.e., the spec has already gone through different versions now but it was designed with backward compatibility in mind and even in version 5 you can use the tags defined in the original version and browser will be able to handle your Web page more or less correctly. A further part of self-descriptiveness comes through HTML's form support. A server can thereby teach a client not only on the data elements of a resource, i.e. about field name expecting a text input whereas a time field presents you a calendar widget to select a specific date and time entry and so on, but it will also tell a client the URI where to send the request to, which HTTP operation to use and which media-type to use to send the request in. While this already tackles HATEOAS as well, a client understanding HTML will know what the server wants it to do and therefore does not need to consult any external documentation that describes how a request should look like.
HTML is in essence a generic media type. You can use it to depict details of a specific car model but also to show news and other data. A media type in the end is nothing more than a human-readable definition how an application (client or server) should process data that is said to be of that format. As such, a generic media type is preferable to specific ones as it allows and promotes the reusage of that media type for many other domains and those increase the likelihood of its support across different vendors.
I've seen in many places that REST is not HTTP, and doesn't have to use HTTP as it's undelying protocol, it's just natural to use HTTP because the set of methods it has (GET, POST, PUT, DELETE). Can someone explain why is it natural for REST and give an example for another way to use REST other then HTTP?
As "Uncle Bob" Martin stated architecture is about intent. As already quoted above, REST is all about decoupling clients from servers to allow servers to evolve freely in future and clients to adopt to changes easily. This is, what basically allowed the Web to grow to its todays size. Fielding just took the concepts used successfully on the Web, mostly by us humans, and started questioning why applications do not use our style of interacting with the Web also. Therefore, loosely speaking, REST is just Web surfing for applications.
REST itself is just an architectural style. Like some churches use a gothic style, others a modern one and yet other a baroque one, each style has its unique properties that differentiate it from the others. In software engineering you have also a couple of different styles you can follow, such as monolithic or n-tier architectures, MVC architecture, domain specific languages (DSLs), SOA, peer-to-peer architectures, cloud computing (serverless, ...) and so on. Each of these have their own characteristics and unique proposition features, benefits and drawbacks. As in traditional architecture you can mix and match different styles into one approach, though the final result may not be what you were initially aiming for and remember, each style attempts to tackle at least one major concern.
Fielding was working on the HTTP 1.0 and 1.1 specification (among others) and analyzed the architecture of the Web in this doctoral thesis. Therefore it is no miracle in my sense that REST does work well on top of HTTP, but as already mentioned, he might have taken a to-close look at HTTP and the Web as statelessness is, at least in my understanding, less a concern for future evolution than for scalability. While scalability might be a future concern as well, I wouldn't call it a high-priority constraint in that regard, even though Fielding claims that all of the constraints are mandatory to deserve the REST tag.
As such, REST itself does not tie you to HTTP as it is just an architectural style. It does not forbid to deviate from its core ideas, but you might miss out on some of the properties it advocates (besides misusing the term REST eventually). But as REST goes almost hand in hand with HTTP, it is like the perfect match and why change it?! Sure, you could come up with a new transport protocol in future and apply the same concepts used to interact with Web pages to that protocol and you will more or less end with a REST architecture. Your protocol however should at least support URIs, media-types, link-relations and content-type negotiation. These are the foundation blocks IMO that every REST enabled application needs to support, as these guarantee the exchange of well-defined messages and the ability to act upon these.
As HTTP is just a transport protocol to transfer a document from a source machine to a target, one might question why SMTP, FTP or similar protocols are not used for REST architectures as well. While these protocols also transfer documents from one point to an other, they either lack support for media-types (S/FTP/S) or do not support the uniform interface constraint fully, i.e. by not supporting HATEOAS fully and the like. Besides that, both require a particular login to create a session which may or not be seen as violation of the statelessness constraint.