question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Allow documenting HATEOAS APIs (pathless operation / interface / URI class / operation type)

See original GitHub issue

TLDR

(added after some discussion)

  • “interfaces” (like path items, just without path parameters, and not linked to a path template)
  • a path item can refer to an interface (which is implemented), possibly adding path parameters to it
  • a string property (containing an URI) in a schema can refer to an interface (which means the consumer can know which operations can be used on this URI)

Background / Current Situation

I work at a company where our Restful API Guidelines prescribe both “document your API using OpenAPI” and “Use HATEOAS” (“Hypertext as the Engine of Application State”, one of the core principles of REST).

Unfortunately both do not work together nicely:

  • Swagger/OpenAPI 2.0’s model is “we have paths which can be distinguished in some way, and describe the operations on those paths” (including their data format).
  • The HATEOAS model is “The client gets a result which might contain links to other resources, and can decide to follow them, no matter which URI format they have”.

Currently the intersection between both is “have links in your result, but just to URIs which are also described as paths in your Swagger definition, and describe in descriptions what kind of URIs you can expect”.

Ideas

A core point of HATEOAS are media types and link relations. An API definition should mainly be a description of the media types and what operations they imply for links included in them. (Paraphrased from a blogpost of Roy Fielding.)

Media type definitions are analogous to what OpenAPI’s definitions are currently, might even be an extension of that. For models with a property of type string, format uri we can then additionally refer to the URI class of that URI.

A URI class is defined analogously to the current path definitions, but with some name to be used in model definitions. The URI class defines what operations are possible on an URI, which parameters are allowed/needed (no path parameters, I guess), and what can be expected in return. (The URI class is not a property of the URI itself, but of its usage in a specific place. The same URI could appear with multiple URI classes.)

I’m not yet sure how link relations can come into this – I guess we might need a way to define the URI class depending on link relation or similar.

A client needs just some initial “bookmark URI” (so a single path definition might be fine), and then can take a link (with a given URI class) and use the operation behind the URI class to do what it wants to do. The format of the second URI doesn’t matter anymore to the client – it can even have a different domain name than the bookmark one. But still everything can be strongly typed if wanted.

Issue Analytics

  • State:closed
  • Created 8 years ago
  • Reactions:49
  • Comments:72 (50 by maintainers)

github_iconTop GitHub Comments

9reactions
DavidBiesackcommented, Mar 18, 2016

The use of x-interfaces / x-interface in #576 seems to solve a different problem (that of several APIs or API subresources implementing an API contract/interface/pattern.)

I’m more interested in the OP question of defining and documenting an API via HATEOAS. We’d like to hide the paths in the API (i.e. in the UI) and encourage clients to consume links rather that hard-code the API to fixed paths. (The paths become more of an implementation detail. They still exist and could be revealed in the UI for reference / lookup, or presented in an alternate view.)

Thus, an API starts at the root and the client can discover the set of links to nested resources via compound keys that include a link relation (name), a verb (PUT, POST, etc.), a type (request and/or response media type), and a description. The definition of a link may also include a path but that is more of an implementation attribute. Thus, each path in an OAS can be associated with one or more contained resources

For example if the API has two primary resources, models and activities, the root would contain

paths:
  /:
    resources:
      root:
        links:
          models: 
               rel: models
               method: GET
               uri: /models
               type: application/vnd.collection+json
               description: Retrieve a paginated list of models
          createModel:
               method: POST
               uri: /models
               type: application/vnd.example.model+json
               description: Create a new model resource in this collection
          activities: 
               method: GET
               uri: /activities
               type: application/vnd.collection+json
               description: Retrieve a paginated list of activities
          createActivity:
               method: POST
               uri: /models
               type: application/vnd.example.activity+json
               description: Create a new activity resource in this collection


  /models:
    resources:
      models:
        collectionItems:
          model:
             uri: /models/{modelId}
        links:      # these are links associated with the collection
          self:
            ...
          next:
            ...
          prev:
            ...
          first:
            ...
          last:
            ...
          create:
            ...
  /models/{modelId}:
    resources:
      model:
        links:
          self:
            method: GET
            type: application/vnd.example.model+json
            description: Fetch a representation of this model
          image:
            method: GET
            type: image/png
            description: Fetch a graphical representation of this model
          pdf:
            method: GET
            type: application/pdf
            description: Fetch a PDF representation of this model
          update:
            method: PUT
            type: application/vnd.example.model+json
            description: Replace the representation of this mdoel
          patch:
            method: PATCH
            type: application/vnd.example.model+json
            description: Update the representation of this mdoel with partial representation
          delete:
            method: DELETE
            description: Delete this model.
          analyze:
            method: POST
            type: application/vnd.example.activities+json
            uri: /activities?model={modelId}
            description: Create an analysis activity

So from the root, one can find models and activities (as resources), and also discover how to create activities, and from the collection, one can access an individual model. From a model, there are links for operations on that model (the uri is inherited from the current path context).

The UI could then navigate the API by exploring links (hiding the URI by default).

8reactions
cbornetcommented, Nov 11, 2020

I’ve published a blog post on the OHM format : https://dev.to/cbornet/ohm-the-mediatype-for-rest-hateoas-powered-by-openapi-2aba . Happy to get your feedback on it !

Read more comments on GitHub >

github_iconTop Results From Across the Web

Spring HATEOAS - Reference Documentation
This project provides some APIs to ease creating REST representations that follow the HATEOAS principle when working with Spring and especially ...
Read more >
RESTful API Evolution With HATEOAS | by Victor Krapivin
Sometimes we need to change resource URI but do not break API client. ... Allow documenting HATEOAS APIs (pathless operation / interface ......
Read more >
Spring Boot REST API CRUD with HATEOAS Tutorial
Tutorial for developing REST APIs that follow HATEOAS principle with Spring Boot and Spring HATEOAS. Adding hypermedia links for REST APIs.
Read more >
Virtualization - HATEOAS API - Axway Community
I need to virtualize en external API (provided by a third party) into our api platform. This API is fully HATEOAS compliant with...
Read more >
Applying HATEOAS to a REST API with Spring Boot
linkTo creates the link and methodOn gets the URI for the GymMembershipController.all method ( people/{id}/memberships ), both of these methods are static ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Hashnode Post

No results found