HydraCG/Specifications

Make hydra:error compatible with RFC 7807

asbjornu opened this issue ยท 24 comments

As discussed in #39, it would be useful if hydra:error responses were compatible with RFC 7807. Defining a @context for application/problem+json that defines "instance": "@id" should achieve what @RubenVerborgh is after, I believe.

Yes, we'd need a @context, which would also be define the other properties of the problem details object.

Guess that for starters we could publish it under hydra's domain but how would you define RFC 7807 terms? I think I recall talk of similar effort with @dret. Isn't there already an attempt to create JSON-LD profile for problem+json? Or, in more general terms, an RDF vocabulary for the Problem Details spec?

The end result could be similar to the following

{
    "@context": [
        "http://www.w3.org/ns/hydra/context.jsonld",
        "http://www.w3.org/ns/hydra/problem+json/context.jsonld",
        "https://example.com/errors.context"
    ],
    "@type": [
        "Error",
        "https://example.com/probs/out-of-credit"
    ],
    "type": "https://example.com/probs/out-of-credit",
    "title": "You do not have enough credit.",
    "detail": "Your current balance is 30, but that costs 50.",
    "instance": "/account/12345/msgs/abc",
    "balance": 30,
    "accounts": ["/account/12345", "/account/67890"]
   }

Some things to note:

  1. Additional @context would be added to define API-specific error details (balance)
  2. type is problematic and would have to be duplicated if one were to also use it as an RDF type. The RFC defines it as string and so it cannot be simply redefined as @type
dret commented

Ok, that is good. We have a clean slate.

@dret how would you go about this? I assume we'd start working on this in Hydra CG but publish the @context JSON within a more neutral ground. Or do you think it's completely acceptable to keep it at Hydra?

dret commented

Awesome, @dret - if you can spare some time on this, it would be much appreciated.
As for the solution - generic would be better, but if it means separate lifecycle, repo and so on that could cause discrepancies or other obstacles, I'd prefer something closer to hydra

dret commented

When the server shall return an error description, what would be the content-type?

Should it send JSON-LD, possibly with a profile? Or should it return application/problem+json and the Hydra client should treat it as LD?

I think best would be application/problem+json and JSON-LD context linked in the header. This will cover both Hydra-enabled and generic clients,

I had that though too, but I think it will put additional weight on the server implementation where potentially the link will change for different errors.

Also, it will not be possible to have multiple contexts like you can using a JS array as seen in my snippet above.

Why is a special content-type required? Can the JSON-LD content-type type be used instead?

It's not a special content type. It's the content type defined by RFC 7807.

@akuckartz, an application/ld+json content-type will hide the fact that the response adheres to RFC 7807 and only make the content accessible to JSON-LD enabled clients. Responding with Content-Type: application/problem+json will make it clear that the response follows RFC 7807 and a context in a Link header can "upgrade" the response to JSON-LD for clients that understand it.

Just to be clear, this is how Hydra-enabled APIs should respond when a problem occurs:

Content-Type: application/problem+json
Link: <http://www.w3.org/ns/hydra/problem+json/context.jsonld>; rel="http://www.w3.org/ns/json-ld#context"; type="application/ld+json"

{
    "type": "https://example.com/probs/out-of-credit",
    "title": "You do not have enough credit.",
    "detail": "Your current balance is 30, but that costs 50.",
    "instance": "/account/12345/msgs/abc",
    "balance": 30,
    "accounts": ["/account/12345", "/account/67890"]
}

My hope is that we can avoid the inline JSON-LD syntax and just do it all in the linked problem+json/context.jsonld file.

I was experimenting and my conclusion is:

  1. Context that could be published at http://www.w3.org/ns/hydra/error.context.jsonld should look like this:
{
    "hydra": "http://www.w3.org/ns/hydra/core#",
    "type": "@type",
    "title": "hydra:title",
    "detail": "hydra:description",
    "status": "hydra:statusCode",
    "instance": "hydra:instance"
}

We shall also add these statements to the vocabulary itself so the resulting RDF is fully transformed into hydra based statements:

