Nova postagem

Pesquisar

Artigo
· Fev. 19 19min de leitura

Securing HL7 Interfaces with SSL/TLS (X.509) Certificates

What is TLS?

TLS, the successor to SSL, stands for Transport Layer Security and provides security (i.e. encryption and authentication) over a TCP/IP connection. If you have ever noticed the "s" on "https" URLs, you have recognized an HTTP connection "secured" by SSL/TLS. In the past, only login/authorization pages on the web would use TLS, but in today's hostile internet environment, best practice indicates that we should secure all connections with TLS.

Discussão (0)1
Entre ou crie uma conta para continuar
Anúncio
· Fev. 19

[懸賞] DC 検索の改善にご協力お願いします!(抽選で 1 名の方に素敵な賞品プレゼント)- USコミュニティ

開発者の皆さん、こんにちは!

前回の懸賞 が大好評でしたので、今回も開催することにいたしました!😉 今回の懸賞のテーマは 

🔎 DC 検索 🔍

検索エンジンを改善する方法についていくつかご提案がございましたらぜひお聞かせください。

検索を改善する方法についてのアイデアを共有いただいた開発者コミュニティのメンバーをランダムに選び、素敵な賞品を差し上げます!

この懸賞に参加するための要件は以下の通りです。

  • コミュニティのメンバーになる (InterSystems の従業員の参加できます!)
  • 検索の改善に関するアイデア を InterSystems Ideas Portal に登録してください。登録時、カテゴリ:Community を選択し改善したい点とその方法について可能な限り詳しく説明してください。
  • 他の人に知ってもらえるように、USコミュニティ記事のコメント欄にあなたが投稿されたアイデアのリンクとお名前をシェアしてください。

3 月中旬に Ideas Portal  へガイドラインに沿ってアイデアを投稿いただいた方全員の中から random.org を使用して 1 名を選出します!見事当選された方には、かわいいギフトが贈られる予定です。

皆さん、頑張ってください!☘


注意:

  • 重複したアイデアは受け入れられません。提出するアイデアが独自のものであることを確認してください。 
  • 当社はアイデアを管理する権利を留保します。モデレーターの決定は最終的なものとなります。
  • アイデアを提出する方法についての簡単なガイドを以下に示します。
  • 投稿するアイデアが多ければ多いほど、賞品を獲得できる可能性が高くなります 🤗
Discussão (0)1
Entre ou crie uma conta para continuar
Artigo
· Fev. 18 2min de leitura

第二十八章 T 开头的术语

第二十八章 T 开头的术语

以 T 开头的术语

表 (table)

InterSystems SQL

表是一种由表示特定实体的行和表示每个实体特定数据点的列组成的数据结构。

目标角色 (target role)

系统

在受保护的 IRIS 应用中,由应用程序授予给已经是其他角色(称为匹配角色)成员的用户的角色。如果用户拥有匹配角色,则在使用应用程序时,用户还可以被授予一个或多个额外的目标角色。

目标用户 (target user)

系统

Discussão (0)1
Entre ou crie uma conta para continuar
Artigo
· Fev. 18 34min de leitura

API REST com Swagger no InterSystems IRIS

API REST com Swagger no InterSystems IRIS

 

Olá,

O protocolo HTTP permite a obtenção de recursos, como documentos HTML. É a base de qualquer troca de dados na Web e um protocolo cliente-servidor, o que significa que as requisições são iniciadas pelo destinatário, geralmente um navegador da Web.

As API REST se beneficiam deste protocolo para trocar mensagens entre cliente e servidor. Isso torna as APIs REST rápidas, leves e flexíveis. As API REST utilizam os verbos HTTP GET, POST, PUT, DELETE e outros para indicar as ações que desejam realizar.

Quando realizamos uma chamada a uma API RESt na verdade o que ocorre é uma chamada HTTP. A API recebe esta chamada e de acordo com o verbo e o caminho solicitados a API executa a ação desejada. No caso da implementação em Iris podemos ver isso claramente na área de definição da URLMap:

