Nueva publicación

Encontrar

Artículo
· 12 feb, 2025 Lectura de 6 min

Utilizando API REST, Flask e IAM com o InterSystems IRIS - Parte 2 – Aplicativo Flask

Utilizando Flask, API REST e IAM com o InterSystems IRIS

Parte 2 – Aplicativo Flask

 

Flask é um microframework de desenvolvimento web escrito em Python. Ele é conhecido por ser simples, flexível e permitir o desenvolvimento rápido de aplicações. 

A instalação do Flask é muito simples. Depois de ter o python instalado corretamente no seu sistema operacional precisamos instalar a biblioteca flask com o comando pip. Para o consumo de API REST é aconselhado o uso da biblioteca requests. O link a seguir traz um guia para a instalação do flask: https://flask.palletsprojects.com/en/stable/installation/

 Instalado o flask, vamos então começar com a estrutura do nosso aplicativo. Vamos criar os diretórios e sub-diretórios para acomodar nossos arquivos:

 

/--+

   |

   +-- static

   |

   +-- templates

 

Vamos então seguir essa definição. Por exemplo, em c:\temp vamos criar o diretório flask e abaixo vamos criar os sub-diretórios static e template.

Siga a documentação de instalação e instale e configute o venv. Depois instale a biblioteca flask como o comando pip. A documentação do flask mostra o comando. Lembre-se que você precisa já ter o python instalado.

Depois de instalar a biblioteca flask, instale a biblioteca requests com o pip, da mesma forma que instalou o flask.

No diretório flask vamos colocar nossa aplicação python. A seguir o código da aplicação:

from flask import Flask, render_template, request, redirect, url_for

import requests

from requests.auth import HTTPBasicAuth

 

app = Flask(__name__)

 

API_URL = "http://192.168.0.13/iris/rest/servico/cliente"

USERNAME = "_SYSTEM"

PASSWD = "SYS"

 

# Rota para Listar Registros

@app.route('/')

def index():

 

    response = requests.get(API_URL, auth=HTTPBasicAuth(USERNAME, PASSWD))

    data = response.json()

    lista = data["clientes"]

    return render_template("index.html", registros=lista)

 

# Rota para Exibir o Formulário de Inclusão

@app.route('/incluir', methods=['GET'])

def incluir():

    return render_template("form.html", registro={"id": "", "nome": "", "idade": ""}, acao="Incluir")

 

# Rota para Criar um Novo Registro

@app.route('/criar', methods=['POST'])

def criar():

    dados = {

        "nome": request.form["nome"],

        "idade": request.form["idade"]

    }

    requests.post(API_URL, json=dados, auth=HTTPBasicAuth(USERNAME, PASSWD))

    return redirect(url_for("index"))

 

# Rota para Exibir o Formulário de Edição

@app.route('/editar/<int:id>', methods=['GET'])

def editar(id):

    response = requests.get(f"{API_URL}/{id}", auth=HTTPBasicAuth(USERNAME, PASSWD))

    registro = response.json() if response.status_code == 200 else {"id": "", "nome": "", "idade": ""}

    return render_template("form.html", registro=registro, acao="Editar")

 

# Rota para Atualizar um Registro Existente

@app.route('/atualizar/<int:id>', methods=['POST'])

def atualizar(id):

    dados = {

        "nome": request.form["nome"],

        "idade": request.form["idade"]

    }

    requests.put(f"{API_URL}/{id}", json=dados, auth=HTTPBasicAuth(USERNAME, PASSWD))

    return redirect(url_for("index"))

 

# Rota para Deletar um Registro

@app.route('/deletar/<int:id>')

def deletar(id):

    requests.delete(f"{API_URL}/{id}", auth=HTTPBasicAuth(USERNAME, PASSWD))

    return redirect(url_for("index"))

 

if __name__ == "__main__":

    app.run(debug=True)

 

O código é bem simples, temos as rotas de inclusão, alteração, deleção, uma rota para listar os registros existentes e dar acesso as opções de manutenção, e os formulários de inclusão e alteração.

Agora vamos para o sub-diretório static. Nele vamos colocar nosso arquivo de CSS style.css:

 

body {

    ;

    text-align: center;

    margin: 20px;

}

 

table {

    width: 60%;

    margin: auto;

    border-collapse: collapse;

}

 

th, td {

    border: 1px solid black;

    padding: 8px;

}

 

a {

    text-decoration: none;

    color: blue;

}

 

E no sub-diretório templates vamos colocar nossos arquivos HTML index.html e form.html:

index.html

<!DOCTYPE html>

<html lang="pt">

