Inicia a declaração de um método de Web Services (Client e/ou Server) em AdvPL.
Abrangência
ERP 11 e superiores
Sintaxe
Parâmetros
Nome | Tipo | Descrição | Obrigatório | Referência |
cVerb | - | PUT, POST, GET ou DELETE | X | |
cId | Caracter | ID para diferenciar e possibilitar a criação de métodos que utilizam verbos http repetidos | ||
cDescription | Caracter | Descrição do método REST | X | |
cSintax | Caracter | Sintaxe HTTP da chamada REST. Esta informação é utilizada apenas para documentação do REST. | ||
cPath | Caracter | Definição do endpoint que irá acionar aquele método. *Pode conter agrupamento, o nome da classe e os pathparms. (A partir da release 12.1.23 da lib, em jan./2019). | ||
cTTalkVersion | Caracter | Valor "v1" para sinalizar que o método utiliza o padrão de mensagem de erro do TTALK. | ||
QueryParms | - | Indica os parâmetros, separados por vírgulas, que este método receberá via QueryString. O parâmetros indicados aqui devem ser declarados como WSDATA. | ||
PathParms | - | Indica os parâmetros, separados por vírgulas, que este método receberá via path, ou seja, como parte da URL. | ||
HeaderParms | - | Indica os parâmetros, separados por vírgulas, que este método receberá via Header na requisição HTTP. | ||
WsRestFul | Caracter | Indica o nome da classe, do serviço, que o método atual pertence. | X |
Observações
- Todo método deve retornar um valor lógico indicando se houve sucesso ou falha na execução do método. Em caso de falha deve-se especificar o motivo da falha através da função SetRestFault.
- Somente as operações PUT, POST, GET e DELETE estão disponíveis como métodos REST.
- O último parâmetro WSRESTFUL pode ser encontrado também como WSSERVICE ou WSREST. O comportamento é o mesmo nos 3 casos.
- O parâmetro QUERYPARAM também pode ser encontrado como WSRECEIVE e também tem o mesmo comportamento.
- O parâmetro cTTalkVersion foi criado para manter a compatibilidade no padrão de mensagem de erro de API's que foram criadas antes da definição do padrão TTALK. Sem essa flag, a mensagem de erro possui as chaves errorCode e errorMessage. Quando é adicionado no método a flag TTALK "v1", o formato fica conforme o guia de API's com as chaves mudadas para code e message, além de outras novas. Link para o guia de implementação de API: http://tdn.totvs.com.br/pages/viewpage.action?pageId=274849083
Exemplo de métodos com verbos repetidos
Na declaração do Serviço REST:
WSMETHOD GET MYLIST DESCRIPTION "Exemplo de retorno de entidade(s)" WSSYNTAX "/samplenew"
WSMETHOD GET MYONE DESCRIPTION "Exemplo de retorno de entidade(s)" WSSYNTAX "/samplenew/{id}" PATH "/{id}"
Na declaração do método:
WSMETHOD GET MYLIST QUERYPARAM startIndex, count WSSERVICE samplenew
Para passar o parâmetro count, por exemplo, poderia ser feita uma requisição no seguinte endereço: http://localhost:8080/rest/samplenew?count=14
Para pegar o valor recebido: Self:count (Valor: 14)
WSMETHOD GET MYONE PATHPARAM id HEADERPARAM cMyHeader WSSERVICE samplenew
Para passar o parâmetro id, por exemplo, poderia ser feita uma requisição no seguinte endereço: http://localhost:8080/rest/samplenew/123
Para pegar o valor recebido: Self:id (Valor: 123)
Na requisição basta incluir no header a chave cMyHeader e passar qualquer valor para que ele fique disponível dentro do método através do comando Self:cMyHeader.
Exemplo de uma classe com diferentes tipos de configuração de path (disponibilizados no release 12.1.23):
#INCLUDE 'totvs.ch'
#INCLUDE "restful.ch"
//-------------------------------------------------------------------
/*/{Protheus.doc} WSRESTFUL
Classe WS para testes genéricos com variedade de exempos de PATH
@author Vinicius Ledesma
@since 05/09/2018
/*/
//-------------------------------------------------------------------
WSRESTFUL thewsclass DESCRIPTION "A Classe WS para testes" FORMAT APPLICATION_JSON
WSDATA pageSize AS INTEGER OPTIONAL
WSDATA page AS INTEGER OPTIONAL
WSDATA thepathparam AS CHARACTER OPTIONAL
WSDATA path1 AS CHARACTER OPTIONAL
WSDATA path2 AS CHARACTER OPTIONAL
WSDATA theheaderparam AS CHARACTER OPTIONAL
WSMETHOD GET DESCRIPTION "Get no modelo antigo WSSYNTAX que não valida agrupamentos e nem path" WSSYNTAX "/thewsclass || /thewsclass/{id}" //Não possibilita utilizar outro GET
WSMETHOD POST ROOT DESCRIPTION "Post sem parâmetro de path" PATH "" //o PATH também poderia ser "/thewsclass"
WSMETHOD POST ID DESCRIPTION "Post com parâmetro de path anonimo" PATH "/thewsclass/{id}" //o PATH poderia ser apenas "/{id}"
WSMETHOD PUT DESCRIPTION "Put com parâmetros de path nomeados" PATH "/{path1}/fixedpart/{path2}"
WSMETHOD DELETE ROOT DESCRIPTION "Delete sem parâmetro de path" PATH "/product/group/thewsclass"
WSMETHOD DELETE ID DESCRIPTION "Delete com parâmetro de path" PATH "/product/group/thewsclass/{id}"
//Version 2
//Se precisasse criar a versão 2 do GET seria necessário mudar para o modelo novo criando quatro métodos com o path definidos, dois(um para lista e um específico com id) para versão 1 e mais dois da versão 2
WSMETHOD POST ROOT2 DESCRIPTION "Versão 2 do Post sem parâmetro de path" PATH "/v2/thewsclass" TTALK "v1"
WSMETHOD POST ID_2 DESCRIPTION "Versão 2 do Post com parâmetro de path anonimo" PATH "/v2/thewsclass/{id}" TTALK "v1"
WSMETHOD PUT V2 DESCRIPTION "Versão 2 do Put com parâmetros de path nomeados" PATH "/v2/thewsclass/{path1}/fixedpart/{path2}" TTALK "v1"
WSMETHOD DELETE RT2 DESCRIPTION "Versão 2 do Delete sem parâmetro de path" PATH "/product/group/v2/thewsclass" TTALK "v1"
WSMETHOD DELETE ID2 DESCRIPTION "Versão 2 do Delete com parâmetro de path" PATH "/product/group/v2/thewsclass/{id}" TTALK "v1"
END WSRESTFUL
//-------------------------------------------------------------------
/*/{Protheus.doc} GET
Get no modelo antigo WSSYNTAX que não valida agrupamentos e nem path
@author Vinicius Ledesma
@since 05/09/2018
/*/
//-------------------------------------------------------------------
WSMETHOD GET WSRECEIVE page, pageSize WSSERVICE thewsclass
Local i
// define o tipo de retorno do método
::SetContentType("application/json")
// verifica se recebeu parametro pela URL
// exemplo: http://localhost:8080/thewsclass/1
If Len(::aURLParms) > 0
::SetResponse('{"id":"' + ::aURLParms[1] + '", "name":"thewsclass", "method":"get WSSYNTAX"}')
Else
// as propriedades da classe receberão os valores enviados por querystring
// exemplo: http://localhost:8080/thewsclass?page=1&pageSize=5
DEFAULT ::page := 1, ::pageSize := 5
// exemplo de retorno de uma lista de objetos JSON
::SetResponse('[')
For i := (::pageSize * ::page - ::pageSize + 1) To ::pageSize * ::page
If i > (::pageSize * ::page - ::pageSize + 1)
::SetResponse(',')
EndIf
::SetResponse('{"id":"' + Str(i) + '", "name":"thewsclass", "method":"get WSSYNTAX"}')
Next
::SetResponse(']')
EndIf
Return .T.
//-------------------------------------------------------------------
/*/{Protheus.doc} POST ROOT
Post sem parâmetro de path
@author Vinicius Ledesma
@since 05/09/2018
/*/
//-------------------------------------------------------------------
WSMETHOD POST ROOT WSSERVICE thewsclass
Local cBody
// recupera o body da requisição
cBody := ::GetContent()
::SetResponse('{"name":"thewsclass", "method":"post root"')
If !Empty(cBody)
::SetResponse(',"body":"'+cBody+'"')
Endif
::SetResponse('}')
Return .T.
//-------------------------------------------------------------------
/*/{Protheus.doc} POST ID
Post com parâmetro de path anonimo
@author Vinicius Ledesma
@since 05/09/2018
/*/
//-------------------------------------------------------------------
WSMETHOD POST ID WSSERVICE thewsclass
::SetResponse('{"id":"' + ::aURLParms[1] + '", "name":"thewsclass", "method":"post id"}')
Return .T.
//-------------------------------------------------------------------
/*/{Protheus.doc} PUT
Put com parâmetros de path nomeados
@author Vinicius Ledesma
@since 05/09/2018
/*/
//-------------------------------------------------------------------
WSMETHOD PUT PATHPARAM path1, path2 WSSERVICE thewsclass
::SetResponse('{"path1":"' + ::path1 + '","path2":"' + ::path2 + '", "urlparm1":"' + ::aURLParms[1] + '","urlparm2":"' + ::aURLParms[2] + '","name":"thewsclass", "method":"put twoparms"}')
Return .T.
//-------------------------------------------------------------------
/*/{Protheus.doc} DELETE ROOT
Delete sem parâmetro de path
@author Vinicius Ledesma
@since 05/09/2018
/*/
//-------------------------------------------------------------------
WSMETHOD DELETE ROOT WSSERVICE thewsclass
::SetResponse('{"name":"thewsclass", "method":"delete root"}')
Return .T.
//-------------------------------------------------------------------
/*/{Protheus.doc} DELETE ROOT
Delete com parâmetro de path
@author Vinicius Ledesma
@since 05/09/2018
/*/
//-------------------------------------------------------------------
WSMETHOD DELETE ID WSSERVICE thewsclass
::SetResponse('{"id":"' + ::aURLParms[1] + '", "name":"thewsclass", "method":"delete id"}')
Return .T.
//-------------------------------------------------------------------
/*/{Protheus.doc} POST ROOT2
Versão 2 do Post sem parâmetro de path
@author Vinicius Ledesma
@since 05/09/2018
/*/
//-------------------------------------------------------------------
WSMETHOD POST ROOT2 WSSERVICE thewsclass
Local cBody
// recupera o body da requisição
cBody := ::GetContent()
::SetResponse('{"name":"thewsclass", "method":"post root"')
If !Empty(cBody)
::SetResponse(',"body":"'+cBody+'"')
Endif
::SetResponse(',"version":"2"}')
Return .T.
//-------------------------------------------------------------------
/*/{Protheus.doc} POST ID_2
Versão 2 do Post com parâmetro de path anonimo
@author Vinicius Ledesma
@since 05/09/2018
/*/
//-------------------------------------------------------------------
WSMETHOD POST ID_2 WSSERVICE thewsclass
::SetResponse('{"id":"' + ::aURLParms[1] + '", "name":"thewsclass", "method":"post id","version":"2"}')
Return .T.
//-------------------------------------------------------------------
/*/{Protheus.doc} PUT V2
Versão 2 do Put com parâmetros de path nomeados
@author Vinicius Ledesma
@since 05/09/2018
/*/
//-------------------------------------------------------------------
WSMETHOD PUT V2 PATHPARAM path1, path2 WSSERVICE thewsclass
::SetResponse('{"path1":"' + ::path1 + '","path2":"' + ::path2 + '", "urlparm1":"' + ::aURLParms[1] + '","urlparm2":"' + ::aURLParms[2] + '","name":"thewsclass", "method":"put twoparms"')
::SetResponse(',"version":"2"}')
Return .T.
//-------------------------------------------------------------------
/*/{Protheus.doc} DELETE RT2
Versão 2 do Delete sem parâmetro de path
@author Vinicius Ledesma
@since 05/09/2018
/*/
//-------------------------------------------------------------------
WSMETHOD DELETE RT2 WSSERVICE thewsclass
::SetResponse('{"name":"thewsclass", "method":"delete root"')
::SetResponse(',"version":"2"')
::SetResponse('}')
Return .T.
//-------------------------------------------------------------------
/*/{Protheus.doc} DELETE ID2
Versão 2 do Delete com parâmetro de path
@author Vinicius Ledesma
@since 05/09/2018
/*/
//-------------------------------------------------------------------
WSMETHOD DELETE ID2 WSSERVICE thewsclass
::SetResponse('{"id":"' + ::aURLParms[1] + '", "name":"thewsclass", "method":"delete id"')
::SetResponse(',"version":"2"')
::SetResponse('}')
Return .T.