XData UrlMap
{
<Routes>
        <Route Url="/cliente" Method="POST" Call="Incluir"  Cors="true"/>
        <Route Url="/cliente/:chave" Method="PUT" Call="Alterar"  Cors="true"/>
        <Route Url="/cliente/:chave" Method="DELETE" Call="Deletar"  Cors="true"/>
        <Route Url="/cliente/:chave" Method="GET" Call="Pesquisar"  Cors="true"/>
        <Route Url="/cliente" Method="GET" Call="Listar"  Cors="true"/>
    </Routes>
}

Veja que temos o caminho (Url) e o verbo (Method) definido para cada chamada (Call). Assim o código que atende a API sabe o que deve realizar.

Essa estrutura na API REST não atende somente ao roteamento das ações que chegam para a API.

Ela também é a base para a criação do arquivo de Swagger da API, conforme vemos na documentação da classe %REST.API, método GetWebRESTApplication: https://docs.intersystems.com/irislatest/csp/documatic/%25CSP.Documatic....

Vamos ver como podemos gerar essa documentação então.

Primeiro vamos publicar nossa API. Vamos utilizar a mesma API do artigo https://community.intersystems.com/post/using-rest-api-flask-and-iam-intersystems-iris-part-1-rest-api

Basta então seguir as orientações e utilizar o código que o artigo disponibiliza para termos nossa API publicada.

Uma vez publicada a API vamos incluir uma nova rota no URLMap e um novo método no nosso código:

 

        <Route Url="/openapi" Method="GET" Call="OpenAPI" Cors="true"/>

ClassMethod OpenAPI() As %Status
{
    Do ##class(%REST.Impl).%SetContentType("application/json")
    
    Set sc = ##class(%REST.API).GetWebRESTApplication("", "/rest/servico", .swagger)
    
    If $$$ISERR(sc) {
        Quit sc  // If an error occurred, exit the method
    }

        
    Write swagger.%ToJSON()

    Quit $$$OK
}

 

Inclua no código da API a nova rota e o método associado a ela. Vamos agora fazer um teste. Vamos abrir o Postman e chamar o endpoint referente a geração do Swagger, que é o /openapi:

 

E a seguir temos a definição completa do Swagger gerado pela nossa chamada:

{

    "info": {

        "title": "",

        "description": "",

        "version": "",

        "x-ISC_Namespace": "DEMO"

    },

    "basePath": "/rest/servico",

    "paths": {

        "/cliente": {

            "post": {

                "parameters": [

                    {

                        "name": "payloadBody",

                        "in": "body",

                        "description": "Request body contents",

                        "required": false,

                        "schema": {

                            "type": "string"

                        }

                    }

                ],

                "operationId": "Incluir",

                "x-ISC_ServiceMethod": "Incluir",

                "x-ISC_CORS": true,

                "responses": {

                    "default": {

                        "description": "(Unexpected Error)"

                    },

                    "200": {

                        "description": "(Expected Result)"

                    }

                }

            },

            "get": {

                "operationId": "Listar",

                "x-ISC_ServiceMethod": "Listar",

                "x-ISC_CORS": true,

                "responses": {

                    "default": {

                        "description": "(Unexpected Error)"

                    },

                    "200": {

                        "description": "(Expected Result)"

                    }

                }

            }

        },

        "/cliente/{chave}": {

            "put": {

                "parameters": [

                    {

                        "name": "chave",

                        "in": "path",

                        "required": true,

                        "type": "string"

                    },

                    {

                        "name": "payloadBody",

                        "in": "body",

                        "description": "Request body contents",

                        "required": false,

                        "schema": {

                            "type": "string"

                        }

                    }

                ],

                "operationId": "Alterar",

                "x-ISC_ServiceMethod": "Alterar",

                "x-ISC_CORS": true,

                "responses": {

                    "default": {

                        "description": "(Unexpected Error)"

                    },

                    "200": {

                        "description": "(Expected Result)"

                    }

                }

            },

            "delete": {

                "parameters": [

                    {

                        "name": "chave",

                        "in": "path",

                        "required": true,

                        "type": "string"

                    }

                ],

                "operationId": "Deletar",

                "x-ISC_ServiceMethod": "Deletar",

                "x-ISC_CORS": true,

                "responses": {

                    "default": {

                        "description": "(Unexpected Error)"

                    },

                    "200": {

                        "description": "(Expected Result)"

                    }

                }

            },

            "get": {

                "parameters": [

                    {

                        "name": "chave",

                        "in": "path",

                        "required": true,

                        "type": "string"

                    }

                ],

                "operationId": "Pesquisar",

                "x-ISC_ServiceMethod": "Pesquisar",

                "x-ISC_CORS": true,

                "responses": {

                    "default": {

                        "description": "(Unexpected Error)"

                    },

                    "200": {

                        "description": "(Expected Result)"

                    }

                }

            }

        },

        "/openapi": {

            "get": {

                "operationId": "OpenAPI",

                "x-ISC_ServiceMethod": "OpenAPI",

                "x-ISC_CORS": true,

                "responses": {

                    "default": {

                        "description": "(Unexpected Error)"

                    },

                    "200": {

                        "description": "(Expected Result)"

                    }

                }

            }

        },

        "/test": {

            "get": {

                "operationId": "Test",

                "x-ISC_ServiceMethod": "Test",

                "x-ISC_CORS": true,

                "responses": {

                    "default": {

                        "description": "(Unexpected Error)"

                    },

                    "200": {

                        "description": "(Expected Result)"

                    }

                }

            }

        }

    },

    "swagger": "2.0"

}

 

O link a seguir nos dá acesso a documentação do Iris que aponta uma ferramenta que recebe a saída da nossa chamada de API e transforma em uma interface amigável de documentação e testes do serviço: https://docs.intersystems.com/irislatest/csp/docbook/DocBook.UI.Page.cls...

Vamos acionar esta URL e informar o caminho para recuperar a definição Swagger da nossa API: https://swagger.io/tools/swagger-ui/

Vamos substituir a chamada de demo da páguma (a chamada petstore) pela nossa chamada: http://127.0.0.1/iris_iss/rest/servico/openapi e veja a tela com a documentação Swagger gerada:

No alto da chamada temos as informações básicas da nossa API:

E podemos ainda navegar pelas chamadas e visualizar informações importantes, como na chamada POST para incluir um novo cliente:

Mas, como vimos um pouco acima, a definição Swagger é na verdade um arquivo no formato JSON que fica disponível para nós na forma de um %DynamicObject (ver documentação em https://docs.intersystems.com/irislatest/csp/documatic/%25CSP.Documatic....) após a chamada ##class(%REST.API).GetWebRESTApplication que realizamos no nosso método OpenAPI. Desta forma, baseados na definição OpenAPI 2.0 podemos incluir ou remover informações do nosso Swagger. Vamos, por exemplo, enriquecer as informações básicas da API. Segundo a definição da Versão 2.0 (https://swagger.io/specification/v2/ ) podemos ter as seguintes informações disponibilizadas:

 

Vamos então completar as informações que podemos disponibilizar. Para isso vamos alterar nosso método OpenAPI, incluindo as informações básicas, protocolo aceito, autenticação e dados de acesso (host e basePath):

ClassMethod OpenAPI() As %Status
{
              Do ##class(%REST.Impl).%SetContentType("application/json")
    
    Set sc = ##class(%REST.API).GetWebRESTApplication("", "/rest/servico", .swagger)
    
    If $$$ISERR(sc) {
        Quit sc  // If an error occurred, exit the method
    }

 


              Do ##class(%REST.Impl).%SetContentType("application/json")
    
    Set sc = ##class(%REST.API).GetWebRESTApplication("", "/rest/servico", .swagger)
    
    If $$$ISERR(sc) {
        Quit sc  // If an error occurred, exit the method
    }
    
    Set info = {
        "title": "Cliente",
        "description": "API de Manipulação de Cliente",
        "version": "1.00"
    }

   Do swagger.%Set("info", info)

 

   Do swagger.%Set("host", "127.0.0.1")
   Do swagger.%Set("basePath", "/iris_iss/rest/servico")

 

   Set schemes = []
   Do schemes.%Push("http")

   Do swagger.%Set("schemes", schemes)
             
   Set security = [{"basicAuth":[]}]

   Do swagger.%Set("security", security)


   Set securityDefinitions = {}
   Do securityDefinitions.%Set("basicAuth", {})
   Do securityDefinitions.basicAuth.%Set("type", "basic")   

   Do swagger.%Set("securityDefinitions", securityDefinitions)  

 
    Write swagger.%ToJSON()

    Quit $$$OK
}


Chamando novamente a documentação Swagger na página de visualização agora temos a seguinte saída:

 

Veja que a nossa documentação está bem mais completa, com as informações sobre a API mais detalhadas, como por exemplo, o mecanismo de autenticação (Basic Auth), o protocolo aceito (HTTP) e as definições de versão, descrição e URL.

Podemos agora enriquecer a definição das chamadas, colocando a estrutura esperada nos payloads e exemplos de dados para a chamada. Para isso vamos sobrepor a informação em paths para “/cliente”:

ClassMethod OpenAPI() As %Status
{
              Do ##class(%REST.Impl).%SetContentType("application/json")
    
    Set sc = ##class(%REST.API).GetWebRESTApplication("", "/rest/servico", .swagger)
    
    If $$$ISERR(sc) {
        Quit sc  // If an error occurred, exit the method
    }


              Do ##class(%REST.Impl).%SetContentType("application/json")
    
    Set sc = ##class(%REST.API).GetWebRESTApplication("", "/rest/servico", .swagger)
    
    If $$$ISERR(sc) {
        Quit sc  // If an error occurred, exit the method
    }
    
    Set info = {
        "title": "Cliente",
        "description": "API de Manipulação de Cliente",
        "version": "1.00"
    }
    Do swagger.%Set("info", info)

 

    Do swagger.%Set("host", "127.0.0.1")
    Do swagger.%Set("basePath", "/iris_iss/rest/servico")

    Set schemes = []
    Do schemes.%Push("http")
    Do swagger.%Set("schemes", schemes)
             
    Set security = [{"basicAuth":[]}]
    Do swagger.%Set("security", security)

    Set securityDefinitions = {}
    Do securityDefinitions.%Set("basicAuth", {})
    Do securityDefinitions.basicAuth.%Set("type", "basic")
    Do swagger.%Set("securityDefinitions", securityDefinitions)
   
    Set incluirPesquisar = {
        "post": {
            "summary": "Criar um novo cliente",
            "description": "Recebe os dados de um cliente e cadastra no sistema.",
            "parameters": [
                {
                    "name": "body",
                    "in": "body",
                    "required": true,
                    "schema": {
                        "type": "object",
                        "properties": {
                            "nome": {
                                "type": "string",
                                "description": "Nome do cliente"
                            },
                            "idade": {
                                "type": "integer",
                                "description": "Idade do cliente"
                            }
                        },                              
                        "required": ["nome", "idade"],
                                           "example": {
                                                          "nome": "João Silva",
                                                          "idade": 30
                                           }
                    }
                }
            ],
            "responses": {
                          "default": {
                    "description": "Falha na chamada da API"
                },
                "200": {
                    "description": "Cliente criado com sucesso"
                },
                "406": {
                    "description": "Falha na inclusão do cliente"
                }                
            }
                            },
              "get": {
                    "summary": "Recupera todos os clientes",
                    "description": "Retorna a lista de clientes com suas informações.",
                    "responses": {
                                  "default": {
                    "description": "Falha na chamada da API"
                },
                      "200": {
                        "description": "Lista de clientes",
                        "schema": {
                          "type": "object",
                          "properties": {
                            "clientes": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "properties": {
                                  "chave": {
                                    "type": "string",
                                    "description": "Chave única do cliente"
                                  },
                                  "nome": {
                                    "type": "string",
                                    "description": "Nome do cliente"
                                  },
                                  "idade": {
                                    "type": "integer",
                                    "description": "Idade do cliente"
                                  }
                                },
                                "required": ["chave", "nome", "idade"]
                              }
                            }
                          },
                          "example": {
                            "clientes": [
                              {
                                "chave": "1",
                                "nome": "Maria",
                                "idade": 35
                              },
                              {
                                "chave": "2",
                                "nome": "Julio",
                                "idade": 57
                              },
                              {
                                "chave": "4",
                                "nome": "Julia",
                                "idade": 25
                              },
                              {
                                "chave": "5",
                                "nome": "Julia",
                                "idade": 22
                              }
                            ]
                          }
                        }
                      }
                    }      
                            }            
      }
    Do swagger.paths.%Set("/cliente", incluirPesquisar)
   
 
    Write swagger.%ToJSON()

    Quit $$$OK
}

 

 

