Olá Comunidade,
Veja como você pode desenvolver em Python e se conectar na plataforma de dados InterSystems IRIS® com PyODBC e API Nativa:
Interface de Programação de Aplicações (API) é um conjunto de definições de sub-rotina, protocolos e ferramentas para a construção de aplicações de software. Em termos gerais, é um conjunto de métodos de comunicação claramente definidos entre vários componentes de software.
Olá Comunidade,
Veja como você pode desenvolver em Python e se conectar na plataforma de dados InterSystems IRIS® com PyODBC e API Nativa:
Recentemente eu precisei gerar uma especificação Swagger a partir de classes persistentes e seriais, então estou publicando meu código (ainda incompleto - você ainda precisa resolver detalhes específicos do aplicativo mas é um começo). Ele está disponível aqui.
Digamos que você tem estas classes:
Olá Comunidade
Foi publicado um novo vídeo em nosso canal InterSystems Developers no YouTube:
O contêiner do IAM, incluindo todos os artefatos necessários para realizar a atualização a partir de versões anteriores do IAM podem ser baixados do site de Distribuição de Software do WRC na área de Componentes.
O número de registro deste lançamento é IAM 1.5.0.9-4.
O Gerenciador de APIs InterSystems 1.5 facilita o gerenciamento do tráfego de suas APIs, a integração de seu ambiente e usuários com suas APIs. Ele possui várias novas funcionalidades incluindo:
A pandemia que atacou o mundo em 2020 fez com que todos passassem a acompanhar as notícias e números que envolvem a COVID-19.
Então, por que não usar essa oportunidade e criar algo simple e agradável de se acompanhar os números das vacinações mundo afora?
Para participar deste desafio, utilizo os dados providos pelo Our World in Data - Research and data to make progress against the world’s largest problems.
Eles tem um repositório dedicado no Github com dados sobre a COVID-19, e utilizo os dados de vacinação para me ajudar com o meu rastreador.
Se você não conhece os caras, dá uma conferida, vai valer seu tempo. Github repository
A aplicação iris-vaccine-tracker tem 3 páginas diferentes:
O dashboard principal mostra uma visão geral sobre a situação de vacinação ao redor do mundo.
O primeiro widget oferece as seguintes informações :
O segundo widget nos dá uma visão em linha do tempo com o top 10 de países com os números mais significantes da vacinação.
O terceiro widget exibe um gráfico de barras para os números do top 10 de países, mostrando o número total de vacinações até agora.
E o último widget, traz a distribuição de vacinas, que estão sendo utilizadas e seu percentual de utilização dentre os países.
![]()
O data table exibe as informações detalhadas que o dashboard principal condensa para a exibição.
![]()
O heat map é uma visão diferente das informações já apresentadas no dashboard principal e no data table—Mas agora, estamos utilizando os detalhes providos pela informação que a tabela persistente Country nos oferece. A biblioteca amCharts usa o ISO Code Alpha2, nome do país e valor para criar esse mapa super show =D.
![]()
http://iris-vaccine-tracker.eastus.cloudapp.azure.com:52773/csp/irisapp/index.html
Curtiu o aplicativo? Acha que vale seu voto? Então vote em iris-vaccine-tracker!
Nesta série de artigos de três partes, é mostrado como você pode usar o IAM para simplesmente adicionar segurança, de acordo com os padrões do OAuth 2.0, a um serviço não autenticado anteriormente implantado no IRIS.
Na primeira parte, foram fornecidos alguns conhecimentos sobre o OAuth 2.0, juntamente com algumas definições e configurações iniciais do IRIS e IAM, para facilitar a compreensão de todo o processo de proteção dos seus serviços.
Esta parte, agora, discutirá e mostrará em detalhes as etapas necessárias para configurar o IAM para validar o token de acesso presente na solicitação de entrada e encaminhar a solicitação para o back-end se a validação for bem-sucedida.
A última parte desta série discutirá e demonstrará as configurações necessárias para o IAM gerar um token de acesso (atuando como um servidor de autorização) e validá-lo, junto com algumas considerações finais importantes.
Se você quiser testar o IAM, entre em contato com seu representante de vendas InterSystems.
Neste cenário, será usado um servidor de autorização externo que gera um token de acesso em formato JWT (JSON Web Token). Este JWT é assinado usando o algoritmo RS256 junto com uma chave privada. Para verificar a assinatura do JWT, a outra parte (neste caso, o IAM) precisa ter a chave pública, fornecida pelo servidor de autorização.
Este JWT gerado pelo servidor de autorização externo também inclui, em seu corpo, uma declaração chamada “exp” contendo o carimbo de data/hora (timestamp) de quando esse token expirará, e outra declaração chamada “iss” contendo o endereço do servidor de autorização.
Portanto, o IAM precisa verificar a assinatura do JWT com a chave pública do servidor de autorização e o carimbo de data/hora de expiração contido na declaração "exp" dentro do JWT antes de encaminhar a solicitação ao IRIS.
Para configurar isso no IAM, vamos começar adicionando um plugin chamado “JWT” ao nosso “SampleIRISService” no IAM. Para isso, acesse a página Services do IAM e copie o id do “SampleIRISService”, que usaremos posteriormente.
.png)
Depois disso, vá em Plugins, clique no botão “New Plugin”, localize o plugin “JWT” e clique em Enable.
.png)
Na página seguinte, cole o id do “SampleIRISService” no campo “service_id” e selecione a caixa “exp” no parâmetro “config.claims_to_verify”.
.png)
Observe que o valor do parâmetro “config.key_claim_name” é “iss”. Vamos usar isso mais tarde.
Em seguida, clique no botão “Create”.
Feito isso, vá até a seção “Consumers” no menu à esquerda e clique em nosso “ClientApp” criado anteriormente. Acesse a aba “Credentials” e clique no botão “New JWT Credential”.
.png)
Na página seguinte, selecione o algoritmo usado para assinar o JWT (neste caso RS256) e cole a chave pública no campo “rsa_public_key” (esta é a chave pública fornecida a você pelo servidor de autorização em formato PEM).
No campo “key”, você precisa inserir o conteúdo da declaração JWT que você inseriu no campo “config.key_claim_name” ao adicionar o plugin JWT. Portanto, neste caso, preciso inserir o conteúdo da declaração iss do meu JWT, que, no meu caso, é o endereço do servidor de autorização.

