Re: More Thoughts on Links and Operation Subclasses

On Mon, Jan 27, 2014 at 2:51 AM, Thomas Hoppe <thomas.hoppe@n-fuse.de> wrote:
> Hi,
>
> I wan to comment on some of your thoughts.
>
>
> On 01/25/2014 04:58 PM, Ryan McDonough wrote:
>>
>> I’ve been trying to really grok what value Operation subclasses really
>> have. Stock hydra has some base subclasses such as ReplaceResourceOpertion,
>> DeleteResourceOperation, and CreateResourceOperation. Take
>> DeleteResourceOpration for example; there’s really no difference between
>> this:
>>
>> {
>>   "@context": "http://www.w3.org/ns/hydra/context.jsonld",
>>   "@id": "/an-issue",
>>   "title": "An exemplary issue representation",
>>   "operations": [
>>     {
>>       "@type": "DeleteResourceOperation",
>>       "method": "DELETE"
>>     }
>>   ]
>> }
>>
>> And this:
>>
>> {
>>   "@context": "http://www.w3.org/ns/hydra/context.jsonld",
>>   "@id": "/an-issue",
>>   "title": "An exemplary issue representation",
>>   "operations": [
>>     {
>>       "@type": "Operation",
>>       "method": "DELETE"
>>     }
>>   ]
>> }
>>
> I have an application for this that I already posted to the list:
> Think about an API where some operations underly authorization restrictions.
> Such restrictions need to be managed, for example with a role based access
> control system.
> What you would need to express policies such as - Owners of Role A can carry
> out Operation "CreateResourceOperation" - for example are such operations.

Quite honestly, I wouldn't do that here. I would much rather make that
determination before i send back the JSON-LD document to the client.
If I have a create operation that a client doesn't have rights to
perform, they simply don't see it. Much like the way I won't present
an HTML form to a consumer that is not entitled to perform a
particular action. I'd evaluate rights higher up in the stack.

Thinking about this more, Hydra isn't really taking a "follow your
nose" approach. It seems that Hydra is defining all possible options
ahead of time in the context, thus giving little opportunity to make
security decisions at runtime.

> I hear you say that you could also specify a HTTP method but this would
> result in a two-dimensional system (Operation + HTTP Method) if you still
> want to use operations.
> So I think in some cases operations are required but in your simple example
> you could model everything with "@type": "Operation".
> Due to fact that APIs have diverse semantics of what HTTP operations really
> do (as you also examplify below), I think there are three ways to go forward
> with operations:
>
> 1.) Create an IANA Registry with some "standard" operations and clearly
> defined semantics

Perhaps not IANA, but have a somewhat robust set of initial operations
in Hydra core would fit the bill.

> 2.) Let each API provider create its own operations, also for very simple
> ones or hope for other vocabs to come up with a set of interoperable
> operations
>
> In any case I think the existing operations must be removed from hydra.