<head>

    <meta charset="UTF-8">

    <title>CRUD Flask</title>

    <link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">

</head>

<body>

    <h2>Lista de Registros</h2>

    <a href="{{ url_for('incluir') }}">Adicionar Novo</a>

    <table border="1">

        <tr>

            <th>ID</th>

            <th>Nome</th>

            <th>Idade</th>

            <th>Ações</th>

        </tr>

        {% for reg in registros %}

        <tr>

            <td>{{ reg.id }}</td>

            <td>{{ reg.nome }}</td>

            <td>{{ reg.idade }}</td>

            <td>

                <a href="{{ url_for('editar', id=reg.id) }}">Editar</a> |

                <a href="{{ url_for('deletar', id=reg.id) }}" onclick="return confirm('Tem certeza?')">Excluir</a>

            </td>

        </tr>

        {% endfor %}

    </table>

</body>

</html>

 

form.html

 

<!DOCTYPE html>

<html lang="pt">

<head>

    <meta charset="UTF-8">

    <title>{{ acao }} Registro</title>

</head>

<body>

    <h2>{{ acao }} Registro</h2>

    <form method="POST" action="{{ url_for('criar' if acao == 'Incluir' else 'atualizar', id=registro.id) }}">

        <label>Nome:</label>

        <input type="text" name="nome" value="{{ registro.nome }}" required><br>

        <label>idade:</label>

        <input type="text" name="idade" value="{{ registro.idade }}" required><br>

        <button type="submit">{{ acao }}</button>

    </form>

    <a href="{{ url_for('index') }}">Voltar</a>

</body>

</html>

 

Para executar a aplicação basta ir para o diretório onde estamos com nossa aplicação python (no nosso caso, c:\temp\flask), ativar o venv (ambiente virtual) e executar a aplicação:

 

 

Agora podemos acessar nossa aplicação acessando a porta 5000 com um navegador:

 

Clicando no link Adicionar Novo temos a tela de inclusão de registros na nossa classe:

 

Voltando a tela de index, selecionado Alterar em algum registro, temos a tela de alteração:

 

E, novamente voltando a tela de index, clicando em Excluir vamos para a confirmação da deleção:

 

 

Com isso terminamos esta parte do artigo. Já temos a nossa classe persistente criada, a API REST publicada e uma aplicação em flask consumindo esta API com a biblioteca requests para realizar a manutenção básica (CRUD) nos nossos registros.

 

Até a próxima!

Comentarios (0)1
Inicie sesión o regístrese para continuar
Resumen
· 12 feb, 2025

InterSystems Community Q&A Monthly Newsletter #45

Top new questions
Can you answer these questions?
#InterSystems IRIS
Migrate to nginx server
By Yehuda Esformes
What causes a broker RESPONSE to have Transfer-Encoding:chunked?
By omer
Intercepting JWT Token in Cookies Instead of Authorization Header in Web Application
By Alessandra Carena
ssldefs.ini file error [Matching SSL server config not found]
By Chiho Han
Error - SFTP connection with ssh key on a server that excludes the rsa-ssh algorithm
By Moussa SAMB
Error encountered while calling an API
By Anthony Decorte
Visual Studio Code eating licenses
By Fabio Care
Can the WebGateway Port changed from i.e. 57773 to 433?
By Ditmar Tybussek
In Studio is there a way to access the code that flags whether a project has unsaved changes? (is there a property that controls the "star" on unsaved projects?)
By Andre Ribera
We are looking for access to some IRIS database to test our DataAI.link system
By Irina Yaroshevskaya
To configure VSCode as Studio for Intersystems
By Manoj R
Where is InterSystems IRIS Download for Windows?
By Irina Yaroshevskaya
Change %Response.ContentLength
By omer
How to remove line from a XML file
By Smythe Smythee
trying to put the SYSMGR global into a readable string
By JIM WHEELER
CPU and Memory utilization per namespace and business component
By Frank Jackson
how i can connect to cache database from visual studio 2017-2022?
By isayas mola
Sorting, remove duplicate and count of Json file
By Sandeep
Syncronizing Productions between DEV environments
By Sean Brady
Track the global set location
By Ashok Kumar
#Health Connect
#InterSystems IRIS for Health
Application Error Question - Error Message... buildRuntimePathFromIndex+135^EnsLib.EDI.X12.Document...
By Patty Aguirre-Romero
Flask, Iris Container and NGINX?
By John McBride
Intersystems Reports (Logi Reports) - Does it merge multiple PDFs?
By Suzy Green
Trakcare/Clinical Viewer, making chart changes when only have LDAP users
By Serena Judge
IRIS Report Designer
By Muhammad Shahid
FHIR Server return a 200 200 HTTP status
By Ilenia Centonze
Python Iris.CreateIRIS generates connection error
By John McBride
iris-healthtoolkit-service
By Stanislav Budulych
VS CODE Search Options
By RKumar
FHIR server: logical reference that makes MalformedRelativeReference
By christopheS
Need Help to do a connection Between IRIS and SAP RFC
By Mariam Chaaban
How do you debug embedded python (Docker Container) in VSCode
By John McBride
How to use DTL remove property for a repeating segment in for each loop for target using copy
By Mark OReilly
How to iterate over HL7 field repetitions in routing rule?
By Will
Transforming a FHIR Response to SDA – Handling Task Resource
By Ali Chaib
Iris is frozen - discover why
By Phillip Wu
#Caché
#Ensemble
#Other
#HealthShare
#45Monthly Q&A fromInterSystems Developers
Artículo
· 12 feb, 2025 Lectura de 10 min