Chamando novamente a documentação podemos visualizar agora os métodos POST para incluir um cliente e GET para recuperar um cliente:

Veja que já temos uma explicação do que é cada um dos métodos disponíveis para o POST e o GET que sobrescrevemos.

Note também não temos mais as tags "x-ISC_ServiceMethod" e "x-ISC_Namespace" que não colocamos na nossa nova definição.

Clicando para expandir o método POST por exemplo, agora temos visualmente um exemplo de chamada (Example Value):

E o formato do payload da chamada (Model):

Já na recuperação dos clientes, temos a definição do Response devolvido com exemplo:

E também com o modelo esperado como resposta:

 

Ainda, podemos testar as chamadas a API pela própria página de documentação. Veja o botão Try it out disponível na página. Clique nele, e a seguir em Execute e veja o resultado:

 

Estas possibilidades para a abordagem Code First de uma API REST nos abrem muitas possibilidades de documentação, permitindo controlar o que será divulgado, adicionando ou subtraindo as informações que julgamos convenientes no material publicado. A definição OpenAPI é muito completa e detalhada. Existem diversas informações que podemos incluir ou retirar, dependendo do que precisamos ou desejamos disponibilizar nela.

Até a próxima!

Discussão (0)1
Entre ou crie uma conta para continuar
Artigo
· Fev. 18 22min de leitura

REST API with Swagger in InterSystems IRIS

REST API with Swagger in InterSystems IRIS

Hello

The HTTP protocol allows you to obtain resources, such as HTML documents. It is the basis of any data exchange on the Web and a client-server protocol, meaning that requests are initiated by the recipient, usually a Web browser.

REST APIs take advantage of this protocol to exchange messages between client and server. This makes REST APIs fast, lightweight, and flexible. REST APIs use the HTTP verbs GET, POST, PUT, DELETE, and others to indicate the actions they want to perform.

When we make a call to a RESt API, what actually happens is an HTTP call. The API receives this call and according to the requested verb and path, the API performs the desired action. In the case of the Iris implementation we can see this clearly in the URLMap definition area:

XData UrlMap
{
<Routes>
        <Route Url="/cliente" Method="POST" Call="Incluir"  Cors="true"/>
        <Route Url="/cliente/:chave" Method="PUT" Call="Alterar"  Cors="true"/>
        <Route Url="/cliente/:chave" Method="DELETE" Call="Deletar"  Cors="true"/>
        <Route Url="/cliente/:chave" Method="GET" Call="Pesquisar"  Cors="true"/>
        <Route Url="/cliente" Method="GET" Call="Listar"  Cors="true"/>
        <Route Url="/openapi" Method="GET" Call="OpenAPI" Cors="true"/>
        <Route Url="/test" Method="GET" Call="Test" Cors="true"/>
    </Routes>
}