Em seguida, clique no botão “Create”.
Agora, com o plugin JWT adicionado, não é mais possível enviar a solicitação sem uma autenticação. Como você pode ver abaixo, em uma simples solicitação GET, sem autenticação, para a URL
retorna uma mensagem não autorizada juntamente com o código de status “401 Não autorizado”.

Para obter os resultados do IRIS, precisamos adicionar o JWT à solicitação.
Portanto, primeiro precisamos solicitar o JWT ao servidor de autorização. O servidor de autorização personalizado que estamos usando aqui retorna um JWT se uma solicitação POST for feita junto com alguns pares de valores-chave no corpo, incluindo informações de usuário e cliente, para a seguinte URL:
https://authorizationserver:5001/auth
Isto é como se parece essa solicitação e a sua resposta:

Em seguida, você pode adicionar o JWT obtido na resposta abaixo no cabeçalho de autorização como um Bearer Token e enviar uma solicitação GET para a mesma URL usada anteriormente:

Ou você também pode adicioná-lo como um parâmetro de querystring, com a chave de querystring sendo o valor especificado no campo “config.uri_param_names” ao adicionar o plugin JWT que, neste caso, é “jwt”:

Finalmente, existe também a opção de incluir JWT na solicitação como um cookie, se algum nome for inserido no campo “config.cookie_names”.
Continue lendo até a terceira e última parte desta série para entender as configurações necessárias para o IAM gerar um token de acesso e validá-lo, junto com algumas considerações finais importantes.
Neste artigo eu gostaria de falar sobre a abordagem de especificação primeiro (spec-first) para o desenvolvimento de APIs REST.
Embora o desenvolvimento de API REST com código primeiro (code-first) tradicional seja assim:
A especificação primeiro (spec-first) segue os mesmos passo, mas ao contrário. Começamos com uma especificação, também usando-a como documentação, geramos uma aplicação REST padrão a partir dela e, finalmente, escrevemos alguma lógica de negócios.
Isso é vantajoso porque:
O primeiro passo é, sem surpresa, escrever a especificação. O InterSystems IRIS oferece suporte à Especificação Open API (OAS):
A Especificação OpenAPI (anteriormente Especificação Swagger) é um formato de descrição de API para APIs REST. Um arquivo OpenAPI permite que você descreva toda a sua API, incluindo:
- Endpoints disponíveis (
/users) e operações em cada endpoint (GET /users,POST /users)- Parâmetros de entrada e saída para cada operação
- Métodos de autenticação
- Informações de contato, licença, termos de uso e outras informações.
As especificações das APIs podem ser escritas em YAML ou JSON. O formato é fácil de aprender e legível tanto para humanos como para máquinas. A Especificação OpenAPI completa pode ser encontrada no GitHub: Especificação OpenAPI 3.0
- da documentaçãoSwagger.
Usaremos Swagger para escrever nossa API. Existem várias maneiras de usar o Swagger:
docker run -d -p 8080:8080 swaggerapi/swagger-editorApós instalar/executar o Swagger, você deverá ver esta janela em um navegador web:

