Skip to content

Commit

Permalink
a few nit-picky corrections
Browse files Browse the repository at this point in the history
  • Loading branch information
caboteria committed Sep 7, 2011
1 parent 4651b50 commit 8e219e4
Show file tree
Hide file tree
Showing 8 changed files with 69 additions and 70 deletions.
19 changes: 9 additions & 10 deletions forms.rst
Expand Up @@ -18,9 +18,9 @@ As far as I can see, this usability issue impacts two important use cases:
person can either be using a web browser, or a command-line tool like
"curl".
2. The development of a command-line or graphical interface to a RESTful API.
Without a proper description of required input types, knowledge around
Without a proper description of required input types, knowledge about
these has to be encoded explicitly in the client. This has the disadvantage
that new features are not automatically exposed, and that there's strict
that new features are not automatically exposed, and that there are strict
requirements around not making backwards incompatible changes.

When we look at the web, this issue doesn't exist. Millions of users interact
Expand All @@ -30,7 +30,7 @@ Interactions with IT systems on the web are all self-explanatory using
hypertext, and input is guided by forms.

In fact, forms are what I see as the solution here. But before I go into that,
let's see look into two classes of solutions that have been proposed to
let's look into two classes of solutions that have been proposed to
address this issue, and why I think they actually do not solve it. The first
is using a type definition language like XMLSchema to describe the input
types, the second is using some kind of service description language like
Expand All @@ -39,7 +39,7 @@ WADL.
Type Definition
===============

As eluded to in :doc:`resources`, some RESTful APIs use a type definition
As alluded to in :doc:`resources`, some RESTful APIs use a type definition
language to provide information about how to construct request entities. In my
view this is a bad approach, and has the following issues:

Expand Down Expand Up @@ -71,14 +71,14 @@ difference between a method on a WADL resource, and an RPC entry point.

It would be possible to construct a more RESTful service description language.
It would focus on mapping the RESTful concepts of resource, collection,
relationships, links. It would probably need a type definition language as
relationships, and links. It would probably need a type definition language as
well to define the constraints on types for each method (again, PUT may have
different constraints than POST). There have been discussions in the RHEV-M
project on this.

In the end though, this approach also feels wrong. What I think is needed is
something that works like the web, where everything is self descriptive, and
guide only by the actual URL flow the user is going through, not by reference
guided only by the actual URL flow the user is going through, not by reference
to some external description.

Using Forms to Guide Input
Expand Down Expand Up @@ -201,9 +201,9 @@ multiple Boolean that indicates if multiple values are accepted (array).
Constraints
-----------

First we need to answer the question what kind constraints do we want to
First we need to answer the question of what kind of constraints we want to
express in our form definition language. I will start by mentioning that in my
view, it is impossible to express each and every constraint client side. Some
view, it is impossible to express each and every constraint on the client side. Some
constraints for example require access to other data (e.g. when creating
relationships), are computationally intensive, or even unknown to the API
designer because they are undocumented for the application the API is written
Expand Down Expand Up @@ -288,8 +288,7 @@ server supports, using the rules described in :doc:`resources`.

If a client requested a "text/html" representation of the form, it is assumed
that the client is a web browser, and we assume the form will be processed as
a regular HTML form. In this case, the server should have generate an HTML
form with the following properties:
a regular HTML form. In this case:

* An HTML <form> should be generated, with an appropriate <input> element for
each field.
Expand Down
2 changes: 1 addition & 1 deletion intro.rst
Expand Up @@ -8,7 +8,7 @@ gained being involved in the design of the `RESTful API
<http://bitbucket.org/geertj/rhevm-api/wiki/Home>`_ for Red Hat's Enterprise
Virtualization product, `twice <http://fedorahosted.org/rhevm-api/>`_. During
the design phase of the API we had to solve many of the real-world problems
described above, but we weren't willing add non-RESTful or "RPC-like"
described above, but we weren't willing to add non-RESTful or "RPC-like"
interfaces to our API too easily.

In my definition, a real-world RESTful API is an API that provides answers to
Expand Down
22 changes: 11 additions & 11 deletions methods.rst
Expand Up @@ -9,15 +9,15 @@ We already discussed that resources are the fundamental concept in a RESTful
API, and that each resource has its own unique URL. Methods can be executed on
resources via their URL.

The table below lists the standard methods that have a well-defind meaning for
The table below lists the standard methods that have a well-defined meaning for
all resources and collections.

