_spec for swagger-ui from spec class
Surely you wanted to use the OpenAPI Specification (OAS) JSON you used for your spec class on the iris-web-swagger-ui iris package. The generated OAS from the ##class(%REST.API).GetWebRESTApplication(...) method is very crude, with no description on the parameters or the expected response structure.
So after creating your REST application from an OAS you should have:
- A generated application.disp.cls class
- An application.spec.cls class (we'll add a path to the OpenAPI spec that's residing in the "XData OpenAPI" property)
- An application.impl.cls class (we'll just implement the GetSpec method)
If you installed the iris-web-swagger-ui package (https://openexchange.intersystems.com/package/iris-web-swagger-ui) you need an endpoint that returns the OAS .
My approach is to add a path to the OAS in the spec class and implement it using the property "OpenAPI" from said spec class. This will get you, for instance, every structure in the original OAS available for testing!
In the sample class for the iris-web-swagger-ui package (Sample.PersonREST), there's an implementation for the SwaggerSpec method that updates some properties to reflect what's configured in the IRIS Web Application. If you're following this post, I recommend updating directly the OAS in the spec class to provide that information in order to centralize your API's documentation (or you can always update it in the GetSpec method I provide as sample).
Following the example in the Sample.PersonREST class, the path will be "/_spec". Although there is a value for the "basePath" tag, it will be overridden with the IRIS Web Application name:
Class application.spec Extends %REST.Spec [ProcedureBlock]
{
XData OpenAPI [ MimeType = application/json ]
{
{
...
"basePath":"/api/myapi",
...
"paths":{
"/_spec": {
"get":{
"operationId":"GetSpec",
"description":"This OpenAPI Spec",
"produces":[
"application/json"
],
"responses":{
"200":{
"description":"Successful operation"
}
}
}
},
...Next is pasting this simple code in the implementation class. Specifically after compiling the spec class, the impl class has a new method (GetSpec) that is expected to return a dynamic object (the leading comment comes from the OAS in the spec class and the "description" tag for the path's "get"). You must replace the "application.spec" with your own application class reference.
/// This OpenAPI Spec
ClassMethod GetSpec() As %DynamicObject
{
Set spec = {}.%FromJSON(##class(%Dictionary.CompiledXData).%OpenId("application.spec||OpenAPI").Data.Read())
Set spec.basePath = %request.Application
Return spec
}That's it!
Now go to your iris-web-swagger-ui (in my case http://localhost:52773/swagger-ui/index.html) and test away exploring at "http://localhost:52773/api/myapi/_spec" in swagger-ui's navigation input!
Note: I defined a Web Application named /api/myapi with "application.disp" as its "Dispatch class".
Comments
Great article! Thank you @Pablo Frigolett !
Also, if you develop in Docker there is an issue with server name, and my version of the same GetSpec method is:
ClassMethod GetSpec() As%DynamicObject
{
Set spec = {}.%FromJSON(##class(%Dictionary.CompiledXData).%OpenId("dc.Sample.v2rest.spec||OpenAPI").Data)
Set url = $Select(%request.Secure:"https",1:"http") _ "://"_$Get(%request.CgiEnvs("SERVER_NAME")) _ ":" _ $Get(%request.CgiEnvs("SERVER_PORT")) _ %request.ApplicationSet spec.servers = [{"url" : (url)}]
Quit spec
}Thanks to @Lorenzo Scalese !
also, thanks to @Semion Makarov swagger ui app is updated to support Swagger 3.1 version. and functionality is improved greatly! 
Also, often we want to switch to our own endpoint automatically instead of default one.
These 3 lines in Dockerfile will do the thing.
RUN old=http://localhost:52773/crud/_spec && \
new=http://localhost:52773/your/api/_spec && \
sed -i "s|$old|$new|g" /usr/irissys/csp/swagger-ui/swagger-initializer.js