本文介绍 IRIS®
中的 REST
和 REST
服务。
REST
命名自“Representational State Transfer”
,具有以下属性:
REST
是一种架构风格,而不是一种格式。尽管 REST
经常使用 HTTP
来传输消息并使用 JSON
来传递数据,但也可以将数据作为 XML
或纯文本传递。 REST
利用现有的 Web
标准,例如 HTTP
、URL
、XML
和 JSON
。REST
是面向资源的。通常,资源由 URL
标识并使用基于 HTTP
方法的操作,例如 GET
、POST
、PUT
和 DELETE
。REST
通常有少量开销。虽然它可以使用 XML
来描述数据,但它更常用的是 JSON
,它是一种轻量级的数据包装器。 JSON 使用标签标识数据,但标签没有在正式的模式定义中指定,也没有明确的数据类型。在 IRIS 2019.2
及更高版本中定义 REST
接口有两种方法:
OpenAPI 2.0
规范,然后使用 API
管理工具生成 REST
接口的代码。REST
接口。使用规范优先的定义,REST
服务正式由以下组件组成:
%REST.Spec
的子类)。此类包含 REST
服务的 OpenAPI 2.0
规范。 支持可以在规范中使用的几个扩展属性。%CSP.REST
的子类)。该类负责接收HTTP
请求并调用实现类中合适的方法。%REST.Impl
的子类)。此类定义实现 REST
调用的方法。API
管理工具生成实现类的存根版本,然后可以扩展它以包含必要的应用程序逻辑。 (逻辑当然可以调用此类之外的代码。)
%REST.Impl
类提供了可以调用的方法,以便设置 HTTP
标头、报告错误等。
Web
应用程序,通过 Web Gateway
提供对 REST
服务的访问。 Web
应用程序配置为启用 REST
访问并使用特定的调度类。 Web
应用程序还控制对 REST
服务的访问。
对这些组件遵循严格的命名约定。给定一个应用程序名称(appname
),规范、调度和实现类的名称分别是 appname.spec
、appname.disp
和 appname.impl
。 Web 应用程序默认命名为 /csp/appname
,但可以使用其他名称。
支持规范优先范式。可以从规范生成初始代码,并且当规范发生变化时(例如,通过获取新的端点),可以重新生成该代码。后面的部分提供了更多细节,但现在,请注意,永远不应该编辑调度类,但可以修改其他类。此外,当重新编译规范类时,调度类会自动重新生成并更新实现类(保留编辑)。
在 2019.2 之前的版本中,IRIS
不支持规范优先范式。一个 REST
服务形式上只包含一个调度类和一个 Web
应用程序。引用这种方式将 REST 服务定义为手动编码的 REST
服务。区别在于较新的 REST
服务定义的 REST
服务包含规范类,而手动编码的 REST
服务不包含。本书的“手动创建 REST
服务”附录描述了如何使用手动编码范例创建 REST
服务。同样,一些 API 管理实用程序使您能够使用手动编码的 REST
服务。
为了帮助更轻松地创建 REST
服务, 提供了以下 API 管理工具:
/api/mgmnt
的REST
服务,可以使用它来发现服务器上的 REST
服务,为这些 REST
服务生成 OpenAPI 2.0
规范,以及在服务器上创建、更新或删除 REST
服务。^%REST
例程,它提供了一个简单的命令行界面,可以使用它来列出、创建和删除 REST 服务。%REST.API
类,可以使用它来发现服务器上的 REST
服务,为这些 REST 服务生成 OpenAPI 2.0
规范,以及在服务器上创建、更新或删除 REST 服务。可以为这些工具设置日志记录,如本章后面所述。
有用的第三方工具包括 REST
测试工具,例如 PostMan
(https://www.getpostman.com/) 和 Swagger
编辑器 (https://swagger.io/tools/swagger-editor/download/)。
创建 REST
服务的推荐方式大致如下:
OpenAPI 2.0
规范。API
管理工具生成 REST
服务类和关联的 Web
应用程序。请参阅以下章节:/api/mgmnt/
服务创建 REST
服务”^%REST
例程创建 REST
服务”%REST.API
类创建 REST
服务”CORS
或使用 Web
会话,请执行此操作。REST
服务”一章。OpenAPI 2.0
规范,生成文档,如“发现和记录 REST API
”一章中所述。对于第 2
步,另一种选择是手动创建规范类(将规范粘贴到其中),然后编译该类;此过程生成调度和存根实现类。也就是说,使用 /api/mgmnt
服务或 ^%REST
例程都不是绝对必要的。本书没有进一步讨论这种技术。
本节详细介绍了规范、调度和实现类。
规范类旨在定义 REST
服务要遵循的契约。此类扩展 %REST.Spec
并包含一个 XData
块,该块包含 REST
服务的 OpenAPI 2.0
规范。下面显示了一个部分示例:
Class YX.SPEC Extends %REST.Spec
{
XData OpenAPI [ MimeType = application/json ]
{
{
"swagger":"2.0",
"info":{
"version":"1.0.0",
"title":"Swagger Petstore",
"description":"A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification",
"termsOfService":"http://swagger.io/terms/",
"contact":{
"name":"Swagger API Team"
},
"license":{
"name":"MIT"
}
}
}
}
}
可以通过替换或编辑 XData
块中的规范来修改此类。还可以根据需要添加类参数、属性和方法。每当编译规范类时,编译器都会重新生成调度类并更新实现类。
调用 REST
服务时直接调用调度类。下面显示了一个部分示例:
Class YX.DISP Extends %CSP.REST [ GeneratedBy = YX.SPEC.cls, ProcedureBlock ]
{
/// The class containing the RESTSpec which generated this class
Parameter SpecificationClass = "petstore.spec";
/// Default the Content-Type for this application.
Parameter CONTENTTYPE = "application/json";
/// By default convert the input stream to Unicode
Parameter CONVERTINPUTSTREAM = 1;
/// The default response charset is utf-8
Parameter CHARSET = "utf-8";
XData UrlMap [ XMLNamespace = "http://www.intersystems.com/urlmap" ]
{
<Routes>
<Route Url="/pets" Method="get" Call="findPets" />
<Route Url="/pets" Method="post" Call="addPet" />
<Route Url="/pets/:id" Method="get" Call="findPetById" />
<Route Url="/pets/:id" Method="delete" Call="deletePet" />
</Routes>
}
}
请注意,SpecificationClass
参数指示相关规范类的名称。 URLMap XData
块(URL
映射)定义此 REST
服务中的调用。
在这些项目之后,该类包含 URL 映射中列出的方法的定义。这是一个例子:
ClassMethod deletePet(pid As %String) As %Status
{
Try {
If '##class(%REST.Impl).%CheckAccepts("application/json") Do ##class(%REST.Impl).%ReportRESTError(..#HTTP406NOTACCEPTABLE,$$$ERROR($$$RESTBadAccepts)) Quit
If ($number(pid,"I")="") Do ##class(%REST.Impl).%ReportRESTError(..#HTTP400BADREQUEST,$$$ERROR($$$RESTInvalid,"id",id)) Quit
Set response=##class(petstore.impl).deletePet(pid)
Do ##class(petstore.impl).%WriteResponse(response)
} Catch (ex) {
Do ##class(%REST.Impl).%ReportRESTError(..#HTTP500INTERNALSERVERERROR,ex.AsStatus())
}
Quit $$$OK
}
请注意以下几点:
petstore.impl
)。它从该方法获取响应并调用 %WriteResponse()
将响应写回调用者。 %WriteResponse()
方法是一种继承方法,存在于所有实现类中,这些实现类都是 %REST.Impl
的子类。%REST.Impl
的其他方法。重要提示:因为调度类是一个生成的类,你永远不应该编辑它。 提供了覆盖部分调度类而不对其进行编辑的机制。
实现类旨在保存 REST
服务的实际内部实现。可以(并且应该)编辑此类。它最初类似于以下示例:
/// A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification
/// Business logic class defined by RESTSpec in petstore.spec
Class petstore.impl Extends %REST.Impl [ ProcedureBlock ]
{
/// If ExposeServerExceptions is true, then details of internal errors will be exposed.
Parameter ExposeServerExceptions = 0;
/// Returns all pets from the system that the user has access to
/// The method arguments hold values for:
/// tags, tags to filter by
/// limit, maximum number of results to return
ClassMethod findPets(tags As %ListOfDataTypes(ELEMENTTYPE="%String"), limit As %Integer) As %Stream.Object
{
//(Place business logic here)
//Do ..%SetStatusCode()
//Do ..%SetHeader(,)
//Quit (Place response here) ; response may be a string, stream or dynamic object
}
...
实现类的其余部分包含与此类似的附加存根方法。在每种情况下,这些存根方法都具有遵循 REST
服务规范定义的契约的签名。请注意,对于 options
方法, 不会生成存根方法供实现。相反,%CSP.REST
类会自动执行所有选项处理。
要启用 API
管理功能的日志记录,请在终端中输入以下内容:
set $namespace="%SYS"
kill ^ISCLOG
set ^%ISCLOG=5
set ^%ISCLOG("Category","apimgmnt")=5
然后系统将条目添加到 ^ISCLOG
全局,以用于对 API
管理端点的任何调用。
要将日志写入文件(为了便于阅读),请输入以下内容(仍在 %SYS
命名空间内):
do ##class(%OAuth2.Utils).DisplayLog("filename")
其中 filename
是要创建的文件的名称。该目录必须已经存在。如果文件已存在,则将其覆盖。
要停止记录,请输入以下内容(仍在 %SYS
命名空间中):
set ^%ISCLOG=0
set ^%ISCLOG("Category","apimgmnt")=0
启用 HTTP
请求的日志记录后,日志条目将存储在 ^ISCLOG
全局中,该全局位于 %SYS
命名空间中。
要使用管理门户查看日志,请导航到 System Explorer > Globals 并查看 ISCLOG
全局(不是 %ISCLOG
)。确保位于 %SYS
命名空间中。