لغة وصف الخدمة RESTful
لغة وصف خدمات RESTful ( RSDL ) هي وصف XML قابل للقراءة آليًا وبشريًا لتطبيقات الويب القائمة على بروتوكول HTTP (عادةً خدمات الويب REST ). [ 1 ]
تتيح هذه اللغة (التي وضعها مايكل باستيرناك أثناء عمله على واجهة برمجة تطبيقات RESTful الخاصة بـ oVirt ) توثيق نموذج الموارد التي توفرها الخدمة، والعلاقات بينها، والعمليات والمعلمات التي يجب توفيرها لهذه العمليات. كما تحدد ما إذا كانت المعلمات إلزامية، وتصف التحميلات الزائدة المحتملة كمجموعات معلمات.
تهدف لغة RSDL إلى تبسيط إعادة استخدام خدمات الويب القائمة على بنية HTTP للويب. وهي مستقلة عن المنصات واللغات، وتهدف إلى تعزيز إعادة استخدام التطبيقات بما يتجاوز الاستخدام الأساسي في متصفح الويب من قِبل البشر والآلات على حد سواء.
بخلاف WADL ، يركز هذا الأسلوب على وصف معرّفات الموارد الموحدة (URIs) كنقاط دخول مستقلة إلى التطبيق، والتي يمكن استدعاؤها بطرق مختلفة، ولا يتطلب استعراض مكونات معرّف الموارد الموحدة (URI) لفهم بنيته، كما يدعم تحميل معلمات معرّف الموارد الموحدة (URI) والرؤوس والجسم بشكل زائد. وهذا ما يجعله سهل القراءة والاستخدام من قِبل البشر والآلات على حد سواء.
ملكيات
- وصف ذاتي : يُمثل RSDL معرّفات الموارد الموحدة (URIs) المختلفة كنقاط دخول مستقلة إلى التطبيق. وباتباع معرّفات الموارد الموحدة، يُمكن تحديد الطرق المتاحة للموارد المحددة وكيفية استخدامها.
- قابل للقراءة آلياً : يحتوي كل URI في RSDL على جميع المعلومات الضرورية لإنشاء طلب HTTP منه، والتي يمكن استهلاكها بسهولة عن طريق الوصول إلى المكونات الداخلية لـ URI.
- سهل القراءة : يحتوي كل معرّف موارد موحد (URI) في RSDL على سمات "rel" و"description" التي تصف معنى العملية المحددة على ذلك المعرّف. يمكن للمستخدمين بسهولة استرجاع جميع العمليات المتاحة لمجموعة/مورد معين بمجرد تحديد واصفات مختلفة ضمن نفس المعرّف.
شكل
<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>عناصر
معرّف الموارد الموحد (URI)
<links> <link rel= "get|..." href= "/api/xxx" >طلب
<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> <type></type> ... </response>مخطط XML
<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>أمثلة
قائمة الموارد
<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> مجموعات </type> </response> </link>الحصول على الموارد
<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>تحديث الموارد
<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.<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>إنشاء مورد
<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.النسبة المئوية </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= <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>حذف المورد
<link rel= "delete" href= "/api/clusters/{cluster:id}" > <request> <http_method> حذف </http_method> <headers> <header required= "false" > <name> معرف الارتباط </name> <value> أي سلسلة نصية </value> </header> </headers> <url> <parameters_set> <parameter context= "matrix" type= "xs:boolean" required= "false" > <name> غير متزامن </name> <value> صحيح|خطأ </value> </parameter> </parameters_set> </url> <body/> </request> </link>توليد الكود
واصف RSDL URI
<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.النسبة المئوية </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= <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>التوقيع (التوقيعات) البرمجية المُولَّدة
/** * يضيف كائن المجموعة. * @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 * يشير إلى حدوث خطأ في بروتوكول HTTP/S. * @throws ServerException * يشير إلى حدوث خطأ في واجهة برمجة تطبيقات oVirt. * @throws IOException * يشير إلى حدوث استثناء إدخال/إخراج من نوع ما. */ public Cluster add ( org . ovirt . engine . sdk . entities . Cluster cluster ) throws ClientProtocolException , ServerException , IOException {.... }/** * يضيف كائن المجموعة. * @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 * [أي سلسلة نصية] * @return * {@link Cluster } * @throws ClientProtocolException * يشير إلى حدوث خطأ في بروتوكول HTTP/S. * @throws ServerException * يشير إلى حدوث خطأ في واجهة برمجة تطبيقات oVirt. * @throws IOException * يشير إلى حدوث استثناء إدخال/إخراج من نوع ما. */ public Cluster add ( org . ovirt . engine . sdk . entities . Cluster cluster , String expect , String correlationId ) throws ClientProtocolException , ServerException , IOException { .... }مراجع
- ↑ "لغة وصف خدمة RESTful (RSDL)" . balisage.net .
- خدمات الويب