...,
{
    "@id": "hydra:instance",
    "@type": "hydra:Link",
    "label": "instance",
    "comment": "Identifies the specific occurrence of the problem.",
    "domain": "hydra:Error",
    "vs:term_status": "testing"
},
...

Example available here.

Having thought more about this, I would prefer if we could find another home for the RFC 7807 context than Hydra. Perhaps @gkellogg or someone else from the @json-ld organization can assist in finding a more generic home for it?

I'm not sure why it should be maintained outside Hydra's namespace ? That context is supposed to elevate raw RFC 7807 JSON payload into an RDF fully described with Hydra's terms. I don't see how other places could fit better. I also do not understand what you had in mind by writing "generic".

What I meant was that having the vocabulary for problem+json defined in something like schema.org would ease adoption since most people have a dependency on that already. Many people may want to use the context and vocabulary for RFC 7807 without wanting to use Hydra. Taking on the entirety of Hydra's context and vocabulary may therefore feel a bit excessive.

Many people may want to use the context and vocabulary for RFC 7807 without wanting to use Hydra.

Than why use a Hydra's RFC 7807 context? I see no benefits from using such a context. Please, elaborate more - I'd like to understand your reasons.

Taking on the entirety of Hydra's context and vocabulary may therefore feel a bit excessive.

Now I'm lost. We're not discussing a one-for-all-ultimate-solution context that is supposed to be used for any kind of error, we're just trying to adopt hydra to RFC 7807 that becomes a standard so developers won't be put in situation requiring any sacrifices from them.

I think maybe this is what I awkwardly meant when we last spoke.

Instead of fitting problem+json into hydra:Error we could make an independent RDF bindings for the problem document and have Hydra import that.

We're not discussing a one-for-all-ultimate-solution context that is supposed to be used for any kind of error, we're just trying to adopt hydra to RFC 7807 that becomes a standard so developers won't be put in situation requiring any sacrifices from them.

Ok, let me try another angle. Imagine schema.org already published a JSON-LD context with terms for every reserved keyword in the RFC 7807 specification. Would we consider redefining this context and its terms in Hydra's vocabulary or would we just use schema.org's context and vocabulary verbatim?

If your answer to that question is "no", then that's the reality I think we should attempt to create: One where some other entity than Hydra CG creates a context and vocabulary for RFC 7807. Once that reality exists, we can adapt and adjust hydra:Error to it.

Instead of fitting problem+json into hydra:Error

There is not to much to do in here. The only thing that needs some thoughts is instance, that actually could be mapped to hydra:object rather than new term introduced in my last example.

we could make an independent RDF bindings for the problem document and have Hydra import that

But what would by Hydra worth if it couldn't let developers describe their APIs in most basic situations, like error handling without using other vocabularies? Hydra currently does not import any external vocabularies and we're trying hard to have hydra closed in semantics, but opened for extensions - I believe we shall keep doing it.

As for what @asbjornu wrote - there are many ifs that are vague. There is also an opposite possibility of incorporating Hydra into schema.org. This is the only vocabulary I'd consider to align to as it's a big player maintained by even bigger players.

We had a chat with @tpluscode and he suggested using rdfs:seeAlso instead of hydra:object. After some reading in both specs I feel it fits perfectly. Example would end up like this (stil possibly available at http://www.w3.org/ns/hydra/error.context.jsonld):

{
    "hydra": "http://www.w3.org/ns/hydra/core#",
    "rdfs": "http://www.w3.org/2000/01/rdf-schema#",
    "type": "@type",
    "title": "hydra:title",
    "detail": "hydra:description",
    "status": "hydra:statusCode",
    "instance": { "@id": "rdfs:seeAlso", "@type": "@id" }
}

There is no need to introduce any new terms in the hydra itself.

The only thing that irks me with rdfs:seeAlso is its name. hydra:object is intuitive โ€“ rdfs:seeAlso is not. To be honest, at face value, rdfs:seeAlso makes absolutely zero sense, at least for someone (like me) who isn't an RDF aficionado.

I see how rdfs:seeAlso may sound weird but you it is in fact a very basic term used in all kinds of RDF. A very generic way for linking to resources related in some unspecified way.