Utilizando API REST, Flask e IAM com o InterSystems IRIS - Parte 1 – API REST

Utilizando Flask, API REST e IAM com o InterSystems IRIS

Parte 1 – API REST

 

Olá,

Neste artigo vamos ver a implementação de uma API REST para realizar a manutenção de um CRUD, utilizando o Flask e o IAM.

Nesta primeira parte do artigo vamos ver a construção e publicação da API REST no Iris.

Primeiro, vamos criar a nossa classe persistente para armazenar os dados. Para isso vamos para o Iris e criamos nossa classe:

Class ERP.Cliente Extends (%Persistent, %Populate, %XML.Adaptor)

{

 

Property nome As %String;

 

Property idade As %Integer;

 

}

 

Pronto. Já temos a nossa classe persistente criada e pronta para receber dados. Agora vamos criar a nossa API REST.

Quando falamos em REST estamos falando do protocolo HTTP e seus verbos. Os verbos HTTP são métodos que definem a operação que o cliente quer fazer. Alguns exemplos de verbos HTTP são: 

  • GET: Solicita um recurso específico e retorna apenas dados. É o padrão para enviar dados quando se submete um formulário HTTP. 
  • POST: Submete dados a um recurso, alterando estados de um recurso presente no servidor. É utilizado para enviar informações para serem processadas, como criar um produto ou um cliente. 
  • HEAD: Similar ao método GET, entretanto não requer o corpo da resposta. 
  • PUT: Substitui todas as atuais representações do recurso de destino pela carga de dados da requisição. 
  • DELETE: Exclusão. 

Como resposta aos verbos temos os códigos de status indicam o resultado da requisição. Por exemplo, 200 indica que a requisição foi bem-sucedida.

O Iris implementa REST de uma maneira bastante fácil e robusta. A documentação a seguir traz todas as informações necessárias para a criação de uma API REST: https://docs.intersystems.com/irislatest/csp/docbook/DocBook.UI.Page.cls?KEY=GREST

Vamos então montar o código da nossa API REST para realizar a manutenção básica na nossa classe ERP.Cliente. para isso vamos criar uma classe que estende de %CSP.REST:

Class Rest.Servico Extends %CSP.REST

{

 

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>

}

 

ClassMethod Incluir() As %Status

{

             

              Do ##class(%REST.Impl).%SetContentType("application/json")

             

    Set payload = %request.Content.Read()

    Set objJSON=##Class(%DynamicAbstractObject).%FromJSON(payload)

       

    Set objCliente=##Class(ERP.Cliente).%New()

    Set objCliente.nome=objJSON.nome

    Set objCliente.idade=objJSON.idade

    Set st=objCliente.%Save()

    If 'st

    {

                  Do ##class(%REST.Impl).%SetStatusCode("404") Quit $$$OK

 

    }

   

              Do ##class(%REST.Impl).%SetStatusCode("200")

 

    return $$$OK

}

 

ClassMethod Alterar(chave As %Integer) As %Status

{

             

              Do ##class(%REST.Impl).%SetContentType("application/json")

 

    Set payload = %request.Content.Read()

    Set objJSON=##Class(%DynamicAbstractObject).%FromJSON(payload)

       

    Set objCliente=##Class(ERP.Cliente).%OpenId(chave)

    If '$IsObject(objCliente)

    {

                  Do ##class(%REST.Impl).%SetStatusCode("404") Quit $$$OK

 

    }    

   

    Set objCliente.nome=objJSON.nome

    Set objCliente.idade=objJSON.idade

    Set st=objCliente.%Save()

    If 'st

    {

                  Do ##class(%REST.Impl).%SetStatusCode("500") Quit $$$OK

 

    }   

   

              Do ##class(%REST.Impl).%SetStatusCode("200")

 

    return $$$OK

}

 