No lado esquerdo, você edita a especificação da API e, à direita, vê imediatamente a documentação/ferramenta de teste da API renderizada.
Vamos carregar nossa primeira especificação de API nele (em YAML). É uma API simples com uma solicitação GET - retornando um número aleatório em um intervalo especificado.
swagger: "2.0"
info:
description: "Math"
version: "1.0.0"
title: "Math REST API"
host: "localhost:52773"
basePath: "/math"
schemes:
- http
paths:
/random/{min}/{max}:
get:
x-ISC_CORS: true
summary: "Get random integer"
description: "Get random integer between min and max"
operationId: "getRandom"
produces:
- "application/json"
parameters:
- name: "min"
in: "path"
description: "Minimal Integer"
required: true
type: "integer"
format: "int32"
- name: "max"
in: "path"
description: "Maximal Integer"
required: true
type: "integer"
format: "int32"
responses:
200:
description: "OK"Aqui está seu conteúdo:
Informações básicas sobre nossa API e versão OAS usada.
swagger: "2.0"
info:
description: "Math"
version: "1.0.0"
title: "Math REST API"
Host do servidor, protocolo (http, https) e nomes de aplicações web:
host: "localhost:52773"
basePath: "/math"
schemes:
- http
Em seguida, especificamos um caminho (para que a URL completa seja http://localhost:52773/math/random/:min/:max) e o método de solicitação HTTP (get, post, put, delete):
paths:
/random/{min}/{max}:
get:
Depois disso, especificamos informações sobre nossa solicitação:
x-ISC_CORS: true
summary: "Get random integer"
description: "Get random integer between min and max"
operationId: "getRandom"
produces:
- "application/json"
parameters:
- name: "min"
in: "path"
description: "Minimal Integer"
required: true
type: "integer"
format: "int32"
- name: "max"
in: "path"
description: "Maximal Integer"
required: true
type: "integer"
format: "int32"
responses:
200:
description: "OK"
Nesta parte, definimos nossa solicitação:
Como você pode ver, este formato não é particularmente desafiador, embora haja muitos outros recursos disponíveis, aqui está uma especificação.
Finalmente, vamos exportar nossa definição como um JSON. Vá em File → Convert and save as JSON. A especificação deve ser semelhante a esta:
{
"swagger": "2.0",
"info": {
"description": "Math",
"version": "1.0.0",
"title": "Math REST API"
},
"host": "localhost:52773",
"basePath": "/math",
"schemes": [
"http"
],
"paths": {
"/random/{min}/{max}": {
"get": {
"x-ISC_CORS": true,
"summary": "Get random integer",
"description": "Get random integer between min and max",
"operationId": "getRandom",
"produces": [
"application/json"
],
"parameters": [
{
"name": "min",
"in": "path",
"description": "Minimal Integer",
"required": true,
"type": "integer",
"format": "int32"
},
{
"name": "max",
"in": "path",
"description": "Maximal Integer",
"required": true,
"type": "integer",
"format": "int32"
}
],
"responses": {
"200": {
"description": "OK"
}
}
}
}
}
}
Agora que temos nossas especificações, podemos gerar um código padrão para esta API REST no InterSystems IRIS.
Para passar para este estágio, precisaremos de três coisas:
math)/math em nosso caso)Existem três maneiras de usar nossa especificação para geração de código, elas são essencialmente as mesmas e apenas oferecem várias maneiras de acessar a mesma funcionalidade
^%REST (Do ^%REST em uma sessão de terminal interativa), documentação.%REST (Set sc = ##class(%REST.API).CreateApplication(applicationName, spec), não interativa), documentação.Acho que a documentação descreve adequadamente as etapas necessárias, então apenas escolha uma. Vou adicionar duas notas:
set sc = ##class(%SYS.REST).DeployApplication(restApp, webApp, authenticationType), então em nosso caso, set sc = ##class(%SYS.REST).DeployApplication("math", "/math"), obter valores para o argumento authenticationType do arquivo de inclusão %sySecurity, entradas relevantes são $$$Authe*, então para um acesso não autenticado use $$$AutheUnauthenticated. Se omitido, o parâmetro padroniza para autenticação de senha.Se você criou a aplicação com sucesso, um novo pacote math deve ter sido criado com três classes:
Documentação com mais informações sobre as classes.
Inicialmente, nossa classe de implementação math.impl contém apenas um método, correspondendo à nossa operação /random/{min}/{max}:
/// Obtenha um número inteiro aleatório entre min e max<br/>
/// Os argumentos do método contêm valores para:<br/>
/// min, número inteiro mínimo<br/>
/// max, número inteiro máximo<br/>
ClassMethod getRandom(min As %Integer, max As %Integer) As %DynamicObject
{
//(Place business logic here)
//Do ..%SetStatusCode(<HTTP_status_code>)
//Do ..%SetHeader(<name>,<value>)
//Quit (Coloque a resposta aqui) ; a resposta pode ser uma string, uma stream ou um objeto dinâmico
}
Vamos começar com a implementação trivial:
ClassMethod getRandom(min As %Integer, max As %Integer) As %DynamicObject
{
quit {"value":($random(max-min)+min)}
}
E, finalmente, podemos chamar nossa API REST abrindo esta página no navegador: http://localhost:52773/math/random/1/100
A saída deve ser:
{
"value": 45
}
Também no editor Swagger, pressionando o botão Try it out e preenchendo os parâmetros da solicitação, também será enviada a mesma solicitação:

Parabéns! Nossa primeira API REST criada com uma abordagem de especificação primeiro (spec-first) está agora disponível!
Claro, nossa API não é estática e precisamos adicionar novos caminhos e assim por diante. Com o desenvolvimento de especificação primeiro, você começa modificando a especificação, em seguida atualiza a aplicação REST (utilizando as mesmas chamadas que foram utilizadas para criar a aplicação) e finalmente escreve o código. Observe que as atualizações de especificações são seguras: seu código não é afetado, mesmo se o caminho for removido de uma especificação, o método não seria excluído da classe de implementação.
Mais notas!
A InterSystems adicionou parâmetros especiais à especificação swagger, aqui estão:
| Nome | Tipo de Dado | Padrão | Local | Descrição |
| x-ISC_DispatchParent | classname | %CSP.REST | info | Super classe para a classe de despacho. |
| x-ISC_CORS | boolean | false | operation | Flag para indicar que requisições CORS para esta combinação endpoint/método deve ser suportada. |
| x-ISC_RequiredResource | array | operation | Lista separada por vírgulas dos recursos definidos e seus modos de acesso (recurso:modo) que são requeridos para acesso a este endponit do serviço REST. Exemplo: ["%Development:USE"] | |
| x-ISC_ServiceMethod | string | operation | Nome do método de classe invocado internamente para atender a esta operação; o valor padrão é o operationId, o que é normalmente adequado. |
Existem três maneiras de habilitar o suporte ao CORS.
Em uma rota na rota base, especificando x-ISC_CORS como verdadeiro (true). Isso é o que fizemos em nossa API REST de matemática.
Por API, adicionando
Parameter HandleCorsRequest = 1;
e recompilando a classe. Ele também sobreviveria à atualização das especificações.
%CSP.REST) e escrevendo a lógica de processamento CORS lá. Para usar esta superclasse, adicione x-ISC_DispatchParent à sua especificação.Finalmente, vamos adicionar nossa especificação no IAM para que seja publicada para outros desenvolvedores.
Se você ainda não começou a utilizar o IAM, consulte este artigo. Ele também fala a respeito da disponibilização da API REST através do IAM, por isso não o descreverei aqui. Você pode querer modificar a especificação do host e os parâmetros do basepath para que eles apontem para o IAM, em vez de apontar para a instância InterSystems IRIS.
Abra o portal do administrador do IAM e acesse a aba Specs no espaço de trabalho relevante.