Notice that we have the path (Url) and the verb (Method) defined for each call (Call). Thus, the code that meets the API knows what it should do.

This structure in the REST API does not only serve the routing of actions that arrive at the API.

It is also the basis for creating the API Swagger file, as seen in the %REST.API class documentation, GetWebRESTApplication method: https://docs.intersystems.com/irislatest/csp/documatic/%25CSP.Documatic....

Let's see how we can generate this documentation then.

First let's publish our API. Let's use the same API as in article https://community.intersystems.com/post/using-rest-api-flask-and-iam-intersystems-iris-part-1-rest-api

Just follow the guidelines and use the code that the article provides to have our API published.

Once the API is published we will include a new route in URLMap and a new method in our code:

<Route Url="/openapi" Method="GET" Call="OpenAPI" Cors="true"/>

ClassMethod OpenAPI() As %Status
{
              Do ##class(%REST.Impl).%SetContentType("application/json")
    
    Set sc = ##class(%REST.API).GetWebRESTApplication("", "/rest/servico", .swagger)
    
    If $$$ISERR(sc) {
        Quit sc  // If an error occurred, exit the method
    }
   
    Write swagger.%ToJSON()

    Quit $$$OK
}

Include the new route and the method associated with it in your API code. Let's now do a test. Let's open Postman and call the endpoint for generating Swagger, which is /openapi:

 

And below we have the complete definition of the Swagger generated by our call:

{

"info": {

"title": "",

"description": "",

"version": "",

"x-ISC_Namespace": "DEMO"

},

"basePath": "/rest/servico",

"paths": {

"/customer": {

"post": {

"parameters": [

{

"name": "payloadBody",

"in": "body",

"description": "Request body contents",

 "required": false,

"schema": {

"type": "string"

}

}

],

"operationId": "Include",

"x-ISC_ServiceMethod": "Include",

 "x-ISC_CORS": true,

"responses": {

"default": {

"description": "(Unexpected Error)"

},

"200": {

"description": "(Expected Result)"

}

}

},

"get": {

"operationId": "List",

"x-ISC_ServiceMethod": "List",

 "x-ISC_CORS": true,

"responses": {

"default": {

"description": "(Unexpected Error)"

},

"200": {

"description": "(Expected Result)"

}

}

}

},

"/customer/{key}": {

"put": {

"parameters": [

{

"name": "key",

"in": "path",

 "required": true,

"type": "string"

},

{

"name": "payloadBody",

"in": "body",

"description": "Request body contents",

 "required": false,

"schema": {

"type": "string"

}

}

],

"operationId": "Change",

"x-ISC_ServiceMethod": "Change",

 "x-ISC_CORS": true,

"responses": {

"default": {

"description": "(Unexpected Error)"

},

"200": {

"description": "(Expected Result)"

}

}

},

"delete": {

"parameters": [

{

"name": "key",

"in": "path",

 "required": true,

"type": "string"

}

],

"operationId": "Delete",

"x-ISC_ServiceMethod": "Delete",

 "x-ISC_CORS": true,

"responses": {

"default": {

"description": "(Unexpected Error)"

},

"200": {

"description": "(Expected Result)"

}

}

},

"get": {

"parameters": [

{

"name": "key",

"in": "path",

 "required": true,

"type": "string"

}

],

"operationId": "Search",

"x-ISC_ServiceMethod": "Search",

 "x-ISC_CORS": true,

"responses": {

"default": {

"description": "(Unexpected Error)"

},

"200": {

"description": "(Expected Result)"

}

}

}

},

"/openapi": {

"get": {

"operationId": "OpenAPI",

"x-ISC_ServiceMethod": "OpenAPI",

 "x-ISC_CORS": true,

"responses": {

"default": {

"description": "(Unexpected Error)"

},

"200": {

"description": "(Expected Result)"

}

}

}

},

"/test": {

"get": {

"operationId": "Test",

"x-ISC_ServiceMethod": "Test",

 "x-ISC_CORS": true,

"responses": {

"default": {

"description": "(Unexpected Error)"

},

"200": {

"description": "(Expected Result)"

}

}

}

}

},

"Swagger": "2.0"

}

 

