RE: ISSUE-31: Are Operations violating REST's uniform interface constraint?

On Sunday, February 16, 2014 8:14 PM, Ryan J. McDonough wrote:
> On Feb 16, 2014, at 11:27 AM, Thomas Hoppe wrote:
> 
> >> The @type of "Search" offers less value than the resource defined in
> the "expects" property. It's here when're it's telling me how to format
> the message to the server. The operation subclass doesn't do much in
> helping me achieve that. The majority of request formatting is
> expressed in #SearchRequest and not the #Search @type.
> >
> > Hmm, for generic modelling of operations (or say forms because that
> would be the analogy in HTML)
> > I think you are right -- in that case I don't care about the @type.
> > But what If a client is specifically interested in a search operation
> of a Web resource.
> 
> I still believe that client doesn't gain much with the @type of the
> operation. What the client must care about is how to prepare the
> request and deliver it over the correct HTTP method. The operation is
> being carried out by the information in the search request message, not
> the annotations around it.

OK. Let's try to use a more interesting example than search. Let's talk
about ordering goods. So, you are arguing that the client would need to send
a do-order-this-stuff message, right? Likely, the server will transform that
to an Order. So, the question is, can I reuse a Order (let's say, e.g.,
http://schema.org/Order) to order some stuff or do I need to design a
separate do-order-this-stuff message type? This now goes back to something I
discussed with Mark a while ago, but if the server I'm talking to doesn't
deliver any goods but just stores files. Do I need another
store-this-order-representation message type?

I think I'd agree that it's purer to do so from a theoretical POV but I
doubt makes that much sense (or difference, for that matter) in practice.
More than likely, intermediaries will treat all of these message exactly the
same way but just looking at the used HTTP method. On the other hand, the
client needs to know whether it is going to be charged when it POSTs an
Order or whether that just results in a "file" to be created on some server.



> > In that case he might look for a well established operation like
> http://some.vocab.ns/Search
> > and inspect how to format a request message in the second place.
> 
> Sure, but I can guarantee you that if this service is running over
> HTTP, there'd be only two operations to perform: GET or POST. I'm
> leaving out PUT, PATCH, and DELETE as they're not applicable to a
> search use case. What the client needs to know now is:
> 
> * How do I send a "search" message to the service in order to get a
> response back?
> * Do I need to send the message via GET or POST?
> 
> It's not so much about describing the "operation" because we already
> know all of the HTTP operations that we can act on. At present, that's
> about 5 in total (i'm excluding the WebDAV methods) that would be
> applicable to most applications. For me, it now boils down to
> formatting and transmission; how does the client prepare the message
> and what HTTP method do they send it with. I know I keep harping on
> HTML forms, XForms, and OpenSearch, but it's because all of these
> formats operate on the same set of assumptions.

Right. But they have either been created for a very specific use case
(OpenSearch) or rely on the intelligence of the user to understand the
consequences of POSTing a set of key-value pairs (HTML forms). With Hydra I
would like to enable clients which can emulate at least parts of that
intelligence by understanding a subset of possible consequences. I did
choose a rather pragmatic approach by simply typing operations. Schema.org
independently (I think) came up with basically the same design.


> > Use-case: A generic client could use this information to present the
> > user a search input when
> > he browses a resource based on the existence of a search operation.
> 
> I still think this can be achieved. Checkout the JSONary project [1]
> and how they use JSON Hyper Schema [2] to dynamically generate HTML
> forms. If you take a gander at the Hyperschema docs, the link object
> for Hyperschema seems to follow the HTML approach and doesn't give have
> any additional semantics around the Link and all of the descriptive
> effort is put into the "schema" property:
> 
> {
>     "links": [
>         {
>             "rel": "search",

Well, I would argue the "rel": "search" provides the additional semantics
here. 


>             "href": "/search",
>             "method" : "POST",
>             "schema": {
>                 "type": "object",
>                 "properties": {
>                     "q": {
>                         "type": "string"
>                     },
>                     "count": {
>                         "type": "integer",
>                         "minimum": 10,
>                         "default": 20
>                     },
>                     "start": {
>                         "type": "integer",
>                         "default": 0
>                     }
>                 },

The tokens used in "schema" mean nothing at all without out of band
knowledge.


>                 "required": [ "q" ]
>             }
>         }
>     ]
> }
> 
> Sure, it doesn't look like much and JSON Schema itself still has a lot
> of holes. But it's still plenty functional enough to build a generic
> client. It's also simple and easy to work with and companies like
> Heroku [3] and GitHub are using this today. But if you squint a little,
> you can see that the "schema" is not very different than hydra:expects.

Agreed.. I would, however, go a step further and say that "rel": "search" in
the example above isn't very different from "@type": "Search" either..


> Arguably, the link should probably be the value the "rel" property such
> that you'd have:
> 
> {
>     "links": {
>         "rel": {

You probably wanted to use "search" instead of "rel" in this example, right?


>             "href": "/search",
>             "method": "POST",
>             "schema": {
>                 "type": "object",
>                 "properties": {
>                     "q": {
>                         "type": "string"
>                     },
>                     "count": {
>                         "type": "integer",
>                         "minimum": 10,
>                         "default": 20
>                     },
>                     "start": {
>                         "type": "integer",
>                         "default": 0
>                     }
>                 },
>                 "required": [  "q"  ]
>             }
>         }
>     }
> }
> 
> But that's likely for another forum.
> 
> Ryan-
> 
> [1] http://jsonary.com/
> [2] http://json-schema.org/latest/json-schema-hypermedia.html
> [3]
> https://blog.heroku.com/archives/2014/1/8/json_schema_for_heroku_platfo
> rm_api

If you look at [3], the only link I see in the example is a "create" link.
Now that looks *very* much like a hydra:Operation. I also often see the same
pattern used with HAL. It's certainly an option but I don't find that any
better. Actually, I find it worse than explicitly allowing to describe
operations on a resource. A link relation type should define the
relationship between two resources. A relation type of "create" thus doesn't
make much sense IMO.. and neither does the "edit" link relation in AtomPub
btw. What would make sense instead is a "create-form" or "source" relation
type. But that's really a different story :-)



--
Markus Lanthaler
@markuslanthaler

Received on Monday, 17 February 2014 20:04:05 UTC