RESTful Service Description Language
The RESTful Service Description Language (RSDL) is a machine- and human-readable XML description of HTTP-based web applications (typically REST web services).[1]
The language (defined by Michael Pasternak during his work on oVirt RESTful API) allows documenting the model of the resource(s) provided by a service, the relationships between them, and operations and the parameters that must be supplied for the operations. It specifies if parameters are mandated; and describes possible overloads as parameters sets.
RSDL is intended to simplify the reuse of web services that are based on the HTTP architecture of the web. It is platform- and language-independent and aims to promote reuse of applications beyond the basic use in a web browser by both humans and machines.
Unlike WADL, it concentrates on describing URIs as stand-alone entry points in to the application which can be invoked in different ways, does not require traversing over URI components to figure out URI structure, and supports URI/Headers/body parameters overloads. This makes it human-readable and easily consumed by both humans and machines.
Properties
- Self descriptive: RSDL represents different URIs as stand-alone entry points into the application. Following resource URIs, one can figure out which methods are available for the given resources and how those resources can be consumed.
- Machine-readable: Each URI in RSDL contains all the necessary information to generate an HTTP request from it, which can be easily consumed by accessing the URI internals.
- Human-readable: Each URI in RSDL contains "rel" and "description" attributes describing the meaning of the given operation on that URI. Humans can easily fetch all available operations for a given collection/resource simply by locating different descriptors within the same URI.
Format
<rsdl rel="rsdl" href="/api?rsdl">
<description />
<version revision="0" build="0" minor="0" major="0" />
<schema rel="schema" href="/api?schema">
<name>api.xsd</name>
<description />
</schema>
<general rel="*" href="/*">
<request>
<headers>
<header required="true|false">
<name />
<description />
<value />
</header>
</headers>
<url>
<parameters_set>
<parameter context="query|matrix" type="xs:string"
required="true|false">
<name />
<value />
</parameter>
</parameters_set>
</url>
</request>
<name />
<description />
</general>
<links>
<link rel="get|..." href="/api/xxx">
<request>
<http_method>GET|POST|PUT|DELETE|...</http_method>
<headers>
<header required="true|false">
<name />
<value />
</header>
</headers>
<url>
<parameters_set>
<parameter context="query|matrix" type=""
required="true|false">
<name />
<value />
</parameter>
</parameters_set>
</url>
<body>
<type>...</type>
<parameters_set>
<parameter type="" required="true|false">
<name>FQ-name-to-parameter</name>
</parameter>
</parameters_set>
</body>
</request>
<response>
<type />
</response>
</link>
</links>
</rsdl>
Components
URI
<links>
<link rel="get|..." href="/api/xxx">
Request
<request>
<http_method>GET|POST|PUT|DELETE|...</http_method>
<headers>
<header required="true|false">
<name></name>
<value></value>
</header>
...
</headers>
<url>
<parameters_set>
<parameter context="query|matrix" type="" required="true|false">
<name></name>
<value></value>
</parameter>
...
</parameters_set>
...
</url>
<body>
<type>...</type>
<parameters_set>
<parameter type="" required="true|false">
<name>FQ-name-to-parameter</name>
</parameter>
...
</parameters_set>
...
</body>
</request>
Response
<response>
<type></type>
...
</response>
XML schema
<xs:element name="detailedLinks" type="DetailedLinks"/>
<xs:complexType name="DetailedLinks">
<xs:sequence>
<xs:annotation>
<xs:appinfo>
<jaxb:property name="links"/>
</xs:appinfo>
</xs:annotation>
<xs:element type="DetailedLink" name="link" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:element name="link" type="Link"/>
<xs:complexType name="Link">
<xs:attribute name="href" type="xs:string"/>
<xs:attribute name="rel" type="xs:string"/>
</xs:complexType>
<xs:element name="url" type="Url"/>
<xs:complexType name="Url">
<xs:sequence>
<xs:element ref="parameters_set" maxOccurs="unbounded" minOccurs="0">
<xs:annotation>
<xs:appinfo>
<jaxb:property name="ParametersSets"/>
</xs:appinfo>
</xs:annotation>
</xs:element>
</xs:sequence>
</xs:complexType>
<xs:element name="body" type="Body"/>
<xs:complexType name="Body">
<xs:sequence>
<xs:element name="type" type="xs:string" minOccurs="1" maxOccurs="1"/>
<xs:element ref="parameters_set" maxOccurs="unbounded" minOccurs="0">
<xs:annotation>
<xs:appinfo>
<jaxb:property name="ParametersSets"/>
</xs:appinfo>
</xs:annotation>
</xs:element>
</xs:sequence>
<xs:attribute name="required" type="xs:boolean">
<xs:annotation>
<xs:appinfo>
<jaxb:property generateIsSetMethod="false"/>
</xs:appinfo>
</xs:annotation>
</xs:attribute>
</xs:complexType>
<xs:element name="request" type="Request"/>
<xs:complexType name="Request">
<xs:sequence>
<xs:element name="http_method" type="HttpMethod" minOccurs="1" maxOccurs="1"/>
<xs:element ref="headers" minOccurs="0" maxOccurs="1"/>
<xs:element ref="url" minOccurs="0" maxOccurs="1"/>
<xs:element ref="body" minOccurs="0" maxOccurs="1"/>
</xs:sequence>
</xs:complexType>
<xs:simpleType name="HttpMethod">
<xs:restriction base="xs:string">
<xs:enumeration value="GET"/>
<xs:enumeration value="POST"/>
<xs:enumeration value="PUT"/>
<xs:enumeration value="DELETE"/>
<xs:enumeration value="OPTIONS"/>
</xs:restriction>
</xs:simpleType>
<xs:element name="response" type="Response"/>
<xs:complexType name="Response">
<xs:sequence>
<xs:element name="type" type="xs:string" minOccurs="1" maxOccurs="1"/>
</xs:sequence>
</xs:complexType>
<xs:element name="parameter" type="Parameter"/>
<xs:complexType name="Parameter">
<xs:complexContent>
<xs:extension base="BaseResource">
<xs:sequence>
<xs:element name="value" type="xs:string" minOccurs="1" maxOccurs="1"/>
<xs:element ref="parameters_set" minOccurs="0" maxOccurs="1"/>
</xs:sequence>
<xs:attribute name="required" type="xs:boolean">
<xs:annotation>
<xs:appinfo>
<jaxb:property generateIsSetMethod="false"/>
</xs:appinfo>
</xs:annotation>
</xs:attribute>
<xs:attribute name="type" type="xs:string"/>
<xs:attribute name="context" type="xs:string"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:element name="header" type="Header"/>
<xs:complexType name="Header">
<xs:complexContent>
<xs:extension base="BaseResource">
<xs:sequence>
<xs:element name="value" type="xs:string" minOccurs="1" maxOccurs="1"/>
</xs:sequence>
<xs:attribute name="required" type="xs:boolean">
<xs:annotation>
<xs:appinfo>
<jaxb:property generateIsSetMethod="false"/>
</xs:appinfo>
</xs:annotation>
</xs:attribute>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:element name="headers" type="Headers"/>
<xs:complexType name="Headers">
<xs:sequence>
<xs:element ref="header" maxOccurs="unbounded">
<xs:annotation>
<xs:appinfo>
<jaxb:property name="Headers"/>
</xs:appinfo>
</xs:annotation>
</xs:element>
</xs:sequence>
</xs:complexType>
<xs:element name="parameters_set" type="ParametersSet"/>
<xs:complexType name="ParametersSet">
<xs:sequence>
<xs:element ref="parameter" maxOccurs="unbounded" minOccurs="0">
<xs:annotation>
<xs:appinfo>
<jaxb:property name="Parameters"/>
</xs:appinfo>
</xs:annotation>
</xs:element>
</xs:sequence>
</xs:complexType>
<xs:element name="schema" type="Schema"/>
<xs:complexType name="Schema">
<xs:complexContent>
<xs:extension base="Link">
<xs:sequence>
<xs:element name="name" type="xs:string" minOccurs="0" maxOccurs="1"/>
<xs:element name="description" type="xs:string" minOccurs="0" maxOccurs="1"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:element name="general_metadata" type="GeneralMetadata"/>
<xs:complexType name="GeneralMetadata">
<xs:complexContent>
<xs:extension base="DetailedLink">
<xs:sequence>
<xs:element name="name" type="xs:string" minOccurs="0" maxOccurs="1"/>
<xs:element name="description" type="xs:string" minOccurs="0" maxOccurs="1"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:element name="rsdl" type="RSDL"/>
<xs:complexType name="RSDL">
<xs:sequence>
<xs:element name="description" type="xs:string" minOccurs="0"/>
<xs:element type="Version" name="version" minOccurs="0" maxOccurs="1" />
<xs:element ref="schema" minOccurs="0" maxOccurs="1" />
<xs:element type="GeneralMetadata" name="general" minOccurs="0" maxOccurs="1"/>
<xs:element type="DetailedLinks" name="links" minOccurs="0"/>
</xs:sequence>
<xs:attribute name="href" type="xs:string"/>
<xs:attribute name="rel" type="xs:string"/>
</xs:complexType>
Examples
List resources
<link rel="get" href="/api/clusters">
<request>
<http_method>GET</http_method>
<headers>
<header required="false">
<name>Filter</name>
<value>true|false</value>
</header>
</headers>
<url>
<parameters_set>
<parameter context="query" type="xs:string" required="false">
<name>search</name>
<value>search query</value>
</parameter>
<parameter context="matrix" type="xs:boolean" required="false">
<name>case_sensitive</name>
<value>true|false</value>
</parameter>
<parameter context="matrix" type="xs:int" required="false">
<name>max</name>
<value>max results</value>
</parameter>
</parameters_set>
</url>
<body/>
</request>
<response>
<type>Clusters</type>
</response>
</link>
Get resource
<link rel="get" href="/api/clusters/{cluster:id}">
<request>
<http_method>GET</http_method>
<headers>
<header required="false">
<name>Filter</name>
<value>true|false</value>
</header>
</headers>
<body/>
</request>
<response>
<type>Cluster</type>
</response>
</link>
Update resource
<link rel="update" href="/api/clusters/{cluster:id}">
<request>
<http_method>PUT</http_method>
<headers>
<header required="true">
<name>Content-Type</name>
<value>application/xml|json</value>
</header>
<header required="false">
<name>Correlation-Id</name>
<value>any string</value>
</header>
</headers>
<body>
<type>Cluster</type>
<parameters_set>
<parameter type="xs:string" required="false">
<name>cluster.name</name>
</parameter>
<parameter type="xs:string" required="false">
<name>cluster.description</name>
</parameter>
<parameter type="xs:string" required="false">
<name>cluster.cpu.id</name>
</parameter>
<parameter type="xs:int" required="false">
<name>cluster.version.major</name>
</parameter>
<parameter type="xs:int" required="false">
<name>cluster.version.minor</name>
</parameter>
<parameter type="xs:double" required="false">
<name>cluster.memory_policy.overcommit.percent</name>
</parameter>
<parameter type="xs:boolean" required="false">
<name>cluster.memory_policy.transparent_hugepages.enabled
</name>
</parameter>
<parameter type="xs:string" required="false">
<name>cluster.scheduling_policy.policy</name>
</parameter>
<parameter type="xs:int" required="false">
<name>cluster.scheduling_policy.thresholds.low</name>
</parameter>
<parameter type="xs:int" required="false">
<name>cluster.scheduling_policy.thresholds.high</name>
</parameter>
<parameter type="xs:int" required="false">
<name>cluster.scheduling_policy.thresholds.duration</name>
</parameter>
<parameter type="xs:string" required="false">
<name>cluster.error_handling.on_error</name>
</parameter>
<parameter type="xs:boolean" required="false">
<name>cluster.virt_service</name>
</parameter>
<parameter type="xs:boolean" required="false">
<name>cluster.gluster_service</name>
</parameter>
<parameter type="xs:boolean" required="false">
<name>cluster.threads_as_cores</name>
</parameter>
<parameter type="xs:boolean" required="false">
<name>cluster.tunnel_migration</name>
</parameter>
</parameters_set>
</body>
</request>
<response>
<type>Cluster</type>
</response>
</link>
Create resource
<link rel="add" href="/api/clusters">
<request>
<http_method>POST</http_method>
<headers>
<header required="true">
<name>Content-Type</name>
<value>application/xml|json</value>
</header>
<header required="false">
<name>Expect</name>
<value>201-created</value>
</header>
<header required="false">
<name>Correlation-Id</name>
<value>any string</value>
</header>
</headers>
<body>
<type>Cluster</type>
<parameters_set>
<parameter type="xs:string" required="true">
<name>cluster.data_center.id|name</name>
</parameter>
<parameter type="xs:string" required="true">
<name>cluster.name</name>
</parameter>
<parameter type="xs:int" required="true">
<name>cluster.version.major</name>
</parameter>
<parameter type="xs:int" required="true">
<name>cluster.version.minor</name>
</parameter>
<parameter type="xs:string" required="true">
<name>cluster.cpu.id</name>
</parameter>
<parameter type="xs:string" required="false">
<name>cluster.description</name>
</parameter>
<parameter type="xs:double" required="false">
<name>cluster.memory_policy.overcommit.percent</name>
</parameter>
<parameter type="xs:boolean" required="false">
<name>cluster.memory_policy.transparent_hugepages.enabled</name>
</parameter>
<parameter type="xs:string" required="false">
<name>cluster.scheduling_policy.policy</name>
</parameter>
<parameter type="xs:int" required="false">
<name>cluster.scheduling_policy.thresholds.low</name>
</parameter>
<parameter type="xs:int" required="false">
<name>cluster.scheduling_policy.thresholds.high</name>
</parameter>
<parameter type="xs:int" required="false">
<name>cluster.scheduling_policy.thresholds.duration</name>
</parameter>
<parameter type="xs:string" required="false">
<name>cluster.error_handling.on_error</name>
</parameter>
<parameter type="xs:boolean" required="false">
<name>cluster.virt_service</name>
</parameter>
<parameter type="xs:boolean" required="false">
<name>cluster.gluster_service</name>
</parameter>
<parameter type="xs:boolean" required="false">
<name>cluster.threads_as_cores</name>
</parameter>
<parameter type="xs:boolean" required="false">
<name>cluster.tunnel_migration</name>
</parameter>
</parameters_set>
</body>
</request>
<response>
<type>Cluster</type>
</response>
</link>
Delete resource
<link rel="delete" href="/api/clusters/{cluster:id}">
<request>
<http_method>DELETE</http_method>
<headers>
<header required="false">
<name>Correlation-Id</name>
<value>any string</value>
</header>
</headers>
<url>
<parameters_set>
<parameter context="matrix" type="xs:boolean" required="false">
<name>async</name>
<value>true|false</value>
</parameter>
</parameters_set>
</url>
<body/>
</request>
</link>
Code generation
RSDL URI descriptor
<link rel="add" href="/api/clusters">
<request>
<http_method>POST</http_method>
<headers>
<header required="true">
<name>Content-Type</name>
<value>application/xml|json</value>
</header>
<header required="false">
<name>Expect</name>
<value>201-created</value>
</header>
<header required="false">
<name>Correlation-Id</name>
<value>any string</value>
</header>
</headers>
<body>
<type>Cluster</type>
<parameters_set>
<parameter type="xs:string" required="true">
<name>cluster.data_center.id|name</name>
</parameter>
<parameter type="xs:string" required="true">
<name>cluster.name</name>
</parameter>
<parameter type="xs:int" required="true">
<name>cluster.version.major</name>
</parameter>
<parameter type="xs:int" required="true">
<name>cluster.version.minor</name>
</parameter>
<parameter type="xs:string" required="true">
<name>cluster.cpu.id</name>
</parameter>
<parameter type="xs:string" required="false">
<name>cluster.description</name>
</parameter>
<parameter type="xs:double" required="false">
<name>cluster.memory_policy.overcommit.percent</name>
</parameter>
<parameter type="xs:boolean" required="false">
<name>cluster.memory_policy.transparent_hugepages.enabled</name>
</parameter>
<parameter type="xs:string" required="false">
<name>cluster.scheduling_policy.policy</name>
</parameter>
<parameter type="xs:int" required="false">
<name>cluster.scheduling_policy.thresholds.low</name>
</parameter>
<parameter type="xs:int" required="false">
<name>cluster.scheduling_policy.thresholds.high</name>
</parameter>
<parameter type="xs:int" required="false">
<name>cluster.scheduling_policy.thresholds.duration</name>
</parameter>
<parameter type="xs:string" required="false">
<name>cluster.error_handling.on_error</name>
</parameter>
<parameter type="xs:boolean" required="false">
<name>cluster.virt_service</name>
</parameter>
<parameter type="xs:boolean" required="false">
<name>cluster.gluster_service</name>
</parameter>
<parameter type="xs:boolean" required="false">
<name>cluster.threads_as_cores</name>
</parameter>
<parameter type="xs:boolean" required="false">
<name>cluster.tunnel_migration</name>
</parameter>
</parameters_set>
</body>
</request>
<response>
<type>Cluster</type>
</response>
</link>
Generated code signature(s)
/**
* Adds Cluster object.
* @param cluster {@link org.ovirt.engine.sdk.entities.Cluster}
* cluster.data_center.id|name
* cluster.name
* cluster.version.major
* cluster.version.minor
* cluster.cpu.id
* [cluster.description]
* [cluster.memory_policy.overcommit.percent]
* [cluster.memory_policy.transparent_hugepages.enabled]
* [cluster.scheduling_policy.policy]
* [cluster.scheduling_policy.thresholds.low]
* [cluster.scheduling_policy.thresholds.high]
* [cluster.scheduling_policy.thresholds.duration]
* [cluster.error_handling.on_error]
* [cluster.virt_service]
* [cluster.gluster_service]
* [cluster.threads_as_cores]
* [cluster.tunnel_migration]
* @return
* {@link Cluster }
* @throws ClientProtocolException
* Signals that HTTP/S protocol error has occurred.
* @throws ServerException
* Signals that an oVirt api error has occurred.
* @throws IOException
* Signals that an I/O exception of some sort has occurred.
*/
public Cluster add(org.ovirt.engine.sdk.entities.Cluster cluster) throws
ClientProtocolException, ServerException, IOException {
....
}
/**
* Adds Cluster object.
* @param cluster {@link org.ovirt.engine.sdk.entities.Cluster}
* cluster.data_center.id|name
* cluster.name
* cluster.version.major
* cluster.version.minor
* cluster.cpu.id
* [cluster.description]
* [cluster.memory_policy.overcommit.percent]
* [cluster.memory_policy.transparent_hugepages.enabled]
* [cluster.scheduling_policy.policy]
* [cluster.scheduling_policy.thresholds.low]
* [cluster.scheduling_policy.thresholds.high]
* [cluster.scheduling_policy.thresholds.duration]
* [cluster.error_handling.on_error]
* [cluster.virt_service]
* [cluster.gluster_service]
* [cluster.threads_as_cores]
* [cluster.tunnel_migration]
* @param expect
* [201-created]
* @param correlationId
* [any string]
* @return
* {@link Cluster }
* @throws ClientProtocolException
* Signals that HTTP/S protocol error has occurred.
* @throws ServerException
* Signals that an oVirt api error has occurred.
* @throws IOException
* Signals that an I/O exception of some sort has occurred.
*/
public Cluster add(org.ovirt.engine.sdk.entities.Cluster cluster, String expect, String correlationId) throws
ClientProtocolException, ServerException, IOException {
....
}
References
- "RESTful Service Description Language (RSDL)". balisage.net.