The following link gives us access to Iris's documentation that points to a tool that receives the output of our API call and transforms it into a user-friendly interface for documentation and testing of the service: https://docs.intersystems.com/irislatest/csp/docbook/DocBook.UI.Page.cls...

Let's fire this URL and provide the path to retrieve the Swagger definition from our API: https://swagger.io/tools/swagger-ui/

Let's replace the demo call on the page (the petstore call) with our call: http://127.0.0.1/iris_iss/rest/servico/openapi and see the screen with the generated Swagger documentation:

At the top of the call we have the basic information of our API:

And we can also navigate through the calls and view important information, such as in the POST call to include a new customer:

But, as we saw a little above, the Swagger definition is actually a file in JSON  format that is available to us in the form of a %DynamicObject (see documentation in https://docs.intersystems.com/irislatest/csp/documatic/%25CSP.Documatic....) after the ##class(%REST.API).GetWebRESTApplication() that we perform in our OpenAPI method. In this way, based on the OpenAPI 2.0 definition we can include or remove information from our Swagger. Let's, for example, enrich the basic information of the API. According to the definition of Version 2.0 (https://swagger.io/specification/v2/ ) we may have the following information made available:

 

Let's then complete the information that we can make available. To do this, we'll change our OpenAPI method, including the basic information, accepted protocol, authentication, and access data (host and basePath):

ClassMethod OpenAPI() As %Status
{
     Do ##class(%REST.Impl).%SetContentType("application/json")
    
    Set sc = ##class(%REST.API).GetWebRESTApplication("", "/rest/servico", .swagger)
    
    If $$$ISERR(sc) {
        Quit sc  // If an error occurred, exit the method
    }
    
    Set info = {
        "title": "Cliente",
        "description": "API de Manipulação de Cliente",
        "version": "1.00"
    }
    Do swagger.%Set("info", info)
    
    Do swagger.%Set("host", "127.0.0.1")
    Do swagger.%Set("basePath", "/iris_iss/rest/servico")

    Set schemes = []
    Do schemes.%Push("http")
    Do swagger.%Set("schemes", schemes)
             
    Set security = [{"basicAuth":[]}]
    Do swagger.%Set("security", security)

    Set securityDefinitions = {}
    Do securityDefinitions.%Set("basicAuth", {})
    Do securityDefinitions.basicAuth.%Set("type", "basic")
    Do swagger.%Set("securityDefinitions", securityDefinitions)
   
    Write swagger.%ToJSON()

    Quit $$$OK
}


Calling the Swagger documentation again on the preview page now we have the following output:

 

See that our documentation is much more complete, with more detailed information about the API, such as the authentication mechanism (Basic Auth), the accepted protocol (HTTP) and the version, description and URL definitions.

We can now enrich the definition of the calls by putting the expected structure in the payloads and data examples for the call. To do this, let's overlay the information in paths for "/client":

ClassMethod OpenAPI() As %Status
{
    Do ##class(%REST.Impl).%SetContentType("application/json")
    
    Set sc = ##class(%REST.API).GetWebRESTApplication("", "/rest/servico", .swagger)
    
    If $$$ISERR(sc) {
        Quit sc  // If an error occurred, exit the method
    }
    
    Set info = {
        "title": "Cliente",
        "description": "API de Manipulação de Cliente",
        "version": "1.00"
    }
    Do swagger.%Set("info", info)
    
    Do swagger.%Set("host", "127.0.0.1")
    Do swagger.%Set("basePath", "/iris_iss/rest/servico")

    Set schemes = []
    Do schemes.%Push("http")
    Do swagger.%Set("schemes", schemes)
             
    Set security = [{"basicAuth":[]}]
    Do swagger.%Set("security", security)

    Set securityDefinitions = {}
    Do securityDefinitions.%Set("basicAuth", {})
    Do securityDefinitions.basicAuth.%Set("type", "basic")
    Do swagger.%Set("securityDefinitions", securityDefinitions)
   
    Set incluirPesquisar = {
        "post": {
            "summary": "Criar um novo cliente",
            "description": "Recebe os dados de um cliente e cadastra no sistema.",
            "parameters": [
                {
                    "name": "body",
                    "in": "body",
                    "required": true,
                    "schema": {
                        "type": "object",
                        "properties": {
                            "nome": {
                                "type": "string",
                                "description": "Nome do cliente"
                            },
                            "idade": {
                                "type": "integer",
                                "description": "Idade do cliente"
                            }
                        },                              
                        "required": ["nome", "idade"],
                                           "example": {
                                                          "nome": "João Silva",
                                                          "idade": 30
                                           }
                    }
                }
            ],
            "responses": {
                          "default": {
                    "description": "Falha na chamada da API"
                },
                "200": {
                    "description": "Cliente criado com sucesso"
                },
                "406": {
                    "description": "Falha na inclusão do cliente"
                }                
            }
                            },
              "get": {
                    "summary": "Recupera todos os clientes",
                    "description": "Retorna a lista de clientes com suas informações.",
                    "responses": {
                                  "default": {
                    "description": "Falha na chamada da API"
                },
                      "200": {
                        "description": "Lista de clientes",
                        "schema": {
                          "type": "object",
                          "properties": {
                            "clientes": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "properties": {
                                  "chave": {
                                    "type": "string",
                                    "description": "Chave única do cliente"
                                  },
                                  "nome": {
                                    "type": "string",
                                    "description": "Nome do cliente"
                                  },
                                  "idade": {
                                    "type": "integer",
                                    "description": "Idade do cliente"
                                  }
                                },
                                "required": ["chave", "nome", "idade"]
                              }
                            }
                          },
                          "example": {
                            "clientes": [
                              {
                                "chave": "1",
                                "nome": "Maria",
                                "idade": 35
                              },
                              {
                                "chave": "2",
                                "nome": "Julio",
                                "idade": 57
                              },
                              {
                                "chave": "4",
                                "nome": "Julia",
                                "idade": 25
                              },
                              {
                                "chave": "5",
                                "nome": "Julia",
                                "idade": 22
                              }
                            ]
                          }
                        }
                      }
                    }      
              }            
      }
    Do swagger.paths.%Set("/cliente", incluirPesquisar)
   
    Write swagger.%ToJSON()

    Quit $$$OK
}

Calling the documentation page again we can now see the POST methods  to include a client and GET to retrieve a list:

See that we already have an explanation of what is each of the methods available for POST and GET that we have overwritten.

Note we also no longer have the "x-ISC_ServiceMethod" and "x-ISC_Namespace" tags that we didn't put in our new definition.

Clicking to expand the POST method for example, we now visually have an example call (Example Value):

And the format of the call payload (Model):

In customer recovery, we have the definition of the returned Response with example:

And also with the expected model as an answer:

 

Also, we can test API calls from the documentation page itself. See the Try it out” button  available on the page. Click on it, then on Execute and see the result:

 

These possibilities for the Code-first approach  of a REST API open up many possibilities for documentation, allowing us to control what will be disseminated, adding or subtracting the information we deem convenient in the published material.

The OpenAPI definition is very complete and detailed. There is a variety of information that we can include or take away, depending on what we need or want to make available in it.

See you next time!

Discussão (0)1
Entre ou crie uma conta para continuar