Integracao REST end-to-end com TLPP
Tutorial: criar endpoint REST em TLPP, consumir API externa, autenticacao com token, error handling. Caso de uso real de integracao.
Vamos criar uma integracao real: um endpoint REST em TLPP que recebe pedido, consulta servico externo de credito, e responde com aprovado/recusado. Cobre 90% das integracoes do dia-a-dia.
1. Habilitar HTTP no appserver.ini
[HTTPV11]
ENABLE=1
PORT=8080
INSTANCES=1,2
INSTANCENAME=APIREST2. Escrever o endpoint TLPP
#include 'tlpp-core.th'
#include 'tlpp-rest.th'
namespace archtec.api
@Post('/v1/pedidos/validar')
function ValidaPedido()
local cBody as character
local oReq as object
local oResp as object
local cToken as character
local lOk as logical
// 1. Autenticacao
cToken := httpRequest:getHeader('Authorization')
if !ValidaToken(cToken)
httpResponse:setStatus(401)
httpResponse:setBody('{"error":"unauthorized"}')
return
endif
// 2. Parse do body
try
cBody := httpRequest:getBody()
oReq := JsonObject():new()
oReq:fromJson(cBody)
catch tExceptionError oErr
httpResponse:setStatus(400)
httpResponse:setBody('{"error":"invalid_json"}')
return
endtry
// 3. Logica de negocio (consulta credito externo)
oResp := JsonObject():new()
oResp['cliente'] := oReq['cliente']
oResp['aprovado'] := ConsultaCredito(oReq['cliente'], oReq['valor'])
oResp['timestamp'] := DToS(Date()) + Time()
oResp['tx_id'] := FwUuidV4()
// 4. Responder
httpResponse:setStatus(200)
httpResponse:setContentType('application/json')
httpResponse:setBody(oResp:toJson())
return3. Validador de token
static function ValidaToken(cAuth as character) as logical
local cToken as character
if !'Bearer ' $ cAuth
return .F.
endif
cToken := substr(cAuth, 8)
// Verifica contra tabela ZAP (api keys)
return !empty(Posicione('ZAP', 1, xFilial('ZAP') + cToken, 'ZAP_COD'))4. Cliente HTTP pra consultar API externa
static function ConsultaCredito(cCliente as character, nValor as numeric) as logical
local oClient as object
local oResp as object
local cBody as character
oClient := FwHttpClient():new('https://credito-externo.com/api/check')
oClient:setHeader('Authorization', 'Bearer ' + GetMv('MV_CREDIT_KEY', .F., ''))
oClient:setHeader('Content-Type', 'application/json')
oClient:setBody('{"doc":"' + cCliente + '","valor":' + cValToChar(nValor) + '}')
oClient:setSocketTimeout(10000) // 10s
try
if oClient:post()
cBody := oClient:getHTTPResponse():getHTTPResponse()
oResp := JsonObject():new()
oResp:fromJson(cBody)
return oResp['status'] == 'approved'
endif
catch tExceptionError oErr
FwLogger():getLogger():error('Credito API: ' + oErr:getDescription())
endtry
return .F. // falha = nao aprovado5. Testar com curl
curl -X POST http://localhost:8080/v1/pedidos/validar \
-H 'Authorization: Bearer SEU_TOKEN' \
-H 'Content-Type: application/json' \
-d '{"cliente":"00000000000191","valor":15000}'
# Esperado:
# {"cliente":"00000000000191","aprovado":true,"timestamp":"...","tx_id":"..."}6. Pegadinhas de producao
- Timeout curto: API externa lenta trava sua thread — sempre setSocketTimeout
- Retry com backoff: pra APIs flaky, implementar 2-3 retries
- Rate limit cliente-side: nao chamar 1000x/seg APIs externas — quebra a conta
- Logs estruturados: FwLogger com tx_id pra correlacao
- Circuit breaker: se API esta caida, parar de tentar por X minutos