Page edited by Mauricio Rogerio Obenaus Datasul REST - API - URL Para acessar uma API pelo serviço REST a URL da API padrão é formada da seguinte dorma: /datasul-rest/resources/api/[caminho da api], onde, por exemplo se a api chamada for /fch/fchdis/fchdis0035.p fica /datasul-rest/resources/api/fch/fchdis/fchdis0035, porem, as API´s podem ser formatadas com nomes de procedure específicas para customizar a apresentação da API pelo serviço REST, por exemplo se na procedure houver um metodo que o o nome inicia por REST_NAME_ o restante do nome deste metodo será utlizada como endpoit para esta api, por exemplo, se na fchdis0035.p houver um metodo chamado REST_NAME_user, a API será acessivel apenas pela URL /datasul-rest/resources/api/user. PROCEDURE REST_NAME_user: END PROCEDURE. <application xmlns="http://wadl.dev.java.net/2009/02"> <grammars> <include href="application.wadl/xsd0.xsd"> <doc title="Generated" xml:lang="en"/> </include> </grammars> <resources base="http://localhost:8080/datasul-rest/resources/api/"> <resource path="/user"> . . . Datasul REST - API - Metodos Para uma API padrão, todos os metodos são disponibilizados para o serviço REST, mas como não há especificação de como os paramatros são tratados, todos os metodos são chamados via POST. Por exemplo abaixo para o programa progress abaixo: PROCEDURE parametros: DEFINE INPUT PARAMETER charinput AS CHARACTER NO-UNDO. END PROCEDURE. O WADL será correspondente será: <resource path="parametros"> <method id="parametros" name="POST"> <request> <param xmlns:xs="http://www.w3.org/2001/XMLSchema" name="charinput" style="query" type="xs:string" default="0"/> </request> <response> <ns2:representation xmlns:ns2="http://wadl.dev.java.net/2009/02" xmlns=" " element="Return" mediaType="application/json"/> </response> </method> </resource> Para permitir utilizar os outros metodos HTTP (PUT,GET, DELETE) os metodos da API devem ser nomeados começando como REST_PUT_, REST_GET_ e REST_DELETE_ respectivamente e o restante do nome do metodo identifica o path para chegar no metodo. Quando a API tem algum metodo nomeado como REST_ apenas os metodos com REST_ será acessiveis pelo serviço REST. Os metodos com nome REST_GET, REST_PUT, REST_POST e REST_DELETE, serão acessiveis na raiz do serviço. Segue abaixo uma tabela de nomes de metodo exemplo e suas respectivas URL´s, considerando o exemplo do fchdis0035 com o metodo REST_NAME_user definindo o nome do serviço. Nome do MetodoURL onde está disponívelMetodo HTTP REST_GEThttp://localhost:8080/datasul-rest/resources/api/userGET REST_POSThttp://localhost:8080/datasul-rest/resources/api/userPOST REST_PUThttp://localhost:8080/datasul-rest/resources/api/userPUT REST_DELETEhttp://localhost:8080/datasul-rest/resources/api/userDELETE REST_GET_blockedusershttp://localhost:8080/datasul-rest/resources/api/user/blockedusersGET REST_PUT_unlockuser http://localhost:8080/datasul-rest/resources/api/user/unlockuser PUT REST_POST_changepassword http://localhost:8080/datasul-rest/resources/api/user/changepassword POST REST_DELETE_user http://localhost:8080/datasul-rest/resources/api/user/user DELETE Datasul REST - API - Parâmetros O serviço de API permite que sejam utilizados os seguintes tipos de dados do progress como parametros INPUT, OUTPUT ou INPUT-OUTPUT de procedures: CHARACTER, com e sem extent, com extents definidos ou não. INTEGER, com e sem extent, com extents definidos ou não. DECIMAL, com e sem extent, com extents definidos ou não. LOGICAL, com e sem extent, com extents definidos ou não. DATE, com e sem extent, com extents definidos ou não. DATETIME, com e sem extent, com extents definidos ou não. DATETIME-TZ, com e sem extent, com extents definidos ou não. INT64, com e sem extent, com extents definidos ou não. LONGCHAR, apenas sem extent. ROWID, com e sem extent, com extents definidos ou não. RAW, com e sem extent, com extents definidos ou não. TEMP-TABLE. Parâmetros para API padrão Vamos considerar o seguinte codigo para typos.p: PROCEDURE parametros: DEFINE INPUT PARAMETER charinput AS CHARACTER NO-UNDO. END PROCEDURE. O WADL será correspondente será: <resource path="parametros"> <method id="parametros" name="POST"> <request> <param xmlns:xs="http://www.w3.org/2001/XMLSchema" name="charinput" style="query" type="xs:string" default="0"/> </request> <response> <ns2:representation xmlns:ns2="http://wadl.dev.java.net/2009/02" xmlns=" " element="ReturnString" mediaType="application/json"/> </response> </method> </resource> Este metodo será acessivel atraves da URL http://localhost:8080/datasul-rest/resources/api/typos/parametros?charinput=teste usando o metodo HTTP POST. O retorno é um JSON do tipo Return, e nesse caso apenas retorna o seguinte conteudo: { "messages": [], "length": null, "data": {} } Vamos inluir um parametro de saida para o metodo: PROCEDURE parametros: DEFINE INPUT PARAMETER charinput AS CHARACTER NO-UNDO. DEFINE OUTPUT PARAMETER charout AS CHARACTER NO-UNDO. ASSIGN charout = "Olá mundo REST: " + charinput. END PROCEDURE. O WADL será correspondente será: <resource path="parametros"> <method id="parametros" name="POST"> <request> <param xmlns:xs="http://www.w3.org/2001/XMLSchema" name="charinput" style="query" type="xs:string" default="0"/> </request> <response> <ns2:representation xmlns:ns2="http://wadl.dev.java.net/2009/02" xmlns=" " element="ReturnString" mediaType="application/json"/> </response> </method> </resource> Note que o response mudou o element de Return para ReturnString. Este metodo continua sendo acessivel atraves da URL http://localhost:8080/datasul-rest/resources/api/typos/parametros?charinput=teste usando o metodo HTTP POST. Porem no retorno, estara disponível o parametro de saida: { "messages": [], "length": null, "data": {"charout": "Olá mundo REST: teste"} } Então o atributo data contera um objeto JSON onde existirá um atributo com o nome do parametro de saida e seu respectivo valor. Por exemplo, se houver mais um parametro de saida: PROCEDURE parametros: DEFINE INPUT PARAMETER charinput AS CHARACTER NO-UNDO. DEFINE OUTPUT PARAMETER charout1 AS CHARACTER NO-UNDO. DEFINE OUTPUT PARAMETER charout2 AS CHARACTER NO-UNDO. ASSIGN charout1 = "Olá mundo REST: " + charinput. charout2 = "Adeus mundo REST: " + charinput. END PROCEDURE O retorno no WADL muda no response de ReturnString para Returntyposparametros, se consultarmos o XSD deste WADL temos a seguinte definição para este element: ... <xs:element name="Returntyposparametros" type="returntyposparametrosVO"/> <xs:complexType name="returntyposparametrosVO"> <xs:sequence> <xs:element name="messages" type="message" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="length" type="xs:int" minOccurs="0"/> <xs:element name="data" type="outtyposparametrosVO" minOccurs="0"/> </xs:sequence> </xs:complexType> <xs:complexType name="outtyposparametrosVO"> <xs:sequence> <xs:element name="charout1" type="xs:string" minOccurs="0"/> <xs:element name="charout2" type="xs:string" minOccurs="0"/> </xs:sequence> </xs:complexType> ... E o resultado da chamada o retorno é um JSON com um objeto onde cada atributo é um parametro com o seu respectivo valor. { "messages":[], "length": null, "data": { "charout1": "Olá mundo REST: teste", "charout2": "Adeus mundo REST: teste" } } Para parametros entrada com EXTENT, os parametros de query na URL podem ou devem ser repetidos, no caso de parametros EXTENT sem definição de tamanho podem ocorrer zero ou N vezes. Para parametros com EXTENT definidos, os parametros na URL devem aparecer exatamente o numero de vezes definido no EXTENT. Por exemplo: PROCEDURE parametros: DEFINE INPUT PARAMETER charinput AS CHARACTER EXTENT NO-UNDO. END PROCEDURE. A URL pode ser: http://localhost:8080/datasul-rest/resources/api/typos/parametros http://localhost:8080/datasul-rest/resources/api/typos/parametros?charinput=teste1 http://localhost:8080/datasul-rest/resources/api/typos/parametros?charinput=teste1&charinput=teste2 http://localhost:8080/datasul-rest/resources/api/typos/parametros?charinput=teste1&charinput=teste2&charinput=teste3 e assim por diante. Já no caso deste exemplo: PROCEDURE parametros: DEFINE INPUT PARAMETER charinput AS CHARACTER EXTENT 3 NO-UNDO. END PROCEDURE. A URL precisa ter o parametro 3 vezes: http://localhost:8080/datasul-rest/resources/api/typos/parametros?charinput=teste1&charinput=teste2&charinput=teste3 Para parametros de saida com EXTENT, o valor do retorno será um array JSON. Por exemplo para a procedure: PROCEDURE parametros: DEFINE INPUT PARAMETER charinput AS CHARACTER NO-UNDO. DEFINE OUTPUT PARAMETER charout1 AS CHARACTER EXTENT 2 NO-UNDO. ASSIGN charout1[1] = "Olá mundo REST: " + charinput. charout1[2] = "Olá de novo mundo REST: " + charinput. END PROCEDURE. o resultado é: { "messages":[], "length": null, "data": {"charout1": ["Olá mundo REST: teste", "Olá de novo mundo REST: teste"] } Parametros TEMP-TABLE Para parametros do tipo TEMP-TABLE os parametros deverão ser enviados no payload da requisição HTML, por exemplo um parametro de temp-table: DEFINE TEMP-TABLE tt-param NO-UNDO FIELD campo1 AS CHARACTER FIELD campo2 AS INTEGER. PROCEDURE parametros: DEFINE INPUT PARAMETER TABLE FOR tt-param. END PROCEDURE. A URL chamada com POST http://localhost:8080/datasul-rest/resources/api/typos/parametros deverá ter um payload com um array JSON, se não hover registros simplesmente "[]" e caso haja registros: [ {campo1: "teste1", campo2: 34}, {campo1: "teste2", campo2: 35} ] Os campos no objeto não são obrigatórios e geram um campo com valor nulo no progress se não forem enviados. campos a mais não geram erro na chamada, mas são ignorados. Campos EXTENT em TEMP-TABLES devem obrigatoriamente ter tamanho definidos, portanto o valor dos campos deve ser um array com o tamanho exato do EXTENT. Para metodos que tem mais de um parametro de TEMP-TABLE, por exemplo: DEFINE TEMP-TABLE tt-param1 NO-UNDO FIELD campo1 AS CHARACTER FIELD campo2 AS INTEGER. DEFINE TEMP-TABLE tt-param2 NO-UNDO FIELD campo3 AS CHARACTER FIELD campo4 AS INTEGER. PROCEDURE parametros: DEFINE INPUT PARAMETER TABLE FOR tt-param1. DEFINE INPUT PARAMETER TABLE FOR tt-param2. END PROCEDURE. O payload HTTP deve ser no seguinte formato, onde um objeto JSON possui um atributo para cara temp-table: { "tt-param1": [{campo1: "teste", campo2: 34}], "tt-param2": [{campo3: "teste", campo4: 34}] } Os parametros de TEMP-TABLE que são OUPUT ou INPUT-OUTPUT são retornados da mesma forma no atributo data do retorno, se houver for apenas uma temp-table de retorno, alem de RowErrors que tem tratamento especial, é retornado um array JSON com o conteudo da TEMP-TABLE diretamente no atributo data. Novamente, se houver mais de uma parametro de saida, alem de RowErrors, o data será retornado como um objeto JSON, onde cada atributo é um parametro de saida, TEMP-TABLE ou não. Parametros - Query, Template ou Representation Para procedures que foram definidas com metodos com o nome REST_ é possível definir parametros INPUT que serão tratados como Query, Template ou Representation. Parametros Query como já vimos, são os padrões quando não nenhum metodo REST_ definido na procedure, e são passados na URL do serviço como um par parametro=valor separados por &(e comercial) apos o ?(sinal de interrogação). Para definir que um parametro terá como origem a URL o nome do parametro deverá começar como QP_. por exemplo: PROCEDURE REST_POST_parametros: DEFINE INPUT PARAMETER QP_param1 AS CHARACTER NO-UNDO. END PROCEDURE. O metodo é passado na URL: http://localhost:8080/datasul-rest/resources/api/typos/parametros?param1=teste1 Parametros Template, tambem são parametros que são passdos na URL, porem são passados junto no path do serviço, para definir um parametro do tipo template deve se iniciar o nome do parametro com PP_, a ordem dos parametros PP_ interfere no caminho da URL, por exemplo: PROCEDURE REST_POST_parametros: DEFINE INPUT PARAMETER PP_param1 AS CHARACTER NO-UNDO. DEFINE INPUT PARAMETER PP_param1 AS CHARACTER NO-UNDO. END PROCEDURE. O metodo é passado na URL: http://localhost:8080/datasul-rest/resources/api/typos/parametros/valorparametro1/valorparametro2 Nesse caso o PP_param1 recebe o conteudo: valorparametro1 e PP_param2 recebe: valorparametro2 Os parametros do tipo representation são os parametros que são enviados no payload da requisição HTTP. Para INPUT e INPUT-OUTPUT de parametros de tipos simples, se houver apenas um parametro, o payload é o valor do parametro, se for um tipo simples sem EXTENT, se for um EXTENT de tipo simples o payload é um array JSON com os valores. Se houver mais de um parametro o payload deve ser um objeto JSON, onde cada paramatro é um atributo deste objeto com o respectivo valor. Para INPUT e INPUT-OUTPUT de parametros do tipo TEMP-TABLE se houver apenas uma TEMP-TABLE o payload é um array de objetos JSON, onde cada item do array é um registro da TEMP-TABLE e cada atributo destes objetos são os campos da TEMP-TABLE. Para campos EXTENT o valor do campo é um array JSON com o mesmo tamanho do EXTENT. Parametro RowErrors Como mencionado antes, o parametro de OUTPUT da TEMP-TABLE RowErrors tem um tratamento especial, ela deve ter a assinatura da RowErrors padrão das DBO´s do Datasul e quando retornada, irá alimentar o atributo messages do Return. Não é necessário fazer nenhum tratamento, apenas retornar os erros em RowErrors conforme o padrão DBO. Parametro REST_count O parametro de OUTPUT REST_count do tipo INTEGER tem um tratamento especial, quando existir, irá alimentar o atributo length do Return. Não é necessário fazer nenhum tratamento. UPLOAD A API permite que seja feito upload de arquivos para o progress, para um serviço permitir o upload de arquivos, o programa progress deve ter um metodo com o nome iniciado com REST_UPLOAD_ ou nome deve ser REST_UPLOAD (se o upload for feito no POST da raiz do servico). este metodo deverá ser chamado no datasul-rest utilizando o metodo HTTP POST e o Content-Type do Payload deverá ser um "multipart/form-data" que caracteriza um FORM em HTML. Neste FORM da requisição o arquivo e enviado para parametros específicos do metodo (opcionais) que são: UP_[nome do parametro do arquivo] - parametro INPUT do tipo LONGCHAR que recebe o conteudo do arquivo codificado em BASE64. FN_[nome do parametro do arquivo] - parametro INPUT do tipo CHARACTER que recebe o nome do arquivo selecionado no FORM. MT_[nome do parametro do arquivo] - parametro INPUT do tipo CHARACTER que recebe o MediaType detectado pelo browser para o arquivo selecionado no FORM. Podem ser recebidos outros parametros no metodo, se iniciarem por QP_ serão query parametros de query, se forem PP_ serão parametros de Path. Parametros de tipos primitivos não iniciados por QP_ ou PP_ devem ser enviados como campos do FORM. por exemplo: Exemplo UPLOAD progress PROCEDURE REST_UPLOAD_upload: DEFINE INPUT PARAMETER FN_arquivo AS CHARACTER NO-UNDO. DEFINE INPUT PARAMETER MT_arquivo AS CHARACTER NO-UNDO. DEFINE INPUT PARAMETER UP_arquivo AS LONGCHAR NO-UNDO. DEFINE INPUT PARAMETER usernamevalue AS CHARACTER NO-UNDO. DEFINE VARIABLE memo AS MEMPTR NO-UNDO. ASSIGN memo = BASE64-DECODE(UP_arquivo). COPY-LOB FROM memo TO FILE "c:\temp\" + FN_arquivo NO-CONVERT. SET-SIZE(memo) = 0. MESSAGE "FN_arquivo" FN_arquivo skip "MT_arquivo" MT_arquivo skip "usernamevalue" usernamevalue SKIP VIEW-AS ALERT-BOX INFO BUTTONS OK. END PROCEDURE. Nesse exemplo o parametro FN_file recebe o nome do arquivo selecionado pelo usuario, MT_file recebe o MediaType do arquivo e UP_file recebe o conteudo do arquivo codificado em BASE64, como pode ser visto do exemplo para extrair o contudo binario do conteudo do arquivo codificado, deve ser utilizado uma variavel MEMPTR em conjunto da função BASE64-DECODE, para gravar este arquivo no sistema operacional podemos utilizar o comando COPY-LOB. Tambem exemplificamos neste exemplo um parametro que pode vir como um campo do formulario. A pagina HTML de exemplo que chama esse metodo e faz o upload de arquivos é o seguinte: Exemplo de HTML para UPLOAD <!doctype html> <html> <head> <title>UPLOAD</title> </head> <body> <form action="http://localhost:8080/datasul-rest/resources/api/imagem/upload" method="POST" enctype="multipart/form-data"> Selecione um arquivo: <input type="file" name="arquivo"/> <br> Informe um nome de usuario: <input type="input" name="usernamevalue"/> <br> <input type="submit" value="Upload"/> </form> </body> </html> Notem que nesse caso, o input com type="file" indica para o browser que ele deve enviar o arquivo via upload, nesse input a propriedade name="arquivo" indica o nome do campo do formulario que indica o arquivo, esse nome deve ser o mesmo definido no nome dos parametros da API em [nome do parametro do arquivo], nesse exemplo (UP|FN|MT)_arquivo. O input adicionar com parametro name="usernamevalue" será recebido no metodo no parametro com seu respectivo nome. O retorno deste metodo segue a mesma regra dos outros metodos da API. View Online · View Changes Online Continue reading...