HTTP Client
📋 Visão Geral
CL_HTTP_CLIENT permite que programas ABAP façam chamadas HTTP/HTTPS para sistemas externos, consumindo APIs REST, Web Services, e outros recursos web.
Casos de uso: - ✅ Consumir APIs REST externas - ✅ Integração com serviços web - ✅ Download de arquivos - ✅ Webhooks e notificações - ✅ Integração com cloud services
🚀 Criar HTTP Client
Método CREATE_BY_URL
DATA: lo_http_client TYPE REF TO if_http_client,
lv_url TYPE string VALUE 'https://api.example.com/users'.
" Criar cliente HTTP
cl_http_client=>create_by_url(
EXPORTING
url = lv_url
ssl_id = 'ANONYM' " Certificado SSL
IMPORTING
client = lo_http_client
EXCEPTIONS
argument_not_found = 1
plugin_not_active = 2
internal_error = 3
OTHERS = 4 ).
IF sy-subrc <> 0.
MESSAGE 'Erro ao criar HTTP client' TYPE 'E'.
ENDIF.
Método CREATE_BY_DESTINATION
Usar destino RFC HTTP (SM59):
DATA: lo_http_client TYPE REF TO if_http_client,
lv_destination TYPE rfcdest VALUE 'Z_HTTP_DEST'.
" Criar via destino RFC
cl_http_client=>create_by_destination(
EXPORTING
destination = lv_destination
IMPORTING
client = lo_http_client
EXCEPTIONS
destination_not_found = 1
internal_error = 2
OTHERS = 3 ).
IF sy-subrc = 0.
WRITE: / '✅ Cliente HTTP criado via destino'.
ENDIF.
Configurar destino em SM59:
1. SM59 → Create
2. RFC Destination: Z_HTTP_DEST
3. Connection Type: G (HTTP Connection)
4. Target Host: api.example.com
5. Path Prefix: /api/v1
🌐 Métodos HTTP
GET
Ler dados:
DATA: lo_http_client TYPE REF TO if_http_client,
lv_response TYPE string.
" Criar cliente
cl_http_client=>create_by_url(
EXPORTING url = 'https://jsonplaceholder.typicode.com/users'
IMPORTING client = lo_http_client ).
" Configurar método GET
lo_http_client->request->set_method( if_http_request=>co_request_method_get ).
" Executar
lo_http_client->send(
EXCEPTIONS
http_communication_failure = 1
http_invalid_state = 2 ).
IF sy-subrc = 0.
" Receber resposta
lo_http_client->receive(
EXCEPTIONS
http_communication_failure = 1
http_invalid_state = 2 ).
IF sy-subrc = 0.
" Obter body da resposta
lv_response = lo_http_client->response->get_cdata( ).
" Status code
DATA(lv_code) = lo_http_client->response->get_status( )-code.
WRITE: / |Status: { lv_code }|.
WRITE: / |Response: { lv_response }|.
ENDIF.
ENDIF.
" Fechar conexão
lo_http_client->close( ).
POST
Enviar dados:
DATA: lo_http_client TYPE REF TO if_http_client,
lv_json_request TYPE string,
lv_json_response TYPE string.
" JSON para enviar
lv_json_request = '{ "name": "João Silva", "email": "joao@example.com" }'.
" Criar cliente
cl_http_client=>create_by_url(
EXPORTING url = 'https://api.example.com/users'
IMPORTING client = lo_http_client ).
" Configurar POST
lo_http_client->request->set_method( if_http_request=>co_request_method_post ).
" Headers
lo_http_client->request->set_header_field(
name = 'Content-Type'
value = 'application/json' ).
" Body
lo_http_client->request->set_cdata( lv_json_request ).
" Enviar
lo_http_client->send( ).
lo_http_client->receive( ).
" Resposta
lv_json_response = lo_http_client->response->get_cdata( ).
DATA(lv_status) = lo_http_client->response->get_status( )-code.
IF lv_status = 201. " Created
WRITE: / '✅ Usuário criado com sucesso'.
ELSE.
WRITE: / |❌ Erro: { lv_status }|.
ENDIF.
lo_http_client->close( ).
PUT
Atualizar dados:
DATA: lo_http_client TYPE REF TO if_http_client,
lv_json TYPE string.
lv_json = '{ "name": "João Silva Updated", "email": "joao.new@example.com" }'.
cl_http_client=>create_by_url(
EXPORTING url = 'https://api.example.com/users/1'
IMPORTING client = lo_http_client ).
" PUT
lo_http_client->request->set_method( if_http_request=>co_request_method_put ).
lo_http_client->request->set_header_field(
name = 'Content-Type'
value = 'application/json' ).
lo_http_client->request->set_cdata( lv_json ).
lo_http_client->send( ).
lo_http_client->receive( ).
DATA(lv_status) = lo_http_client->response->get_status( )-code.
IF lv_status = 200.
WRITE: / '✅ Usuário atualizado'.
ENDIF.
lo_http_client->close( ).
DELETE
Deletar dados:
DATA: lo_http_client TYPE REF TO if_http_client.
cl_http_client=>create_by_url(
EXPORTING url = 'https://api.example.com/users/1'
IMPORTING client = lo_http_client ).
" DELETE
lo_http_client->request->set_method( if_http_request=>co_request_method_delete ).
lo_http_client->send( ).
lo_http_client->receive( ).
DATA(lv_status) = lo_http_client->response->get_status( )-code.
IF lv_status = 204. " No Content
WRITE: / '✅ Usuário deletado'.
ENDIF.
lo_http_client->close( ).
🔐 Autenticação
Basic Authentication
DATA: lo_http_client TYPE REF TO if_http_client,
lv_username TYPE string VALUE 'admin',
lv_password TYPE string VALUE 'password123'.
cl_http_client=>create_by_url(
EXPORTING url = 'https://api.example.com/data'
IMPORTING client = lo_http_client ).
" Autenticação básica
lo_http_client->authenticate(
username = lv_username
password = lv_password ).
lo_http_client->request->set_method( if_http_request=>co_request_method_get ).
lo_http_client->send( ).
lo_http_client->receive( ).
DATA(lv_response) = lo_http_client->response->get_cdata( ).
WRITE: / lv_response.
lo_http_client->close( ).
Bearer Token (OAuth)
DATA: lo_http_client TYPE REF TO if_http_client,
lv_token TYPE string VALUE 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'.
cl_http_client=>create_by_url(
EXPORTING url = 'https://api.example.com/protected'
IMPORTING client = lo_http_client ).
" Header de autorização
lo_http_client->request->set_header_field(
name = 'Authorization'
value = |Bearer { lv_token }| ).
lo_http_client->request->set_method( if_http_request=>co_request_method_get ).
lo_http_client->send( ).
lo_http_client->receive( ).
lo_http_client->close( ).
API Key
DATA: lo_http_client TYPE REF TO if_http_client,
lv_api_key TYPE string VALUE 'abc123xyz789'.
cl_http_client=>create_by_url(
EXPORTING url = 'https://api.example.com/data'
IMPORTING client = lo_http_client ).
" API Key no header
lo_http_client->request->set_header_field(
name = 'X-API-Key'
value = lv_api_key ).
" Ou na URL
DATA(lv_url) = |https://api.example.com/data?api_key={ lv_api_key }|.
lo_http_client->send( ).
lo_http_client->receive( ).
lo_http_client->close( ).
📤 Headers Customizados
Adicionar Headers
" Content-Type
lo_http_client->request->set_header_field(
name = 'Content-Type'
value = 'application/json' ).
" Accept
lo_http_client->request->set_header_field(
name = 'Accept'
value = 'application/json' ).
" Custom headers
lo_http_client->request->set_header_field(
name = 'X-Custom-Header'
value = 'CustomValue' ).
" User-Agent
lo_http_client->request->set_header_field(
name = 'User-Agent'
value = 'SAP-ABAP-Client/1.0' ).
Ler Headers da Resposta
" Após receive()
DATA(lv_content_type) = lo_http_client->response->get_header_field( 'Content-Type' ).
DATA(lv_server) = lo_http_client->response->get_header_field( 'Server' ).
WRITE: / |Content-Type: { lv_content_type }|.
WRITE: / |Server: { lv_server }|.
" Todos os headers
DATA: lt_headers TYPE tihttpnvp.
lo_http_client->response->get_header_fields( CHANGING fields = lt_headers ).
LOOP AT lt_headers INTO DATA(ls_header).
WRITE: / |{ ls_header-name }: { ls_header-value }|.
ENDLOOP.
📊 Trabalhar com JSON
/UI2/CL_JSON - Parse JSON
DATA: lv_json TYPE string,
lo_json TYPE REF TO /ui2/cl_json.
" JSON recebido
lv_json = lo_http_client->response->get_cdata( ).
" Estrutura ABAP
TYPES: BEGIN OF ty_user,
id TYPE i,
name TYPE string,
email TYPE string,
END OF ty_user.
DATA: ls_user TYPE ty_user.
" Converter JSON → ABAP
/ui2/cl_json=>deserialize(
EXPORTING
json = lv_json
CHANGING
data = ls_user ).
WRITE: / |ID: { ls_user-id }|.
WRITE: / |Nome: { ls_user-name }|.
WRITE: / |Email: { ls_user-email }|.
Criar JSON para Enviar
TYPES: BEGIN OF ty_product,
name TYPE string,
price TYPE p DECIMALS 2,
stock TYPE i,
END OF ty_product.
DATA: ls_product TYPE ty_product,
lv_json TYPE string.
ls_product-name = 'Produto ABC'.
ls_product-price = '99.90'.
ls_product-stock = 50.
" Converter ABAP → JSON
lv_json = /ui2/cl_json=>serialize(
data = ls_product
compress = abap_false " Formatado
pretty_name = /ui2/cl_json=>pretty_mode-low_case ). " camelCase
" Enviar JSON
lo_http_client->request->set_cdata( lv_json ).
🔧 Configurações Avançadas
SSL/TLS
" Criar com SSL
cl_http_client=>create_by_url(
EXPORTING
url = 'https://api.example.com'
ssl_id = 'ANONYM' " ou certificado específico
IMPORTING
client = lo_http_client ).
" Desabilitar verificação SSL (não recomendado em produção)
lo_http_client->propertytype_logon_popup = lo_http_client->co_disabled.
Configurar certificado SSL:
1. STRUST - Trust Manager
2. Importar certificado
3. Usar SSL ID em create_by_url
Timeout
" Timeout em segundos
lo_http_client->set_timeout(
timeout = 30 " 30 segundos
).
Proxy
" Configurar proxy
lo_http_client->get_proxy( )->set_proxy(
proxy_host = 'proxy.empresa.com'
proxy_port = '8080' ).
" Autenticação no proxy
lo_http_client->get_proxy( )->set_proxy_authentication(
proxy_user = 'proxy_user'
proxy_password = 'proxy_pass' ).
Compression
" Aceitar resposta comprimida (gzip)
lo_http_client->request->set_header_field(
name = 'Accept-Encoding'
value = 'gzip' ).
💡 Exemplos Completos
Exemplo 1: Consultar API REST Pública
*&---------------------------------------------------------------------*
*& Report Z_HTTP_GET_USERS
*&---------------------------------------------------------------------*
REPORT z_http_get_users.
DATA: lo_http_client TYPE REF TO if_http_client,
lv_json TYPE string.
START-OF-SELECTION.
TRY.
" API pública de teste
cl_http_client=>create_by_url(
EXPORTING url = 'https://jsonplaceholder.typicode.com/users'
IMPORTING client = lo_http_client ).
" GET
lo_http_client->request->set_method( if_http_request=>co_request_method_get ).
" Enviar e receber
lo_http_client->send( ).
lo_http_client->receive( ).
" Status
DATA(ls_status) = lo_http_client->response->get_status( ).
WRITE: / |Status: { ls_status-code } - { ls_status-reason }|, /.
IF ls_status-code = 200.
" JSON
lv_json = lo_http_client->response->get_cdata( ).
" Parse JSON
TYPES: BEGIN OF ty_user,
id TYPE i,
name TYPE string,
username TYPE string,
email TYPE string,
END OF ty_user.
DATA: lt_users TYPE TABLE OF ty_user.
/ui2/cl_json=>deserialize(
EXPORTING json = lv_json
CHANGING data = lt_users ).
WRITE: / |Usuários encontrados: { lines( lt_users ) }|, /.
LOOP AT lt_users INTO DATA(ls_user).
WRITE: / |{ ls_user-id } - { ls_user-name } ({ ls_user-email })|.
ENDLOOP.
ELSE.
WRITE: / '❌ Erro ao buscar usuários'.
ENDIF.
" Fechar
lo_http_client->close( ).
CATCH cx_root INTO DATA(lo_ex).
WRITE: / |Exceção: { lo_ex->get_text( ) }|.
ENDTRY.
Exemplo 2: POST com JSON
*&---------------------------------------------------------------------*
*& Report Z_HTTP_POST_DATA
*&---------------------------------------------------------------------*
REPORT z_http_post_data.
DATA: lo_http_client TYPE REF TO if_http_client,
lv_request TYPE string,
lv_response TYPE string.
START-OF-SELECTION.
TRY.
" Dados para enviar
DATA: BEGIN OF ls_post,
title TYPE string VALUE 'Novo Post',
body TYPE string VALUE 'Conteúdo do post',
userId TYPE i VALUE 1,
END OF ls_post.
" Converter para JSON
lv_request = /ui2/cl_json=>serialize(
data = ls_post
compress = abap_false ).
WRITE: / '═══ REQUEST ═══'.
WRITE: / lv_request, /.
" Criar cliente
cl_http_client=>create_by_url(
EXPORTING url = 'https://jsonplaceholder.typicode.com/posts'
IMPORTING client = lo_http_client ).
" Configurar POST
lo_http_client->request->set_method( if_http_request=>co_request_method_post ).
lo_http_client->request->set_header_field(
name = 'Content-Type'
value = 'application/json' ).
lo_http_client->request->set_cdata( lv_request ).
" Enviar
lo_http_client->send( ).
lo_http_client->receive( ).
" Resposta
DATA(lv_status) = lo_http_client->response->get_status( )-code.
lv_response = lo_http_client->response->get_cdata( ).
WRITE: / '═══ RESPONSE ═══'.
WRITE: / |Status: { lv_status }|.
WRITE: / lv_response, /.
IF lv_status = 201.
WRITE: / '✅ Post criado com sucesso!'.
ELSE.
WRITE: / '❌ Erro ao criar post'.
ENDIF.
lo_http_client->close( ).
CATCH cx_root INTO DATA(lo_ex).
WRITE: / |Erro: { lo_ex->get_text( ) }|.
ENDTRY.
Exemplo 3: API com Autenticação
*&---------------------------------------------------------------------*
*& Report Z_HTTP_AUTH_API
*&---------------------------------------------------------------------*
REPORT z_http_auth_api.
PARAMETERS: p_user TYPE string LOWER CASE DEFAULT 'api_user',
p_pass TYPE string LOWER CASE DEFAULT 'api_pass',
p_url TYPE string LOWER CASE DEFAULT 'https://api.example.com/data'.
DATA: lo_http_client TYPE REF TO if_http_client.
START-OF-SELECTION.
TRY.
" Criar cliente
cl_http_client=>create_by_url(
EXPORTING
url = CONV string( p_url )
ssl_id = 'ANONYM'
IMPORTING
client = lo_http_client ).
" Basic Auth
lo_http_client->authenticate(
username = CONV string( p_user )
password = CONV string( p_pass ) ).
" Timeout
lo_http_client->set_timeout( timeout = 60 ).
" GET
lo_http_client->request->set_method( if_http_request=>co_request_method_get ).
lo_http_client->request->set_header_field(
name = 'Accept'
value = 'application/json' ).
" Executar
lo_http_client->send(
EXCEPTIONS
http_communication_failure = 1
http_invalid_state = 2 ).
IF sy-subrc = 0.
lo_http_client->receive(
EXCEPTIONS
http_communication_failure = 1
http_invalid_state = 2 ).
IF sy-subrc = 0.
DATA(ls_status) = lo_http_client->response->get_status( ).
CASE ls_status-code.
WHEN 200.
DATA(lv_data) = lo_http_client->response->get_cdata( ).
WRITE: / '✅ Dados recebidos:', /.
WRITE: / lv_data.
WHEN 401.
WRITE: / '❌ Não autorizado - verificar credenciais'.
WHEN 404.
WRITE: / '❌ Recurso não encontrado'.
WHEN OTHERS.
WRITE: / |❌ Erro { ls_status-code }: { ls_status-reason }|.
ENDCASE.
ELSE.
WRITE: / '❌ Erro ao receber resposta'.
ENDIF.
ELSE.
WRITE: / '❌ Erro ao enviar requisição'.
ENDIF.
lo_http_client->close( ).
CATCH cx_root INTO DATA(lo_ex).
WRITE: / |Exceção: { lo_ex->get_text( ) }|.
ENDTRY.
⚡ Boas Práticas
✅ Fazer
" 1. Sempre fechar conexão
TRY.
" ... usar lo_http_client ...
CATCH cx_root.
" ... tratamento ...
ENDTRY.
lo_http_client->close( ). " ✅ Sempre fechar
" 2. Tratar exceções
TRY.
cl_http_client=>create_by_url(
EXPORTING url = lv_url
IMPORTING client = lo_http_client ).
CATCH cx_root INTO DATA(lo_ex).
WRITE: / lo_ex->get_text( ). " ✅ Tratar erro
ENDTRY.
" 3. Verificar status code
DATA(lv_code) = lo_http_client->response->get_status( )-code.
IF lv_code <> 200. " ✅ Verificar
" Tratar erro
ENDIF.
" 4. Timeout adequado
lo_http_client->set_timeout( timeout = 30 ). " ✅ Timeout
" 5. Usar destinos RFC para URLs recorrentes
cl_http_client=>create_by_destination(
EXPORTING destination = 'Z_API_DEST' " ✅ SM59
IMPORTING client = lo_http_client ).
❌ Evitar
" 1. Não fechar conexão
lo_http_client->send( ).
lo_http_client->receive( ).
" ❌ Esquecer close()
" 2. Hardcoded credentials
DATA lv_password TYPE string VALUE 'senha123'. " ❌ NUNCA!
" 3. Não tratar erros
lo_http_client->send( ). " ❌ E se falhar?
" 4. Timeout muito alto
lo_http_client->set_timeout( timeout = 300 ). " ❌ 5 minutos?
" 5. URLs hardcoded
DATA lv_url TYPE string VALUE 'http://prod-server.com'. " ❌ Usar SM59
🔗 Próximos Passos
- OData - Alternativa para APIs SAP
- REST API - Criar APIs REST em ABAP
- Web Services - SOAP Web Services
Tags: #HTTP #REST #API #Integrações #CL_HTTP_CLIENT #JSON