本文介绍 IRIS®
中的 REST
和 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 使用标签标识数据,但标签没有在正式的模式定义中指定,也没有明确的数据类型。
REST 服务简介
在 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
,但可以使用其他名称。
支持规范优先范式。可以从规范生成初始代码,并且当规范发生变化时(例如,通过获取新的端点),可以重新生成该代码。后面的部分提供了更多细节,但现在,请注意,永远不应该编辑调度类,但可以修改其他类。此外,当重新编译规范类时,调度类会自动重新生成并更新实现类(保留编辑)。
手动编码 REST 服务
在 2019.2 之前的版本中,IRIS
不支持规范优先范式。一个 REST
服务形式上只包含一个调度类和一个 Web
应用程序。引用这种方式将 REST 服务定义为手动编码的 REST
服务。区别在于较新的 REST
服务定义的 REST
服务包含规范类,而手动编码的 REST
服务不包含。本书的“手动创建 REST
服务”附录描述了如何使用手动编码范例创建 REST
服务。同样,一些 API 管理实用程序使您能够使用手动编码的 REST
服务。
API 管理工具简介
为了帮助更轻松地创建 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 服务概述
创建 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 服务类
本节详细介绍了规范、调度和实现类。
Specification Class
规范类旨在定义 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
块中的规范来修改此类。还可以根据需要添加类参数、属性和方法。每当编译规范类时,编译器都会重新生成调度类并更新实现类。
Dispatch Class
调用 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 映射中列出的方法的定义。这是一个例子:
代码语言:javascript复制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
的其他方法。
重要提示:因为调度类是一个生成的类,你永远不应该编辑它。 提供了覆盖部分调度类而不对其进行编辑的机制。
Implementation Class
实现类旨在保存 REST
服务的实际内部实现。可以(并且应该)编辑此类。它最初类似于以下示例:
/// A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification<br/>
/// Business logic class defined by RESTSpec in petstore.spec<br/>
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<br/>
/// The method arguments hold values for:<br/>
/// tags, tags to filter by<br/>
/// limit, maximum number of results to return<br/>
ClassMethod findPets(tags As %ListOfDataTypes(ELEMENTTYPE="%String"), limit As %Integer) As %Stream.Object
{
//(Place business logic here)
//Do ..%SetStatusCode(<HTTP_status_code>)
//Do ..%SetHeader(<name>,<value>)
//Quit (Place response here) ; response may be a string, stream or dynamic object
}
...
实现类的其余部分包含与此类似的附加存根方法。在每种情况下,这些存根方法都具有遵循 REST
服务规范定义的契约的签名。请注意,对于 options
方法, 不会生成存根方法供实现。相反,%CSP.REST
类会自动执行所有选项处理。
为 API 管理功能启用日志记录
要启用 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
命名空间中。