mirror of
https://github.com/bigskysoftware/hypermedia-systems.git
synced 2025-10-25 00:03:44 -04:00
edits, standardize RESTful
This commit is contained in:
parent
914e6a5b64
commit
396e1c8ca8
@ -11,15 +11,15 @@ including:
|
||||
* A server that presents a hypermedia API, that is, that responds to network requests with hypermedia responses
|
||||
* A client that properly interprets those responses
|
||||
|
||||
In this chapter we will take a look at each of these components and their implementation in the context of The Web.
|
||||
In this chapter we will look at these components and their implementation in the context of the web.
|
||||
|
||||
Once we have reviewed the major components of The Web as a hypermedia system, we will take a look at Chapter 5 of Roy
|
||||
Fielding's dissertation, "`Architectural Styles and the Design of Network-based Software Architectures`". This is where the
|
||||
terms REpresenation State Transfer (REST), REST-ful and Hypermedia As The Engine Of Application State (HATEOAS) come from,
|
||||
Once we have reviewed the major components of the web as a hypermedia system, we will look at Chapter 5 of Roy
|
||||
Fielding's dissertation, "`Architectural Styles and the Design of Network-based Software Architectures.`" This is where the
|
||||
terms REpresenation State Transfer (REST), RESTful and Hypermedia As The Engine Of Application State (HATEOAS) come from,
|
||||
and we will analyze these terms in the context of The Web.
|
||||
|
||||
This should give you a stronger understanding of the theoretical basis of The Web as a a hypermedia system, how it is
|
||||
supposed to fit together, and why Hypermedia-Driven Applications are REST-ful, whereas JSON APIs, despite how the
|
||||
supposed to fit together, and why Hypermedia-Driven Applications are RESTful, whereas JSON APIs, despite how the
|
||||
term REST is currently used in the industry, are not.
|
||||
|
||||
== Components Of A Hypermedia System
|
||||
@ -425,14 +425,14 @@ He was describing the early web, with HTML being transferred over HTTP by early
|
||||
|
||||
Today, in a strange turn of events, the term "`REST`" is mainly associated with JSON Data APIs, rather than with HTML
|
||||
and hypermedia. This becomes extremely humorous once you realize that the vast majority of JSON Data APIs aren't
|
||||
REST-ful, and, in fact _can't_ be REST-ful, since they aren't using a natural hypermedia format.
|
||||
RESTful, and, in fact _can't_ be RESTful, since they aren't using a natural hypermedia format.
|
||||
|
||||
To re-emphasise: REST, as coined by Fielding, describes _the pre-JSON API web_, and letting go of the current, common
|
||||
usage of the term as "`JSON API`" is necessary to develop a proper understanding of it.
|
||||
|
||||
=== The "`Constraints`" of REST
|
||||
|
||||
In his dissertation, Fielding defines various "`constraints`" to describe how a REST-ful system must behave. This approach
|
||||
In his dissertation, Fielding defines various "`constraints`" to describe how a RESTful system must behave. This approach
|
||||
can feel a little round-about and difficult to follow for many people, but it is an appropriate approach for an academic
|
||||
dissertation. Given a bit of time thinking about the constraints he outlines, and some concrete examples, it will
|
||||
become easy to understand if a given system actually satisfies the architectural requirements of REST or not.
|
||||
@ -465,7 +465,7 @@ It should be obvious that any web application, regardless of how it is designed,
|
||||
|
||||
See https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm#sec_5_1_3[Section 5.1.3] for the Stateless constraint.
|
||||
|
||||
As described by Fielding, a REST-ful system is stateless: every request should encapsulate all information necessary to
|
||||
As described by Fielding, a RESTful system is stateless: every request should encapsulate all information necessary to
|
||||
respond to that request, with no side state or context stored on either the client or the server.
|
||||
|
||||
In practice, for many web applications today, we actually violate this constraint: it is common to establish a
|
||||
@ -483,7 +483,7 @@ tradeoffs.
|
||||
|
||||
It should be noted, however, that sessions do cause additional operational complexity headaches when deploying hypermedia
|
||||
servers, which now may need to have shared access to the session state information stored across an entire cluster. So
|
||||
Fielding was correct in pointing out that an ideal REST-ful system, one that did not violate this constraint, would,
|
||||
Fielding was correct in pointing out that an ideal RESTful system, one that did not violate this constraint, would,
|
||||
indeed, be simpler and therefore more robust.
|
||||
|
||||
=== The Caching Constraint
|
||||
@ -522,16 +522,16 @@ So we have four additional sub-constraints that, taken together, form the Unifor
|
||||
|
||||
==== Identification of Resources
|
||||
|
||||
In a REST-ful system, resources should have a unique identifier. Today the concept of Universal Resource Locators (URLs) is
|
||||
In a RESTful system, resources should have a unique identifier. Today the concept of Universal Resource Locators (URLs) is
|
||||
common, but at the time of Fielding's writing they were still relatively new and novel.
|
||||
|
||||
What might be more interesting today is the notion of a _resource_, thus being identified: in a REST-ful system, _any_ sort of
|
||||
What might be more interesting today is the notion of a _resource_, thus being identified: in a RESTful system, _any_ sort of
|
||||
data that can be referenced, that is, the target of a hypermedia reference, is considered a resource. URLs, though common
|
||||
enough today, end up solving the very complex problem of uniquely identifying any and every resource on the internet.
|
||||
|
||||
==== Manipulation of Resources Through Representations
|
||||
|
||||
In a REST-ful system, _representations_ of the resource are transferred between clients and servers. These
|
||||
In a RESTful system, _representations_ of the resource are transferred between clients and servers. These
|
||||
representations can contain both data and metadata about the request (such as "`control data`" like an HTTP
|
||||
method or response code). A particular data format or _media type_ may be used to present a given resource to a client,
|
||||
and that media type can be negotiated between the client and the server.
|
||||
@ -543,10 +543,10 @@ We saw this latter aspect of the uniform interface in the `Accept` header in the
|
||||
The Self-Descriptive Messages constraint, combined with the next one, HATEOAS, form what we consider to be the core of
|
||||
the Uniform Interface, of REST and why hypermedia provides such a powerful system architecture.
|
||||
|
||||
The Self-Descriptive Messages constraint requires that, in a REST-ful system, messages must be _self-describing_.
|
||||
The Self-Descriptive Messages constraint requires that, in a RESTful system, messages must be _self-describing_.
|
||||
|
||||
This means that _all information_ necessary to both display _and also operate_ on the data being represented must be
|
||||
present in the response. In a properly REST-ful system, there can be no additional "`side`" information necessary for
|
||||
present in the response. In a properly RESTful system, there can be no additional "`side`" information necessary for
|
||||
client to transform a response from a server into a useful user interface. Everything must "`be in`" the message itself,
|
||||
in the form of hypermedia controls.
|
||||
|
||||
@ -589,7 +589,7 @@ The second implementation returns a JSON representation:
|
||||
What can we say about the differences between these two responses?
|
||||
|
||||
One thing that may initially jump out at you is that the JSON representation is smaller than the HTML
|
||||
representation. Fielding notes exactly this tradeoff when using a REST-ful architecture in his dissertation:
|
||||
representation. Fielding notes exactly this tradeoff when using a RESTful architecture in his dissertation:
|
||||
|
||||
[quote, Roy Fielding, Architectural Styles and the Design of Network-based Software Architectures]
|
||||
____
|
||||
@ -629,7 +629,7 @@ to the system itself.
|
||||
|
||||
==== Hypermedia As The Engine of Application State (HATEOAS)
|
||||
|
||||
The final sub-constraint on the Uniform Interface is that, in a REST-ful system, hypermedia should be "`the engine of
|
||||
The final sub-constraint on the Uniform Interface is that, in a RESTful system, hypermedia should be "`the engine of
|
||||
application state`". This is sometimes abbreviated as "`HATEOAS`", although Fielding prefers to use the terminology
|
||||
"`the hypermedia constraint`" when discussing it.
|
||||
|
||||
@ -738,7 +738,7 @@ The JSON representation, on the other hand, might look like this:
|
||||
Note that, once again, the JSON representation is unchanged. There is no indication of this new functionality. Instead,
|
||||
a client must *know* about this change, presumably via some shared documentation between the client and the server.
|
||||
|
||||
Contrast this with the HTML response. Because of the uniform interface of the REST-ful model and, in particular,
|
||||
Contrast this with the HTML response. Because of the uniform interface of the RESTful model and, in particular,
|
||||
because we are using Hypermedia As The Engine of Application State, no such exchange of documentation is necessary! Instead,
|
||||
the client (a browser) simply renders the new HTML with this operation in it, making this operation available for the end user
|
||||
without any additional coding changes.
|
||||
@ -767,12 +767,12 @@ operations and resources in it, and display it to users to work with.
|
||||
|
||||
=== Layered System
|
||||
|
||||
The final "`required`" constraint on a REST-ful system that we will consider is The Layered System constraint. This constraint can be found in
|
||||
The final "`required`" constraint on a RESTful system that we will consider is The Layered System constraint. This constraint can be found in
|
||||
https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm#sec_5_1_6[Section 5.1.6] of Fielding's dissertation.
|
||||
|
||||
To be frank, after the excitement of the uniform interface constraint, the "`layered system`" constraint is a bit of a
|
||||
let down. But it is still worth understanding and it is actually utilized effectively by The web. The constraint
|
||||
requires that a REST-ful architecture be "`layered`", allowing for multiple servers to act as intermediaries between
|
||||
requires that a RESTful architecture be "`layered`", allowing for multiple servers to act as intermediaries between
|
||||
a client and the eventual "`source of truth`" server.
|
||||
|
||||
These intermediary servers can act as proxies, transform intermediate requests and responses and so forth.
|
||||
@ -788,7 +788,7 @@ nonetheless.
|
||||
|
||||
=== An Optional Constraint: Code-On-Demand
|
||||
|
||||
We called The Layered System constraint the final "`required`" constraint on a REST-ful system. We used this langauge because
|
||||
We called The Layered System constraint the final "`required`" constraint on a RESTful system. We used this langauge because
|
||||
there is one additional constraint mentioned in the dissertation. This constraint is called The Code On Demand constraint
|
||||
and is, somewhat awkwardly, described as an "`optional constraint`". The constraint can be found in
|
||||
https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm#sec_5_1_7[Section 5.1.7] of the dissertation.
|
||||
@ -803,7 +803,7 @@ after deployment improves system extensibility. However, it also reduces visibil
|
||||
within REST.
|
||||
____
|
||||
|
||||
So, scripting was and is a native aspect of the original REST-ful model of the web, and, thus something that
|
||||
So, scripting was and is a native aspect of the original RESTful model of the web, and, thus something that
|
||||
should of course be allowed in a Hypermedia-Driven Application.
|
||||
|
||||
However, in a Hypermedia-Driven Application the presence of scripting should _not_ change the fundamental networking
|
||||
|
||||
@ -392,7 +392,7 @@ work with them. Everything is encoded _in_ the hypermedia. A web browser acces
|
||||
issue HTTP requests and then render HTML, nothing more about the specifics of our applications end points or underlying
|
||||
domain model.
|
||||
|
||||
As simple as our application is at this point, it is thoroughly REST-ful.
|
||||
As simple as our application is at this point, it is thoroughly RESTful.
|
||||
|
||||
=== Adding A New Contact
|
||||
|
||||
@ -850,9 +850,9 @@ with domain logic in a controller, organizing our URLs in a coherent, resource-o
|
||||
|
||||
And, furthermore, this is a deeply _Hypermedia-Driven_ web application. Without thinking about it very much, we have
|
||||
been using REST, HATEOAS and all the other hypermedia concepts we discussed earlier. We would bet that this simple
|
||||
little contact app of ours is more REST-ful than 99% of all JSON APIs ever built!
|
||||
little contact app of ours is more RESTful than 99% of all JSON APIs ever built!
|
||||
|
||||
And it was all effortless:just by virtue of using a _hypermedia_, HTML, we naturally fall into the REST-ful network
|
||||
And it was all effortless:just by virtue of using a _hypermedia_, HTML, we naturally fall into the RESTful network
|
||||
architecture.
|
||||
|
||||
So that's great. But what's the matter with this little web app? Why not end here and go off to develop the old web 1.0 style
|
||||
|
||||
@ -285,7 +285,7 @@ transferring HTML.
|
||||
|
||||
Thankfully, now, with htmx, we have a chance to rectify this situation.
|
||||
|
||||
The "`right thing`", from a REST-ful, resource oriented perspective is, rather than issuing an HTTP `POST` to
|
||||
The "`right thing`", from a RESTful, resource oriented perspective is, rather than issuing an HTTP `POST` to
|
||||
`/contacts/42/delete`, to issue an HTTP `DELETE` to `/contacts/42`. We want to delete the contact. The contact is
|
||||
a resource. The URL for that resource is `/contacts/42`. So the ideal is a `DELETE` request to `/contacts/42/`.
|
||||
|
||||
@ -488,7 +488,7 @@ Now, when someone clicks on the "`Delete Contact`" button, they will be presente
|
||||
you want to delete this contact?`" and they will have an opportunity to cancel if they clicked the button in error. Very
|
||||
nice.
|
||||
|
||||
With this final change we now have a pretty solid "`delete contact`" mechanism: we are using the correct REST-ful routes
|
||||
With this final change we now have a pretty solid "`delete contact`" mechanism: we are using the correct RESTful routes
|
||||
and HTTP Methods, we are confirming the deletion, and we have removed a lot of the cruft that normal HTML imposes on us,
|
||||
all while using declarative attributes in our HTML and staying firmly within the normal hypermedia model of the web.
|
||||
|
||||
@ -1049,7 +1049,7 @@ a span and then add the `revealed` event trigger.
|
||||
The fact that switching to infinite scroll was so easy shows how well htmx generalizes HTML: just a few attributes allow
|
||||
us to dramatically expand what we can achieve in the hypermedia.
|
||||
|
||||
And, again, we note that we are doing all this within the original, REST-ful model of the web: despite all this new
|
||||
And, again, we note that we are doing all this within the original, RESTful model of the web: despite all this new
|
||||
behavior, we are still exchanging hypermedia with the server, no JSON API response to be seen.
|
||||
|
||||
As the web was designed.
|
||||
|
||||
@ -1170,5 +1170,5 @@ to redirect and have the URL update to something new. We can just re-render the
|
||||
contacts that were deleted) will be re-rendered.
|
||||
|
||||
And there we go, we now have a bulk delete feature for our application. Once again, not a huge amount of code, and we
|
||||
are implementing these features entirely by exchanging hypermedia with a server in the traditional, REST-ful manner of
|
||||
are implementing these features entirely by exchanging hypermedia with a server in the traditional, RESTful manner of
|
||||
the web.
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
== JSON Data APIs
|
||||
|
||||
So far we have been focusing on using hypermedia to build Hypermedia-Driven Applications. In doing so we are
|
||||
following the original networking architecture of the web, and building a REST-ful system, in the original sense
|
||||
following the original networking architecture of the web, and building a RESTful system, in the original sense
|
||||
of that term.
|
||||
|
||||
However, today, we should acknowledge that many web applications are often _not_ built using this approach. Instead, they use a
|
||||
@ -29,7 +29,7 @@ that is, a browser, understands. We are building an API for the browser to inte
|
||||
magic of HTML and hypermedia, the browser doesn't need to know anything about our hypermedia API beyond an entry point
|
||||
URL: all the actions and display information comes, self-contained, within the HTML responses.
|
||||
|
||||
Building REST-ful web applications like this is so natural and simple that you might not think of it as an API at all, but
|
||||
Building RESTful web applications like this is so natural and simple that you might not think of it as an API at all, but
|
||||
we assure you, it is.
|
||||
|
||||
== Hypermedia APIs & JSON Data APIs
|
||||
@ -141,7 +141,7 @@ This is the core strength of splitting your Data API from your Hypermedia API, i
|
||||
****
|
||||
Unfortunately, today, for historical reasons, what we are calling JSON Data APIs are often referred to
|
||||
"`REST APIs`" in the industry. This is ironic, because, by any reasonable reading of Roy Fielding's work defining what REST
|
||||
means, the vast majority of JSON APIs are _not_ REST-ful. Not even close.
|
||||
means, the vast majority of JSON APIs are _not_ RESTful. Not even close.
|
||||
|
||||
[quote, Roy Fielding, https://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven]
|
||||
____
|
||||
@ -437,7 +437,7 @@ the web application, allowing the application to know which user is making a giv
|
||||
.HTTP Cookies
|
||||
****
|
||||
HTTP Cookies are kind of a strange feature of HTTP. In some ways they violate the goal of remaining stateless, a
|
||||
major component of the REST-ful architecture: a server will often use a session cookie as an index into state kept
|
||||
major component of the RESTful architecture: a server will often use a session cookie as an index into state kept
|
||||
on the server "`on the side`", such as a cache of the last action performed by the user.
|
||||
|
||||
Nonetheless, cookies have proven extremely useful and so people tend not to complain about this aspect of them too much
|
||||
|
||||
@ -110,7 +110,7 @@ JavaScript. The APIs, over time, came to be known as "Web Services".
|
||||
The early Web Service development community quickly realized that many of these new XML APIs seemed different
|
||||
than "regular" HTML-based web requests: the XML APIs often did not use hypermedia concepts, but rather were plain data APIs,
|
||||
returning raw data without any additional context or information. This fact was viewed with ambivalence: the web
|
||||
had proven to be extremely flexible and vibrant, surely the core REST-ful concepts that it was built on should also be
|
||||
had proven to be extremely flexible and vibrant, surely the core RESTful concepts that it was built on should also be
|
||||
part of this new approach as well!
|
||||
|
||||
==== The Richarson Maturity Model
|
||||
@ -257,7 +257,7 @@ both of which seem reasonably true.
|
||||
|
||||
Despite these benefits, and even during the XML API era, when REST was a well known and hypermedia oriented concept
|
||||
,it was rare for web services to reach the third level of Richardson maturity. There were, at the time, heated arguments
|
||||
around whether or not a particular API is REST-ful. Over time, those arguments have, to a large extent, faded away.
|
||||
around whether or not a particular API is RESTful. Over time, those arguments have, to a large extent, faded away.
|
||||
|
||||
Most APIs stopped at level 2 of the Richarson Maturity Model and simply published API documentation rather than embedding
|
||||
hypermedia controls. There were scattered examples of successful hypermedia controls in APIs, around paging and things
|
||||
@ -304,10 +304,10 @@ JSON, on the other hand, is a plain data representation. It becomes harder to s
|
||||
this format. It's possible to do, and some JSON APIs do include them, but, in moving to JSON as a response format, the
|
||||
Web Service world, or, today, the JSON API world, took another step away from hypermedia.
|
||||
|
||||
.REST-ful JSON APIs?
|
||||
.RESTful JSON APIs?
|
||||
****
|
||||
A funny thing that happened along the way here was that the term REST, which was coined to described the HTML-based
|
||||
web: it increasingly became associated with JSON APIs which were _not_, for the most part, REST-ful, at least in the original
|
||||
web: it increasingly became associated with JSON APIs which were _not_, for the most part, RESTful, at least in the original
|
||||
sense of that term. Today it is mostly JSON API engineers and you are unlikely to see or hear the term being discussed
|
||||
among web developers.
|
||||
|
||||
@ -337,7 +337,7 @@ with the server.
|
||||
AngularJS was followed by React, from Facebook, in 2013. React introduced the notion of reactive programming, where
|
||||
a backing JavaScript model could be updated, and the DOM would automatically update to reflect the new state of the world.
|
||||
This made management of JavaScript-based web applications much easier in some ways, but also pushed React-based web
|
||||
applications further away from the original REST-ful model of the web in which *hypermedia* was intended to store (i.e. encode)
|
||||
applications further away from the original RESTful model of the web in which *hypermedia* was intended to store (i.e. encode)
|
||||
the state of the application.
|
||||
|
||||
As of this writing, React is king of the hill in Single Page Application frameworks, but there are many up and coming
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user