ClassMethod Deletar(chave As %Integer) As %Status

{

              Do ##class(%REST.Impl).%SetContentType("application/json")

       

    Set st=##Class(ERP.Cliente).%DeleteId(chave)

    If 'st

    {

                  Do ##class(%REST.Impl).%SetStatusCode("404") Quit $$$OK

 

    }   

   

              Do ##class(%REST.Impl).%SetStatusCode("200")

 

    return $$$OK

}

 

ClassMethod Pesquisar(chave As %Integer) As %Status

{

       

    Do ##class(%REST.Impl).%SetContentType("application/json")

             

    Set objCliente=##Class(ERP.Cliente).%OpenId(chave)

    If '$IsObject(objCliente)

    {

                  Do ##class(%REST.Impl).%SetStatusCode("404") Quit $$$OK

 

    }

   

              Do ##class(%REST.Impl).%SetStatusCode("200")   

   

    Set objJSON={}   

    Set objJSON.id=chave

    Set objJSON.nome=objCliente.nome

    Set objJSON.idade=objCliente.idade

             

              Write objJSON.%ToJSON() 

 

    return $$$OK

}

 

ClassMethod Listar() As %Status

{

              Do ##class(%REST.Impl).%SetContentType("application/json")          

                                         

              Set result=##class(%ResultSet).%New("%DynamicQuery:SQL")

 

              Set st=result.Prepare("select id, nome, idade from ERP.Cliente")

    If 'st

    {

                  Do ##class(%REST.Impl).%SetStatusCode("500") Quit $$$OK

 

    }        

              Set st=result.Execute()

   

    Set objJSON={}

    Set clientes=[]

             

              While result.Next(.st) {

                           

                            Set objCliente={}

                            Set objCliente.id=result.%Get("ID")                                        

                            Set objCliente.nome=result.%Get("nome")          

                            Set objCliente.idade=result.%Get("idade")           

                            Do clientes.%Push(objCliente)

              }

       

              Do ##class(%REST.Impl).%SetStatusCode("200")

             

              Set saida={}

              Set saida.clientes=clientes

             

              Write saida.%ToJSON()

 

    return $$$OK

}

 

}

Note a parte do código que define as URLs (UrlMap) onde nós temos a URL chamada, o verbo (Method) acionado e o método do código que deve ser chamado. Fica muito fácil entender cada uma das chamadas realizadas e a associação da chamada com o verbo HTTP.

Agora que criamos a nossa classe vamos configurar uma aplicação web no íris para que esta aplicação faça o serviço REST que desejamos disponibilizar. Para isso vamos no Portal de Administração->Administração do Sistema->Segurança->Aplicações->Aplicações Web e vamos criar uma nova aplicação:

 

Informe o nome da aplicação (/rest/servico), o Namespace onde a classe REST foi criada, marque a caixa Ativar aplicativo. Selecione a opção REST e informe a classe de Dispatch (Rest.Servico). Marque a opção Senha em Métodos para Autenticação e salve a configuração.

Nossa classe REST está publicada e pronta para ser consumida. Simples assim!

Vamos utilizar o Postman para fazer alguns testes na nossa API. O primeiro teste é verificar se conseguimos recuperar a lista de clientes.

Vamos abrir o Postman, e na barra de endereços vamos informar a URL da nossa API: http://<ip_addr>/<config_iris>/rest/servico/cliente. Informe na aba Authorization os dados de autenticação (usuário e senha) para acessar a API:

 

 

Agora selecione o verbo desejado, GET, e envie a solicitação. Esta configuração vai fazer com que seja acionado o método Listar. E temos então, como resposta, um status HTTP 200 e a lista de clientes.

Podemos realizar uma inclusão com a chamada utilizando o verbo POST e criando um body para a nossa requisição. Para isso vá para a aba Body e informe o payload que será enviado (no nosso exemplo {"nome":"Pierre", "idade":"45"}). Clique em Enviar e veja a resposta (HTTP status 200):

 

 

Agora temos o registro do Pierre criado na nossa classe. Podemos buscar o registro com o GET passando o número do ID do registro:

Note que agora, na URL, informamos o ID do registro desejado. Isso faz com que nossa API chame o método Pesquisar.

Assim temos a nossa classe persistente criada, a nossa API REST desenvolvida e publicada no íris, podendo ser consumida com segurança.

Na próxima parte deste artigo vamos ver como podemos consumir esta API através de uma aplicação FLASK.