Clique no botão Add Spec e insira o nome da nova API (math em nosso caso). Depois de criar uma nova especificação no IAM, clique em Edit e cole o código da especificação (JSON ou YAML - não importa para o IAM):

Não se esqueça de clicar em Update File.
Agora nossa API está publicada para desenvolvedores. Abra o Portal do Desenvolvedor e clique em Documentação no canto superior direito. Além das três APIs padrão, nossa nova API REST Math deve estar disponível:

Abra-a:

Agora os desenvolvedores podem ver a documentação de nossa nova API e testá-la no mesmo lugar!
O InterSystems IRIS simplifica o processo de desenvolvimento de APIs REST e, a abordagem de especificação primeiro (spec-first) permite um gerenciamento mais rápido e fácil do ciclo de vida das APIs REST. Com essa abordagem, você pode usar uma variedade de ferramentas para uma variedade de tarefas relacionadas, como geração de cliente, teste de unidade, gerenciamento de API e muitos outros.

Este artigo apresenta o InterSystems iKnow Entity Browser, uma aplicação web que permite visualizar dados de texto extraídos e organizados obtidos de um grande número de textos, alimentado pela tecnologia InterSystems iKnow, também conhecida como InterSystems Text Analytics no InterSystems IRIS. Sinta-se à vontade para experimentar a demonstração dessa ferramenta ou aprender mais sobre ela no InterSystems Open Exchange.
Comecei o desenvolvimento deste projeto no final de 2016. De agora em diante, o meu iKnow Entity Browser é usado em todo o mundo por aqueles que usam a tecnologia InterSystems e por aqueles que fazem extração de texto. Este artigo deveria ter aparecido antes, entretanto, nunca é tarde para contar algo sobre coisas úteis!
InterSystems iKnow (ou InterSystems Text Analytics) é uma tecnologia de NLP incorporável que permite extrair dados significativos de textos. Bem, não apenas para extrair esses dados, mas também para coletá-los, vinculá-los, filtrá-los e priorizá-los. Como resultado, o InterSystems iKnow fornece uma base sólida para a construção de aplicações de dados para mineração de dados.
Do ponto de vista da programação, o iKnow fornece uma API rica que permite incorporar essa tecnologia a qualquer aplicação, independentemente de sua linguagem de programação. O iKnow Entity Browser usa esta API para visualizar os dados processados na forma de uma árvore de conceitos e relações.
Antes do lançamento do InterSystems iKnow Entity Browser, a única solução pronta para uso disponível para exploração de dados era o visualizador incorporado do iKnow, que é enviado junto com os produtos baseados no InterSystems Caché e IRIS. Este visualizador apresenta muitas ferramentas úteis principalmente para pesquisar algo no texto processado (no iKnow é chamado de domínio), enquanto o iKnow Entity Browser é criado também para visualizar e organizar conceitos em um texto.

Visualização do Portal de Conhecimento iKnow
O iKnow Entity Browser é um projeto de código aberto, o que significa que qualquer pessoa pode contribuir com seu núcleo. Aqui está a lista de recursos que foram desenvolvidos:

Demonstração de gráfico do iKnow Entity Browser
A instalação do iKnow Entity Browser é bastante direta. Baixe a versão mais recente (arquivo XML) da aplicação e importe-a para o namespace habilitado para iKnow (por exemplo, SAMPLES). Isso funciona com todos os lançamentos mais recentes dos produtos InterSystems, incluindo a plataforma de dados InterSystems IRIS. Para importar o arquivo XML, você pode arrastar e soltar o arquivo na janela do Studio (Atelier). Alternativamente, você pode importar o arquivo usando o portal de gerenciamento de sistemas, no explorador de sistemas - classes. Em seguida, abra o seu navegador na página web http://localhost:57772/EntityBrowser/ (altere o host/porta respectivamente para a configuração do seu servidor e lembre-se de colocar uma barra / no final da URL).
Para excluir a aplicação, basta excluir o pacote EntityBrowser do Studio/Atelier. A aplicação web instalada será excluída automaticamente da mesma forma que foi criada durante a instalação, se não foi modificada desde então.
Atualmente, para usar o iKnow Entity Browser em diferentes namespaces, você precisa importá-lo para cada namespace habilitado para iKnow e configurar manualmente a aplicação web (por exemplo, você pode clonar a aplicação /EntityBrowser e renomeá-la). Nesse caso, altere as configurações dentro da aplicação web para as correspondentes (leia o guia de personalização abaixo).
Se você instalou o iKnow Entity Browser no servidor e tornou a aplicação web pública, pode se conectar a esse servidor a partir de qualquer front-end, até mesmo a partir desta aplicação de demonstração, por exemplo.
O menu de configuração da aplicação, localizado no canto superior direito da interface do usuário, permite personalizar a aparência e a fonte de dados. No menu de configurações, você pode especificar o seguinte (veja a imagem abaixo):
Configurações do iKnow Entity Browser
Uma vez que o conceito de seed é especificado nas configurações, o iKnow Entity Browser constrói um gráfico de conceitos semelhantes ou relacionados ao conceito de seed. Você pode brincar com este gráfico arrastando seus nós, no entanto, a força física sempre tentará organizá-lo na forma de um diagrama de floco de neve.
O gráfico pode ser editado usando os controles na parte inferior da tela. Isso inclui os botões desfazer/refazer, aumentar/diminuir o zoom e redefinir os botões de zoom, redefinir o botão de seleção, desvincular e excluir botões de seleção. Passar o mouse sobre qualquer um desses botões exibe uma dica de ferramenta.

