HTTP interface

Resource API can be exposed via HTTP interface with 2nd level of REST Maturity Model

It can be achieved by passing Resource API service instance to WSGI application:

from werkzeug.serving import run_simple
from custom_app.service import CustomService
from resource_api_http.http import Application

srv = CustomService()
app = Application(srv, debug=True)
run_simple('127.0.0.1', 5000, app, use_debugger=True, use_reloader=True)

NOTE: there is no need to call setup() method before passing the service to WSGI app. WSGI app shall make the call itself.

General principles

  • structure of the resource is not exposed via URL schema
  • links between the resources are exposed via URL schema
  • it is not be possible to get links related to the resource via the same url as the resource itself
  • there isn’t any url to get a collection of the resources’ representations. Instead there are URLs to get a list of URIs first and later on use individual HTTP requests to fetch representations of each resource.
  • all resources have one and only one URI

URL schema

Http service has the follwoing URL schema:

LINK = RELATIONSHIP
RESOURCE_NAME = NAMESPACE.ACTUAL_RESOURCE_NAME
ID = Individual resource's URI
LINK_NAME = Name of the relationship in a triple
TARGET_ID = URI of the target resource in relationship's triple

# has to contain all required fields
{new_link_data} = {"@target": TARGET_PK, key: value}
# has to contain only the fields to be changed. Can't contain "@target".
{partial_link_data} = {key: value}

# has to contain all required fields
{new_resource_data} = {key: value, "@links": {link_to_many_name: [{new_link_data}, ...],
                                              link_to_one_name: {new_link_name}}}
# has to contain only the fields to be changed. Can't contain "@links".
{partial_resource_data} = {key: value}  # does not have to contain all fields


## Schema

OPTIONS /
>> {service_schema}

## Resource operations

  # create new resource
  POST {new_resource_data} /RESOURCE_NAME
  >> PK, 201 || None, 204

  # get a collection of IDs
  GET /RESOURCE_NAME
  >> [ID1, ID2, ..., IDN], 200

  # get a filtered collection of IDs
  GET /RESOURCE_NAME?query_param=value
  >> [ID1, ID2, ..., IDN], 200

  # get resource's representation
  GET /RESOURCE_NAME/ID
  >> {key: value}, 200

  # update certain fields of the resource
  PATCH {partial_resource_data} /RESOURCE_NAME/ID
  >> None, 204

  # remove the resource
  DELETE /RESOURCE_NAME/ID
  >> None, 204

  # get number of resources
  GET /RESOURCE_NAME:count
  >> integer count, 200

  # get number of resources with filtering
  GET /RESOURCE_NAME:count?query_param=value
  >> integer count, 200

## Link operations

  ### Link to one operations

    NOTE: "link" string is a part of the URL

    # get target resource's ID
    GET /RESOURCE_NAME/ID/LINK_NAME/item
    >> TARGET_ID, 200

    # update the link
    PATCH /RESOURCE_NAME/ID/LINK_NAME/item {partial_link_data}
    >> None, 204

    # create a new link or completely overwrite the existing one
    PUT /RESOURCE_NAME/ID/LINK_NAME {new_link_data}
    >> None, 204

    # get data related to the link
    GET /RESOURCE_NAME/ID/LINK_NAME/item:data
    >> {key: value}, 200

    # remove the link
    DELETE /RESOURCE_NAME/ID/LINK_NAME/item
    >> None, 204

  ### Link to many operations

    # get a collection of TARGET_IDs
    GET /RESOURCE_NAME/ID/LINK_NAME
    >> [TARGET_ID1, TARGET_ID2, ...], 200

    # get a filtered collection of TARGET_IDs
    GET /RESOURCE_NAME/ID/LINK_NAME?query_param=value
    >> [TARGET_ID1, TARGET_ID2, ...], 200

    # get number of links
    GET /RESOURCE_NAME/ID/LINK_NAME:count
    >> integer count, 200

    # get number of links with filtering
    GET /RESOURCE_NAME/ID/LINK_NAME:count?query_param=value
    >> integer count, 200

    # create a new link
    POST /RESOURCE_NAME/ID/LINK_NAME {new_link_data}
    >> None, 204

    # get data related to the link
    GET /RESOURCE_NAME/ID/LINK_NAME/TARGET_ID:data
    >> {partial_link_data}, 200

    # update the link
    PATCH /RESOURCE_NAME/ID/LINK_NAME/TARGET_ID {partial_link_data}
    >> None, 204

    # remove the link
    DELETE /RESOURCE_NAME/ID/LINK_NAME/TARGET_ID
    >> None, 204

Error status codes

  • 400 in case if request body is invalid
  • 403 for any issue related to user authentication/authorization. E.g. if user has no permission to change certain fields.
  • 404 if the resource/link being accessed does not exist
  • 405 when some HTTP method is not allowed with a specific URL
  • 409 when trying to perform the operation that causes conflicts
  • 501 when some functionality is not implemented
  • 500 when unknown server error takes place

WSGI Application reference

class resource_api_http.http.Application(service, debug=False)

Plain WSGI application for Resource API service

service (Service's subclass instance)
Service to generate HTTP interface for
debug (bool)
If True 500 responses will include detailed traceback describing the error