plexus / yaks

Ruby library for building hypermedia APIs
http://rubygems.org/gems/yaks
MIT License
236 stars 26 forks source link

RFC: Error Handling #112

Open plexus opened 9 years ago

plexus commented 9 years ago

This proposal outlines how Yaks will handle the representation of errors that occur in the API and need to be communicated back to the client.

Objectives:

Documents consulted:

An error is represented in Yaks as a Yaks::Resource with a type of "error" (String, lowercase). An error can either be rendered at the top level, or as a subresource. There is no standard RCF5988 rel type for errors, so it is recommended applications use a fully qualified URI as a rel, e.g. http://api.example.org/rel/error.

A Yaks::Resource with type "error" (henceforth called an "error resource") like any resource can have attributes, links, and controls. The attributes error_id, http_status, error_code, timestamp, title, messages, dev_description are reserve. When present they have specific semantics, and they may be treated specially by output formats.

  Yaks JSON-API Mason Siren proposal Collection+JSON
unique id for occurance error_id id id (req)   code
HTTP status code http_status status httpStatusCode code  
error code (string) error_code code code    
timestamp when the error occurred timestamp   time    
human readable summary of type of error (stable over occurances) title title message message title
human readable explanation specific to occurance (end user) messages detail messages (array)   message
human readable explanation specific to occurance (client dev) dev_message   details    
free-form extra attributes   meta      
links collection   links (only about) controls    
reference to location in request doc causing error   source/pointer      
reference to URI query parameter causing error   source/parameter      

The table above shows how these attributes map to field names as standardized for each format. Reserved attributes that don't have a matching output field name, or non-reserved attributes, should be rendered as regular attributes in the output, if the output format supports extra attributes on error responses.

This proposal standardizes features that not all output formats support. Output formats that have an explicit affordance for error responses should render those attributes that the format specification provides for, and ignore others. Formats where error handling is unspecified should render an error resource as a regular Yaks resource.

Form Errors

Yaks already has an existing, but undocumented, affordance regarding errors, the error property on Yaks::Resource::Form::Field.

This field is intended for applications that render forms on the client side based on hypermedia form controls. When server-side validation of a form submission fails, then the server can return the submitted form with inline error messages present.

The format of the error property is a Hash. Each entry represents a failed validation, with the key being machine readable, and the value being human readable, possibly localized.

{'errors.email_format' => 'The email address is invalid'}

Formats that support rendering form controls with inline errors should render these as is. Other formats that allow including multiple messages should extract these and render them as part of the messages

Links

Since an error resource is a resource it may contain links. For a link pointing to error details the about rel as standardized by IANA should be used. This is also the rel expected by JSON-API clients.

Reserved Attributes

An overview of the attributes, with the definitions and restrictions that individual formats impose on them. Unfortunately only JSON-API and Mason explain what the fields they define mean.

error_id

A unique id for this occurance. Useful for searching application logs.

JSON-API a unique identifier for this particular occurrence of the problem.

Mason This property is OPTIONAL. If present it MUST be a string value. It should contain a unique identifier for later reference to the situation that resulted in a error condition (for instance when looking up a log entry).

Collection+JSON The code property MAY be a child property of the error object. It SHOULD be a STRING type.

http_status

The HTTP status code. Some formats expect this to be a string, others an integer. An error resource can use either representation. It is up to the Format to coerce accordingly with to_s / to_i.

JSON-API the HTTP status code applicable to this problem, expressed as a string value.

Mason This property is OPTIONAL. If present it MUST be a an integer value. It should contain the HTTP status code from the latest response.

error_code

An code (string) representing the type of error. Multiple occurances of the same error will have the same code. This might correspond with a specific Exception subclass.

JSON-API an application-specific error code, expressed as a string value.

Mason This property is OPTIONAL. If present it MUST be a string value. It should contain a code describing the error condition in general.

title

A human readable message describing the type of error. May be localized. Multiple occurances of the same error with the same locale will have the same title. This might correspond with a specific Exception subclass.

JSON-API a short, human-readable summary of the problem that SHOULD NOT change from occurrence to occurrence of the problem, except for purposes of localization.

Mason This property is OPTIONAL. If present it MUST be an array of strings. It should contain an array of additional human readable error messages directed at the end user.

Collection+JSON The message property MAY be a child property of the error object. It SHOULD be a STRING type.

messages

An array of human readable messages, specific to this occurance of the problem. Formats that only render a single message should concatenate multiple messages with spaces.

JSON-API a human-readable explanation specific to this occurrence of the problem.

Mason This property is OPTIONAL. If present it MUST be an array of strings. It should contain an array of additional human readable error messages directed at the end user.

Collection+JSON The message property MAY be a child property of the error object. It SHOULD be a STRING type.

dev_message

A message intended for the developer consuming the API. Should not be shown to the end user.

Mason This property is OPTIONAL. If present it MUST be a string value. It should contain an extensive human readable message directed at the client developer.

timestamp

A timestamp of when the error occured. Should be a Ruby Time or DateTime object.

Mason This property is OPTIONAL. If present it MUST be a string value representing a date in the format defined by RFC 3339. Example: "1985-04-12T23:20:50.52Z". It should contain a timestamp of when the error condition occured.

plexus commented 9 years ago

cc @janko-m @chastell @carlesjove @groyoh @mamund @JornWildt @mikekelly @kevinswiber