Menu com controles
Caso precise de uma lista de conceitos selecionados, você pode alternar uma visualização tabular pressionando o botão correspondente no canto superior direito. Tudo o que você faz no gráfico fica sincronizado com a visualização tabular e vice-versa.
Na visualização tabular, quando você passa o mouse sobre uma das linhas, o nó correspondente é destacado no gráfico. Se você clicar na linha, a visualização do gráfico se concentra automaticamente no nó correspondente. Assim como no gráfico, você pode clicar nos botões nas linhas da tabela para selecionar/desmarcar os nós.

Visualização Tabular
Depois de ter uma seleção de nós, você pode exportá-los como uma tabela no formato *.csv. Pressione o botão de visualização tabular no canto superior direito para que a tabela apareça e então você encontrará o botão "Exportar". Isso exportará todos os nós selecionados na forma de uma tabela, a mesma tabela que você tem em uma visualização tabular.
iKnow Entity Browser é apenas um dos vários projetos que fiz para a corporação InterSystems. Aqui estão alguns, se você ainda não viu esses projetos: WebTerminal, Visual Editor, Class Explorer, Light Pivot Table, GlobalsDB Admin. Encontre esses e outros projetos relacionados à InterSystems no InterSystems Marketplace.
Todos os meus projetos são de código aberto, permitindo que outros contribuam. O código desses projetos está disponível no GitHub. Você também pode usar seu código como um exemplo para construir sua própria aplicação sobre os produtos da InterSystems. Se você der uma olhada mais de perto, descobrirá que a maioria deles são pacotes instaláveis, enviados em um único arquivo XML. Se você está curioso em usar a mesma estratégia para seus pacotes, confira este artigo.
Espero que você ache o iKnow Entity Browser e outros projetos úteis! Aproveite!
##Introdução
Estamos na era da economia multi-plataforma, e as API's são a "liga" deste cenário digital. Sendo tão importantes, elas são encaradas por desenvolvedores como um serviço ou produto a ser consumido. Assim sendo, a experiência na sua utilização é um fator crucial de sucesso.
Visando melhorar esta experiência, padrões de especificação, como o OpenAPI Specification (OAS) estão cada vez mais sendo adotados no desenvolvimento de API's RESTFul.
##O que é o IRIS ApiPub?
IRIS ApiPub é um projeto Open Source, que tem como principal objetivo publicar automaticamente API's RESTful criadas com a tecnologia Intersystems IRIS, da forma mais simples e rápida possível, utilizando o padrão Open API Specification (OAS) versão 3.0.
Ele permite que o usuário foque principalmente na implementação e nas regras de negócio das API’s (Web Methods), abstraindo e automatizando os demais aspectos relacionados a documentação, exposição, execução e monitoramento dos serviços.

Este projeto também inclui uma implementação de exemplo completa (apiPub.samples.api) do sampleSwagger Petstore, utilizado como sample oficial do swagger.
Se você já possui serviços SOAP publicados, você pode testar a sua publicação com Rest/JSON com OAS 3.0.

Ao publicar métodos com tipos complexos é necessário que a classe do objeto seja uma subclasse de %XML.Adaptor. Desta maneira serviços SOAP já construídos se tornam automaticamente compatíveis.

Habilite o monitoramento das API's para administrar e rastrear todas as chamadas Rest. Monte também os seus próprios indicadores.

$ git clone https://github.com/devecchijr/apiPub.git
$ docker-compose build
$ docker-compose up -d
Abra a URL do swagger http://localhost:52773/swagger-ui/index.html
Tente executar alguma API do Petstore, como fazer o post de um novo pet.
Veja o dashboard do apiPub Monitor. Tente fazer um drill down no domínio petStore para explorar e analisar as mensagens.
Mude ou crie metódos na classe apiPub.samples.api e volte a consultar a documentação gerada. Repare que todas as mudanças são automaticamentes refletidas na documentação OAS ou nos schemas.
Defina a classe de implementação das tuas API’s e rotule os métodos com o atributo [WebMethod]

Caso você já possua alguma implementação com WebServices esse passo não é necessário.
Crie uma subclasse de apiPub.core.service e aponte a propriedade DispatchClass para a sua classe de Implementação criada anteriormente. Informe também o path de documentação OAS 3.0. Se desejar, aponte para a classe apiPub.samples.api (PetStore).

Crie uma Aplicação Web e aponte a classe de Dispatch para a classe de serviço criada anteriomente.

Com o iris-web-swagger-ui é possível expor a especificação do teu serviço. Basta apontar para o path de documentação e ... VOILÁ!!