>
>> In either case, the client is still going to issue an HTTP DELETE request.
>> The function of the Hyrda operation is implied by the HTTP method that is
>> specified. CreateResourceOperation is also confusing. A new resource could
>> be created via PUT or POST. The intent of POST is not always create. In some
>> of my applications, I’m using POST in a fire and forget model and using a
>> 202 (Accepted) response to indicate success. The resource is receiving
>> events may affect another resource rather that modifying the requested
>> resource via CRUD actions. While yes, I subclass Operation and create my own
>> “FireAndForgetOperation” class. However, the client doesn’t need to know
>> anything about how my server is going to process the message. The POST
>> request may result in a creating a new resource, updating several others, or
>> it may even take a few days to process. The client only needs to know how to
>> format the request (i.e. hydra:expects and hydra:supportedProperties) and
>> how to send the message (hydra:method). With that said, I’m trying to
>> determine if there’s value in having types at that point? There's not much
>> to be gained by everyone inventing their own Operation types.
>>
>> I've said this before, but the Operation's type feels a lot like Link
>> relations rel attribute. In Hydra, we seem to be using @type to indicate the
>> function of the Operation. Arguably, Link relations do the same thing with
>> the rel attribute with the addition of a set of standard, relatively
>> well-understood relation types. Assuming that the intent of Operation
>> subclasses is similar to Link relation types, I can see Hydra both creating
>> some standard Operation types for common types and potentially incorporating
>> some IANA Link relation types. But this is where things get funky:
>> practically all Link relation types are intended for GET requests. JSON
>> Schema is using Link relations on non-idempotent links, but there’s really
>> not any link relation that I’m aware of that functions with anything other
>> than an HTTP GET.
>>
>> And this where things get a little more awkward for me. If we’re talking
>> about a search use case, we could potentially express it with an
>> IriTemplate:
>>
>> {
>>   "@context": "http://www.w3.org/ns/hydra/context.jsonld",
>>    "@type": "IriTemplate",
>>   "template": "http://api.example.com/issues{?query}
>> <http://api.example.com/issues%7B?query%7D>",
>>
>>   "mappings": [
>>     {
>>       "@type": "IriTemplateMapping",
>>       "variable": "query",
>>       "property": "#SearchCriteria",
>>       "required": true
>>     }
>>   ]
>> }
>>
>> But we might also be able to express it as:
>>
>> {
>>   "@context": "http://www.w3.org/ns/hydra/context.jsonld",
>>   "@id": "/issues",
>>   "title": "Reads a Resource",
>>   "operations": [
>>     {
>>       "@type": "ReadResourceOperation",
>>       "method": "GET",
>>       "expects" : "#SearchCriteria"
>>     }
>>   ]
>> }
>>
>> Ignore the fact for a moment that unlike JSON Schema’s Hyper Schema or
>> Collection+JSON, Hyrda does not specify that we should use the mappings as
>> URL query parameters rather than as a new JSON-LD structure. Something like
>> a search is typically done using GET and could be expressed via an
>> IriTemplate or Operation. Right now, a Link or TemplatedLink feels like an
>> Operation with a method property of GET, yet Hyrda is treating read controls
>> very differently than other type of links or operations.
>>
>> Lastly, I think we also need to add two new properties to in order to
>> indicate the media type that should be sent to the server and another that
>> hints at what might be returned from the request. For example:
>>
>> {
>>   "@context": "http://www.w3.org/ns/hydra/context.jsonld",
>>   "@id": "/an-issue",
>>   "title": "An exemplary issue representation",
>>   "operations": [
>>     {
>>       "@type": "Operation",
>>       "method": "POST"
>>       "enctype" : "application/x-www-form-urlencoded",
>>       “mediaType" : "application/pdf"
>>       ...
>>     }
>>   ]
>> }
>>
>> The enctype informs the client as to how to format the request message
>> while mediaType indicates the format that the server may return. If not
>> specified, the value should be application/ld+json if not specified. The
>> mediaType property is more coarse grained than the current hyrda:returns
>> property. in that we’re asserting that the response mediaType might be
>> something other than JSON-LD.
>
> Theoretically these bits of information could be introspected via HTTP
> requests (HEAD...) or on a higher level simply from the types (classes) but
> I also think that this might be valuable in some scenarios, e. g. if latency
> must be reduced.

For the media type values, yeah they could be gleaned from the
headers. For properties like "enctype", this would need to be done in
the descriptor. The enctype value would trigger how the request body
needs to be formatted before it is sent to the server. Thus, headers
aren't much help at that point. Think of a photo upload service: I
need to tell the client I can have it upload multiple photos as long a
they send them using multipart/mixed media type. That has to be said
before the client produces the message.

> JSON Hyper Schema has essentially the same facility to express expected and
> returned media/ types but I think they define no default. In any case, this
> should be optional.

Totally cribbing this idea from JSON Schema as it's very handy. And
yes, it's optional and use only in cases where your input format is
not going be JSON-LD.


>
>>
>> Without these properties, it’s very difficult to work with existing
>> content on the web, whether it be images, PDFs, or other formats such a
>> Atom, HAL+JSON, etc. and even plain old JSON or XML. JSON-LD is awesome, but
>> it’s not the only format on the web. While yes, some of these formats may
>> not fit the Hydra/JSON-LD model, but these formats are in use today. For
>> example, if my App is looking to see what the last 5 commits were on a
>> GitHub project, I need to be able to format a GET request with the required
>> URL parameters. I’m also going to be getting back JSON, not JSON-LD. Now I’m
>> not suggesting that Hydra go all out an support translating JSON data into
>> JSON-LD. No, that’s up to the client application. However, Hydra should be
>> able to properly instruct a client to properly format a
>> application/x-www-form-urlencoded request and indicate that the response may
>> not be a JSON-LD format.
>>
>> This is also where I really start to get hanky about hydra:returns and
>> hyrdra:statusCodes. Clients really need to get into the habit of reacting to
>> responses and sensing content via Content-Type and Link headers rather than
>> having a preconceived expectation at build time about what they might get
>> back. Perhaps abandoning the properties isn’t the right solution and perhaps
>> it could be resolved through a Hydra client API. As it stands, these Hydra
>> properties tee up client generators that would be a lot of like what tools
>> like WADL, Swagger, etc. do now.
>>
>> We need to make sure that Hydra can accommodate existing media types and
>> even link relations to a certain degree. These formats and conventions exist
>> now and applications and APIs are using them today. I’d really like to see
>> Hydra accommodate them in some capacity.
>>
>>
>> Ryan-
>>
>
>



-- 
Ryan J. McDonough
http://www.damnhandy.com

Received on Monday, 27 January 2014 15:19:12 UTC