======= ========== ==================================================
Method Scope Semantics
======= ========== ==================================================
GET collection Retrieve all resources in a collection
GET resource Retrieve a single resource
HEAD collection Return all resources in a collection (header only)
HEAD collection Retrieve all resources in a collection (header only)
HEAD resource Retrieve a single resource (header only)
POST collection Create a new resource in a collection
PUT resource Update a resource
Expand Down Expand Up @@ -48,13 +48,13 @@ example of this is the difference between a "power off" and a "shutdown" of a
virtual machine. Both will lead to a vm resource in the "DOWN" state.
However, these operations are quite different.

As a solutions to such non-RESTful operations, an "actions" sub-collection can
As a solution to such non-RESTful operations, an "actions" sub-collection can
be used on a resource. Actions are basically RPC-like messages to a resource
to perform a certain operation. The "actions" sub-collection can be seen as a
command queue to which new action can be POSTed, that are then executed by the
API. Each action resource that is POSTed, should have a "type" attribute that
indicates the type of action to be performed, and can have arbitrary other
attributes that parametrize the operation.
attributes that parameterize the operation.

It should be noted that actions should only be used as an exception, when
there's a good reason that an operation cannot be mapped to one of the
Expand All @@ -74,11 +74,11 @@ An alternative method called PATCH `has been proposed recently
<http://tools.ietf.org/html/rfc5789>`_. The semantics of this call are that
like PUT it updates a resource, but unlike PUT, it applies a delta rather than
replacing the resource with the new representation. At the time of writing,
the PATCH was still a proposed standard waiting final approval.
PATCH was still a proposed standard waiting final approval.

Many current RESTful APIs use PUT but implement the PATCH semantics. Since
this behavior seems wide spread, and since requiring PUT to accept a full
representation is adds a high client overhead, my recommendation would be to
this behavior seems widespread, and since requiring PUT to accept a full
representation adds a high client overhead, my recommendation is to
implement PUT as PATCH for now, until PATCH becomes widespread, at which point
it can replace PUT and PUT can get its original meaning.

Expand All @@ -95,7 +95,7 @@ retrieving the response entity at all using the HEAD HTTP method.

In my view, the usefulness of this feature is dubious. First of all, it can
increase response sizes quite significantly. Second, it can only be used when
a resource is being returned, it does not make sense to be used with
a resource is being returned; it does not make sense to be used with
collections. Because I have not yet seen any good use of this header in the
context of a RESTful API, I recommend not to implement Link headers.

Expand Down Expand Up @@ -135,7 +135,7 @@ After the response has been retrieved once with a status that is not equal to
should not assume it will continue to be available.

A client may request the server to modify its asynchronous behavior with the
following "Except" headers:
following "Expect" headers:

* "Expect: 200-ok/201-created/204-no-content" disables all asynchronous
functionality. The server may return a "417 Expectation Failed"
Expand All @@ -150,7 +150,7 @@ Accepted status for any request other than GET.
Ranges / Pagination
===================

In case collections contain a lot of resource, it is quite a common
When collections contain many resources, it is quite a common
requirement for a client to retrieve only a subset of the available resources.
This can be implemented using the Range header with a "resource" range unit:

Expand Down Expand Up @@ -183,7 +183,7 @@ when some kind of event happens.

Ideally, such a notification would be implemented using a call-out from the
server to the client. However, there is no good portable standard to do this
over HTTP, and it also breaks with network address translation, and HTTP
over HTTP, and it also breaks with network address translation and HTTP
proxies. A second approach called busy-loop polling is horribly inefficient.

In my view, the best approach is what is is called "long polling". In long
Expand Down
12 changes: 6 additions & 6 deletions misc.rst
Expand Up @@ -12,32 +12,32 @@ is of course available because of the self-descriptive nature of a RESTful
API. But the request is to have that information offline as well, so that CLI
users can get help without have to connect first.

In my view this is a bad idea to offer this offline help. It introduces a
In my view it is a bad idea to offer this offline help. It introduces a
tight coupling between a client and a server, which will break the RESTful
model. A server cannot be independently upgraded anymore from a client, and
clients become tied to a specific server version. Also I doubt the usefulness
of this feature as having to connect first to get help does not seem like a
big issue to me.

That said, it is relatively straightforward to define a way in such an offline
That said, it is relatively straightforward to define a way that such an offline
description can be facilitated.