Há duas maneiras de definir o cabeçalho OAS 3.0:
A primeira é através da criação de um bloco JSON XDATA nomeado como apiPub na classe de implementação. Este método permite que se tenha mais de uma Tag e a modelagem é compatível com o padrão OAS 3.0. As propriedades permitidas para customização são info, tags e servers.
XData apiPub [ MimeType = application/json ]
{
{
"info" : {
"description" : "This is a sample Petstore server. You can find\nout more about Swagger at\n[http://swagger.io](http://swagger.io) or on\n[irc.freenode.net, #swagger](http://swagger.io/irc/).\n",
"version" : "1.0.0",
"title" : "IRIS Petstore (Dev First)",
"termsOfService" : "http://swagger.io/terms/",
"contact" : {
"email" : "apiteam@swagger.io"
},
"license" : {
"name" : "Apache 2.0",
"url" : "http://www.apache.org/licenses/LICENSE-2.0.html"
}
},
"tags" : [ {
"name" : "pet",
"description" : "Everything about your Pets",
"externalDocs" : {
"description" : "Find out more",
"url" : "http://swagger.io"
}
}, {
"name" : "store",
"description" : "Access to Petstore orders"
}, {
"name" : "user",
"description" : "Operations about user",
"externalDocs" : {
"description" : "Find out more about our store",
"url" : "http://swagger.io"
}
} ]
}
}
A segunda maneira é através da definição de parâmetros na classe de implementação, assim como no exemplo a seguir:
Parameter SERVICENAME = "My Service";
Parameter SERVICEURL = "http://localhost:52776/apipub";
Parameter TITLE As %String = "REST to SOAP APIs";
Parameter DESCRIPTION As %String = "APIs to Proxy SOAP Web Services via REST";
Parameter TERMSOFSERVICE As %String = "http://www.intersystems.com/terms-of-service/";
Parameter CONTACTNAME As %String = "John Doe";
Parameter CONTACTURL As %String = "https://www.intersystems.com/who-we-are/contact-us/";
Parameter CONTACTEMAIL As %String = "support@intersystems.com";
Parameter LICENSENAME As %String = "Copyright InterSystems Corporation, all rights reserved.";
Parameter LICENSEURL As %String = "http://docs.intersystems.com/latest/csp/docbook/copyright.pdf";
Parameter VERSION As %String = "1.0.0";
Parameter TAGNAME As %String = "Services";
Parameter TAGDESCRIPTION As %String = "Legacy Services";
Parameter TAGDOCSDESCRIPTION As %String = "Find out more";
Parameter TAGDOCSURL As %String = "http://intersystems.com";

