hypercontract is a concept for describing RESTful Web APIs using profiles written in RDF.
This workspace contains the source code of a prototype implementation of this concept. It consists of two applications:
- hypercontract - a web server that publishes the hypercontract RDF vocabulary
- hypershop - a demo application with an REST API documented with hypercontract
git clone https://github.com/hypercontract/hypercontract.git
cd hypercontract
npm install
Run npm start
and browse to...
- http://localhost to open hypershop
- http://localhost/profile to open the hypershop API documentation
- http://localhost:8080 to open the hypercontract vocabulary documentation
npm test
- Run E2E testsnpm start
, thennpm run test-postman
- run Postman tests
Alternatively, you can import Postman collections from /postman
into your Postman application.
The project is written in TypeScript and set up as an Nx Workspace consisting of two applications and two libraries.
hypercontract
hypercontract
is a web application built with NestJS, using Express under the hood. Its only purpose is to publish the hypercontract RDF vocabulary at https://hypercontract.org.
hypershop
hypershop
is a web application, also built with NestJS and Express. It serves as a demo to showcase how to describe a RESTful Web API using hypercontract. For this, it serves a simple online shop offering a catalog of randomly generated products that can be added to a shopping cart to place a new order.
The functionality of hypershop can be accessed through the browser as HTML representations or using an HTTP client as JSON, JSON-HAL or JSON-LD
All examples in this walkthrough can also be executed locally. Just replace the URLs accordingly:
The hypershop REST API supports JSON, JSON-HAL and JSON-LD as well as HTML. All requests in against the API can be executed in either of these formats.
- JSON (
application/json
) - JSON-HAL (
application/hal+json
) - JSON-LD (
application/ld+json
) - HTML (
text/html
)
Request the API Root as JSON-HAL.
GET https://example.hypercontract.org
Accept: application/hal+json
Requests with other media types fail with a 406 Not Acceptable
response.
GET https://example.hypercontract.org
Accept: application/xml
The hypershop REST API also supports Content Negotiation by Profile.
Request the API Root according to the hypershop profile (https://example.hypercontract.org/profile
).
GET https://example.hypercontract.org
Accept: application/ld+json
Accept-Profile: <https://example.hypercontract.org/profile>
Requesting a profile not supported by the application fails with a 406 Not Acceptable
response.
GET https://example.hypercontract.org
Accept: application/ld+json
Accept-Profile: <https://example.org>
Open the hypershop profile in your browser.
Note that...
- the Entry Point of the API is defined as
https://example.hypercontract.org
- the Entry Point URL returns an ApiRoot resource
- the Default Namespace of the API is defined as
https://example.hypercontract.org/profile/
This means that...
- the only URL we need to know is the entry point URL
- we can look up the
ApiRoot
definition to find out what we'll get when accessing the entry point - all descriptors can be dereferenced via their URIs by prefixing them with the default namespace.
You can also request a machine-readable version in various RDF formats:
- JSON-LD (
application/ld+json
) - RDF/XML (
application/rdf+xml
) - Turtle (
text/turtle
) - N-Triples (
application/n-triples
) - N-Quads (
application/n-quads
) - TriG (
application/trig
)
GET https://example.hypercontract.org/profile
Accept: application/hal+json
Open the ApiRoot
definition in your browser.
From the ApiRoot
resource there are four possible state transitions identified by these link relation types:
- to the Order History via
orderHistory
- to the Shopping Cart via
shoppingCart
- to the User Profile via
userProfile
- via the
searchCatalog
operation
You can also request a machine-readable version of all profile concepts.
GET https://example.hypercontract.org/profile/ApiRoot
Accept: application/hal+json
You can learn more a about any profile concept by prefixing the name with the default namepspace.
Open the searchCatalog
definition in your browser.
The definition of the searchCatalog
operation tells us that the state transition...
- is performed by a GET request against the link target
- the link target is a
SearchResults
resource - the request requires query parameters described by the
SearchQuery
class
Open the SearchQuery
definition in your browser.
The SearchQuery
definition only refers to a queryString
property of type string
which is a...
A free-text search term that is used to search the catalog for Products. It is matched against the product name and the product description.
As the SearchQuery
class describes the query parameters of the searchCatalog
operation, we need to know how to serialize this type as a query parameter. The profile specifies this using application/td+xml
schema describing a URI template of type text/uri-list
:
https://example.hypercontract.org/products{?queryString}
Open the SearchResults
definition in your browser.
The definition tells us that the representation returned when performing the searchCatalog
operation will contain the total number of results in a totalResults
descriptor as well as a list of Product
representations identified by the products
descriptor.
It also describes how the SearchResults
resource is serialized using JSON Schemas for
application/hal+json
application/json
application/ld+json
Search the catalog by requesting search results as JSON-LD.
GET https://example.hypercontract.org/products/?queryString=pizza
Accept: application/ld+json
The response contains a list of Product
s, each uniquely identified through the JSON-LD-specific @id
property. Every product also has a addToShoppingCart
descriptor.
Open the addToShoppingCart
definition in your browser.
addToShoppingCart
is an Operation like searchCatalog
. However, this time the state transition
- requires a POST request
- expects a request body matching the
AdditionToShoppingCart
concept - returns a representation of the
ShoppingCart
resource - (even though the target of the state transition is the
ShoppingCartItems
resource)
Open the AdditionToShoppingCart
definition to learn how to build the request body for the addToShoppingCart
operation.
Open the ShoppingCart
definition to learn what response to expect when performing the operation.
Use everything you learned to add a product to the shopping cart.
POST https://example.hypercontract.org/shoppingCart/items
Accept: application/ld+json
Content-Type: application/json
{
"product": "https://example.hypercontract.org/products/3c6118c5-ef72-4cfa-a767-933127c6e679",
"quantity": 2
}