One change is required for this server-side. For each collection, the API
One server-side change is required for this. For each collection, the API
should implement a placeholder resource with a special ID (let's say "_", but
it doesn't matter as long as it cannot be a valid ID), and some fake data.
When a special HTTP Expect header is set, only this placeholder resource is
returned when querying a collection.

Having the placeholder resources in place for every collection, the following
procedure can be used client-side to retrieve all relevant metadata:
procedure can be used by the client to retrieve all relevant metadata:

1. Retrieve the entry point of the API and store it in memory as a resource.
2. For every hyperlink in the entry point, fetch the target, and store it
under the "target' property under the link object, recursively. When
under the "target" property under the link object, recursively. When
collections are retrieved, the special Expect header must be set.
3. For every hyperlink in the entry point, execute an OPTIONS call on the
target, and store the resulting headers under the "options" property of the
link object, recursively
link object, recursively.
4. Serialize the resulting object to a file.

The result of this is basically a recursive dump of the "GET"-able part of an
Expand Down
24 changes: 12 additions & 12 deletions relationships.rst
Expand Up @@ -3,19 +3,19 @@ Relationships
=============

As we have seen in :doc:`resources`, the resource is the fundamental unit in
RESTful API design. Resources model an object from the application data model.
RESTful API design. Resources model objects from the application data model.

Resources do not exist in isolation, but have relationships to other other
resources. Sometimes these relationships exist between the mapped objects in
the application data model as well, sometimes they are specific to the RESTful
resources.

One of the fundaments of the RESTful architecture style, is these
relationships are expressed by hyperlinks on the representation of a resource.
One of the principles of the RESTful architecture style is that these
relationships are expressed by hyperlinks to the representation of a resource.

In our resource model, we interpret any object with an "href" attribute as a
hyperlink. The value of the href attribute contains an absolute URL that can
be retrieved with GET. Using GET on a such a URL get is guaranteed to be
be retrieved with GET. Using GET on a such a URL is guaranteed to be
side-effect free.

Two types of hyperlinks are normally used:
Expand All @@ -28,7 +28,7 @@ Two types of hyperlinks are normally used:
semantics of the relationship. I'll call these "object links," not to be
confused with the "link objects" above.

Below is an example of a virtual machine representation in YAML, that
Below is an example of a virtual machine representation in YAML that
illustrates the two different ways in which a relationship can be expressed::

!vm
Expand Down Expand Up @@ -59,11 +59,11 @@ resource model (favoring link objects).
* Link objects are used to express structural relationships in the API. So for
example, the top-level collections, singleton resources and sub-collections
(including actions) are all referenced using link objects.
* Objects links are used to express semantical relationships from the
* Object links are used to express semantic relationships from the
application data model. In the example above, the vm to cluster link comes
directly from the application data model and is therefore modeled as a link.

Note however that sub-collections can express both a semantical relationship,
Note however that sub-collections can express both a semantic relationship,
as well as a structural relationship. See for example the "collection/nics"
sub-collection to a VM in the example above. In such a case, our convention
has been to use link objects.
Expand Down Expand Up @@ -93,20 +93,20 @@ point of a virtualization API using rel="collection/vms".
Modeling Semantic Relationships
-------------------------------

Semantical relationships can be modeled either by an object link, or by a
Semantic relationships can be modeled either by an object link, or by a
sub-collection. I believe that choosing the right way to represent a
sub-collection is important to get a consistent API experience for the user.
sub-collection is important to get a consistent API experience for the client.
I would advocate using the following rules:

1. In case of a 1:N relationship, where the target object is **existentially
dependent** on the source object, I'd recommend to use a sub-collection.
With existentially dependent I mean that a target object cannot exist
By "existentially dependent" I mean that a target object cannot exist
without its source. In database parlance, this would be a FOREIGN KEY
relationship with an ON DELETE CASCADE. An example of such a relationship
are the NICs that are associated with a VM
are the NICs that are associated with a VM.
2. In case of a 1:N relationship, where there is data that is associated with
the link, I'd recommend to use a sub-collection. Note that we are talking
about data here that is neither part of the source object, or the target
about data here that is neither part of the source object, nor the target
object. The resources in the sub-collection can hold the extra data. In
this case, the data in the sub-resource would therefore be a merge of the
data from the mapped object from the application data model, and link data.
Expand Down

0 comments on commit 8e219e4

Please sign in to comment.