É possível customizar vários aspectos das API's, como tags, paths e verbos. Para tal, é necessária a utilização de uma notação específica, definida no comentário do método a ser customizado.
Sintaxe:
/// @apiPub[assignment clause]
[Method/ClassMethod] methodName(params as type) As returnType {}
Todas as customizações dadas como exemplo nesta documentação estão disponíveis na classe apiPub.samples.api.
Quando não há nenhum tipo complexo como parâmetro de entrada, apiPub atribui automaticamente o verbo como Get. Caso contrário é atribuído o verbo Post.
Caso se queira customizar o método adiciona-se a seguinte linha nos comentários do método.
/// @apiPub[verb="verb"]
Onde verb pode ser get, post, put, delete ou patch.
Exemplo:
/// @apiPub[verb="put"]
Esta ferramenta atribui automaticamente os paths ou o roteamento para os Web Methods. Ele utiliza como padrão o nome do método como path.
Caso se queira customizar o path adiciona-se a seguinte linha nos comentários do método.
/// @apiPub[path="path"]
Onde path pode ser qualquer valor precedido com barra, desde que não conflita com outro path na mesma classe de implementação.
Exemplo:
/// @apiPub[path="/pet"]
Outro uso bastante comum do path é definir um ou mais parâmetros no próprio path. Para tal, é necessário que o nome do parâmetro definido no método esteja entre chaves.
Exemplo:
/// @apiPub[path="/pet/{petId}"]
Method getPetById(petId As %Integer) As apiPub.samples.Pet [ WebMethod ]
{
}
Quando o nome do parâmetro interno difere do nome do parâmetro exposto, pode-se equalizar o nome conforme exemplo a seguir:
/// @apiPub[path="/pet/{petId}"]
/// @apiPub[params.pId.name="petId"]
Method getPetById(pId As %Integer) As apiPub.samples.Pet [ WebMethod ]
{
}
No exemplo acima, o parâmetro interno pId é exposto como petId.
É possível definir a tag(agrupamento) do método quando há mais que uma tag definida no cabeçalho.
/// @apiPub[tag="value"]
Exemplo:
/// @apiPub[tag="user"]
Caso se queira alterar o Status Code sucesso do método, que é por padrão 200, utiliza-se a seguinte notação.
/// @apiPub[successfulCode="code"]
Exemplo:
/// @apiPub[successfulCode="201"]
Esta ferramenta assume como padrão o Status Code 500 para quaisquer exceções. Caso se queira adicionar novos códigos para exceção na documentação, utiliza-se a seguinte notação.
/// @apiPub[statusCodes=[{code:"code",description:"description"}]]
Onde a propriedade statusCodes é um array de objetos com código e descrição.
Exemplo:
/// @apiPub[statusCodes=[
/// {"code":"400","description":"Invalid ID supplied"}
/// ,{"code":"404","description":"Pet not found"}]
/// ]
Ao disparar a exceção, Inclua o Status Code na descrição da exceção entre os sinais de "<" e ">".
Exemplo:
Throw ##Class(%Exception.StatusException).CreateFromStatus($$$ERROR($$$GeneralError, "<400> Invalid ID supplied"))}
Veja o método getPetById da classe apiPub.samples.api
Para que a API seja exposta como deprecated, utiliza-se a seguinte notação:
/// @apiPub[deprecated="true"]
Segundo a especificação OAS, operationId é uma string única usada para identificar uma API ou operação. Nesta ferramenta ela é utilizada para a mesma finalidade no monitoramento e rastreamento das operações.
Por padrão, ela recebe o mesmo nome do método da classe de implementação.
Caso se queira alterá-la utiliza-se a seguinte notação
/// @apiPub[operationId="updatePetWithForm"]
O charset padrão da geralmente é definido através do parâmetro CHARSET na classe de serviço, descrita no Passo 2. Caso se queira customizar o charset de um método, deve se utilizar a seguinte notação:
/// @apiPub[charset="value"]
Exemplo:
/// @apiPub[charset="UTF-8"]
Pode-se customizar vários aspectos de cada parâmetro de entrada e saída dos métodos, como por exemplo os nomes e as descrições que serão expostas para cada parâmetro.
Para se customizar um parametro específico utiliza-se a seguinte notação
/// @apiPub[params.paramId.property="value"]
ou para respostas:
/// @apiPub[response.property="value"]
Exemplo:
/// @apiPub[params.pId.name="petId"]
/// @apiPub[params.pId.description="ID of pet to return"]
Neste caso, está sendo atribuido o nome petId e a descrição ID of pet to return para o parâmetro definido como pId
Quando a customização não é específica para um determinado parâmetro, utiliza-se a seguinte notação
/// @apiPub[params.property="value"]
No exemplo abaixo, a descrição This can only be done by the logged in user é atribuída para todo o request, não apenas para um parâmetro:
/// @apiPub[params.description="This can only be done by the logged in user."]
Utilize a seguinte notação para parâmetros de entrada ou saída:
/// @apiPub[params.paramId.property="value"]
Para respostas:
/// @apiPub[response.property="value"]
| Propriedade |
|---|
| required: "true" se o parâmetro for requerido. Todos os parâmetros do tipo path já são automaticamente requeridos |
| schema.items.enum: exposição de Enumeradores para tipos %String ou %Library.DynamicArray. Veja o método findByStatus da classe apiPub.samples.api |
| schema.default: Aponta para um valor default para enumeradores. |
| inputType: Por padrão é query parameter para os tipos simples e application/json para os tipos complexo (body). Caso se queira alterar o tipo de input, pode se utilizar este parâmetro. Exemplo de uso: Upload de uma imagem, que normalmente não é do tipo JSON. Veja método uploadImage da classe apiPub.samples.api. |
| outputType: Por padrão é header para os tipos %Status e application/json para o restante. Caso se queira alterar o tipo de output, pode se utilizar este parâmetro. Exemplo de uso: Retorno de um token ("text/plain"). Veja método loginUser da classe apiPub.samples.api |
É possível relacionar schemas OAS 3.0 a tipos dinâmicos internos.
A vantagem de se relacionar o schema com o parâmetro, além de informar ao usuário a especificação do objeto requerido, é o parsing automático do request é realizado na chamada da API. Se o usuário da API por exemplo enviar uma propriedade que não está no schema, enviar uma data em um formato inválido ou não enviar uma propriedade obrigatória, um ou mais erros serão retornados ao usuário informando as irregularidades.
O primeiro passo é incluir o schema desejado no bloco XDATA conforme exemplo abaixo. Neste caso o schema chamado User pode ser utilizado por qualquer método. Ele deve seguir as mesmas regras da modelagem OAS 3.0.
XData apiPub [ MimeType = application/json ]
{
{
"schemas": {
"User": {
"type": "object",
"required": [
"id"
],
"properties": {
"id": {
"type": "integer",
"format": "int64"
},
"username": {
"type": "string"
},
"firstName": {
"type": "string"
},
"lastName": {
"type": "string"
},
"email": {
"type": "string"
},
"password": {
"type": "string"
},
"phone": {
"type": "string"
},
"userStatus": {
"type": "integer",
"description": "(short) User Status"
}
}
}
}
}
}
O segundo passo é relacionar o nome do schema informado no passo anterior ao parâmetro interno do tipo %Library.DynamicObject usando a seguinte notação:
/// @apiPub[params.paramId.schema="schema name"]
Exemplo associando o parâmetro user ao schema User:
/// @apiPub[params.user.schema="User"]
Method updateUserUsingOASSchema(username As %String, user As %Library.DynamicObject) As %Status [ WebMethod ]
{
code...
}
Exemplo de request com erro a ser submetido. A propriedade username2 não existe no schema User. A propriedade id também não foi especificada e é requerida:
{
"username2": "devecchijr",
"firstName": "claudio",
"lastName": "devecchi junior",
"email": "devecchijr@gmail.com",
"password": "string",
"phone": "string",
"userStatus": 0
}
Exemplo de erro retornado:
{
"statusCode": 0,
"message": "ERRO #5001: <Bad Request> Path User.id is required; Invalid path: User.username2",
"errorCode": 5001
}
Veja métodos updateUserUsingOASSchema e getInventory da classe apiPub.samples.api. O método getInventory é um exemplo de schema associado à saída do método (response), portanto não é parseável.
Para auxiliar na geração do schema OAS 3.0, você pode usar o seguinte recurso:
Defina uma variável com uma amostra do objeto JSON.
set myObject = {"prop1":"2020-10-15","prop2":true, "prop3":555.55, "prop4":["banana","orange","apple"]}
Utilize o método utilitário da classe apiPub.core.publisher para gerar o schema:
do ##class(apiPub.core.publisher).TemplateToOpenApiSchema(myObject,"objectName",.schema)
Copie e cole o schema retornado no bloco XDATA:
Exemplo:
XData apiPub [ MimeType = application/json ]
{
{
"schemas": {
{
"objectName":
{
"type":"object",
"properties":{
"prop1":{
"type":"string",
"format":"date",
"example":"2020-10-15"
},
"prop2":{
"type":"boolean",
"example":true
},
"prop3":{
"type":"number",
"example":555.55
},
"prop4":{
"type":"array",
"items":{
"type":"string",
"example":"apple"
}
}
}
}
}
}
}
}
1 - Adicione e ative os seguintes componentes na tua Production (IRIS Interoperability)
| Component | Type |
|---|---|
| apiPub.tracer.bm | Service (BS) |
| apiPub.tracer.bs | Service (BS) |
| apiPub.tracer.bo | Operation (BO) |
2 - Ative o monitoramento na classe descrita no Passo 2
O parâmetro Traceable deve estar ativado.
Parameter Traceable As %Boolean = 1;
Parameter TracerBSName = "apiPub.tracer.bs";
Parameter APIDomain = "samples";
O parâmetro APIDomain é utilizado para agrupar as API's no monitoramento.
3 - Importe os dashboards
zn "IRISAPP"
Set sc = ##class(%DeepSee.UserLibrary.Utils).%ProcessContainer("apiPub.tracer.dashboards",1)
Outros dashboards também podem ser criados com base no cubo apiPub Monitor.
Roteie as suas API's geradas e obtenha diversas vantagens com o Intersystems API Manager
ApiPub é compatível com o produto Intersystems IRIS ou Intersystems IRIS for Health a partir da versão 2018.1.
Github: apiPub
Hoje em dia existem muitas aplicações que estão usando o Open Authorization framework (OAuth) para acessar recursos de todos os tipos de serviços de maneira segura, confiável e eficiente. O InterSystems IRIS já é compatível com a estrutura OAuth 2.0, na verdade, há um ótimo artigo na comunidade sobre OAuth 2.0 e InterSystems IRIS no seguinte link aqui.
No entanto, com o advento das ferramentas de gerenciamento de API, algumas organizações estão usando-as como um único ponto de autenticação, evitando que solicitações não autorizadas cheguem aos serviços de downstream e desacoplando as complexidades de autorização/autenticação do próprio serviço.
Como você deve saber, a InterSystems lançou sua ferramenta de gerenciamento de API, chamada InterSystems API Management (IAM), que está disponível com a licença IRIS Enterprise (mas não com o IRIS Community Edition). Aqui esta outra ótima postagem na comunidade apresentando o InterSystems API Management.
Esta é a primeira parte de uma série de artigos de três partes que mostram como você pode usar o IAM para simplesmente adicionar segurança, de acordo com os padrões do OAuth 2.0, a um serviço não autenticado implantado no IRIS anteriormente.
Nesta primeira parte, serão fornecidos alguns antecedentes do OAuth 2.0 juntamente com algumas definições e configurações iniciais do IRIS e IAM para facilitar a compreensão de todo o processo de proteção de seus serviços.
Após a primeira parte, esta série de artigos abordará dois cenários possíveis para proteger seus serviços com IAM. No primeiro cenário, o IAM validará apenas o token de acesso presente na solicitação de entrada e encaminhará a solicitação para o backend se a validação for bem-sucedida. No segundo cenário, o IAM irá gerar um token de acesso (atuando como um servidor de autorização) e validá-lo.
Portanto, a segunda parte irá discutir e mostrar em detalhes as etapas necessárias para configurar o cenário 1 e a terceira parte irá discutir e demonstrar as configurações do cenário 2, juntamente com algumas considerações finais.
Se você quiser testar o IAM, entre em contato com seu representante de vendas da InterSystems.
Cada fluxo de autorização OAuth 2.0 consiste basicamente em 4 partes:
Para simplificar, este artigo usará o fluxo OAuth “Credenciais da Senha do Proprietário do Recurso”, mas você pode usar qualquer fluxo OAuth no IAM. Além disso, este artigo não especificará nenhum escopo.
Normalmente, o fluxo de Credenciais da Senha do Proprietário do Recurso segue estas etapas:
Com isso em mente, existem dois cenários em que você pode usar o IAM para lidar com o OAuth 2.0:
Nesta postagem, será utilizado uma aplicação IRIS Web denominada “/SampleService”. Como você pode ver na captura de tela abaixo, este é um serviço REST não autenticado implantado no IRIS:
.png)
Adicionalmente, é configurado um serviço chamado “SampleIRISService” no lado do IAM contendo uma rota, como você pode ver na imagem abaixo:
.png)
Além disso, é configurado um consumidor chamado “ClientApp” no IAM, inicialmente sem nenhuma credencial, para identificar quem está chamando a API no IAM:
.png)
Com as configurações acima, o IAM faz proxy para o IRIS a cada solicitação GET enviada para a seguinte URL:
Neste ponto, nenhuma autenticação é usada ainda. Portanto, se enviarmos uma solicitação GET simples, sem autenticação, para a URL
obtemos a resposta desejada.
Neste artigo, vamos usar uma aplicação chamada “PostMan” para enviar solicitações e verificar as respostas. Na captura de tela abaixo do PostMan, você pode ver a solicitação GET simples junto com sua resposta.
.png)
Continue lendo até a segunda parte desta série para entender como configurar o IAM para validar os tokens de acesso presentes nas solicitações de entrada.