Comentarios (0)1
Inicie sesión o regístrese para continuar
Artículo
· 12 feb, 2025 Lectura de 4 min

Using REST API, Flask and IAM with InterSystems IRIS - Part 3 – IAM

Using Flask, REST API, and IAM with InterSystems IRIS

Part 3 – IAM

 

InterSystems API Manager (IAM) is a component that allows you to monitor, control, and manage traffic from HTTP-based APIs. It also acts as an API gateway between InterSystems IRIS applications and servers.

The document published in https://docs.intersystems.com/irislatest/csp/docbook/DocBook.UI.Page.cls?KEY=PAGE_apimgr provides information about the product.

 

The document https://docs.intersystems.com/components/csp/docbook/DocBook.UI.Page.cls?KEY=CIAM3.0_install provides all the information for the installation and configuration of IAM.

 

After installing IAM we will activate it and configure a service, route and plugin to create a Rate Limiting for our REST API.

 

First, after installing IAM we will activate it as defined in the documentation:

 

 

Once IAM is activated, we will open the administration interface to create the necessary service, route and plugin. For this in the browser we access the server on port 8002:

 

 

On this screen we see the service, route and plugin maintenance options, which are the tasks we are going to perform. First we will create the service to serve our REST API. Click on the side menu on Services and then on New Service:

 

 

Enter the name (client-service) and in the Add using URL option, enter the API path in URL (http://192.168.0.13/iris/rest/servico/cliente in our example). Click Create and the service is created:

 

 

Now let's create the route. In the side menu, click on Routes, then on New Route.

 

 

 

Select the service we created, enter a name for the route (client-route for example), inform the protocols that can be used (http and https), enter the host (192.168.0.13) and the methods (GET, PUT, POST, DELETE). Click the Add Path link and enter the path for this route (/api/client). Click Create and the route is created:

 

 

 

 

 

 

 

Now let's create the Limiting rate plugin. This plugin limits the number of requests a user can make in a given period of time. To do this, go back to the side menu and click on Plugins and then on New Plugin. In the search box, type Rate and see the plugins listed:

 

 

 

Select the Rate Limiting Advanced plugin. The plugin configuration screen will be presented:

 

 

 

 

On the setup screen, change the option to Scoped. Select the service we created. Enter the number of accesses in Config.Limit (5 for example) and the interval time in Config.Window.Size (60 for example). Change Config.Strategy to Local, and then click Create. Ready. Our plugin is created and already working:

 

 

 

Now we'll need to make a change to our python code to consume our API through IAM. To do this, let's change the API URL address to the address we created in the IAM Route:

 

API_URL = "http://192.168.0.13/iris/rest/servico/cliente" - Original Code

 

API_URL = "http://192.168.0.13:8000/api/cliente" - New URL going through IAM

Reactivate the Flask server and return to the application page. This time give a refresh sequence (F5) in order to call the API several times. See that in the 6th API call we have a failure:

 

 

Our application is not prepared to handle the failed HTTP status. Let's make some adjustments. First let's create an error page in the templates folder called erro.html:

 

<! html DOCTYPE>

<html lang="en-us">

<head>

    <meta charset="UTF-8">

    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <title>Error</title>

</head>

<body>

    <h1>An error has occurred!</h1>

    <p>Error code: {{ status_code }}</p>

    <p>Error message: {{ error_message }}</p>

</body>

</html>

 

Let's go back to the python code and make an adjustment to catch the error. In the section we call the index page assembly, we'll treat an HTTP code other than 200:

 

Where we have the following code in the route "/":

 

    date = response.json()

    list = date["customers"]

    return render_template("index.html", records=list)

 

We changed to:

 

  if response.status_code == 200:

        date = response.json()

        list = date["customers"]

        return render_template("index.html", records=list)

  else:

        return render_template('erro.html', status_code=response.status_code, error_message=response.json().get('message', 'Unknown Error'))

 

Let's restart the Flask application and once again we'll call the API several times. This time we will get a handled error screen:

 

 

 

We can then see that IAM is already working, receiving the requests and applying the configured plugins. According to our configuration, IAM restricted access to the API by returning an HTTP status of 429 as configured in the plugin.

 

Going back to the administration screen in IAM we can already see some information about the consumption of the service:

 

 

We can see the number of requests that have been made to the service by HTTP Status for example. We can also change the way the graph is displayed:

 

 

IAM is a powerful tool that adds several advantages to Iris and allows a series of actions with its plugins. IAM can be a powerful ally for publishing services.

 

See you next time!

Comentarios (0)1
Inicie sesión o regístrese para continuar
Comentarios (0)1
Inicie sesión o regístrese para continuar