El uso de APIs se ha vuelto un estándar para la integración de sistemas actuales, esto es principalmente por su fácil desarrollo, fácil integración con cualquier sistema y sus estándares cómo el uso de json, protocolos http y códigos de respuesta, entre otros.

En esta entrada vamos a explorar cómo consumir un API Restful desde PL/SQL, que elementos del entorno debemos tener en cuenta para lograr una comunicación efectiva y veremos algunos ejemplos de comunicación usando POST junto con el método de autenticación de APIs OAuth2.

¿Qué es un API RESTful?

Primero debemos entender qué es un API RESTful. Un API RESTful (Transferencia de Estado Representacional) es una interfaz de programación que sigue los principios de REST. Utiliza los métodos HTTP estándar (GET, POST, PUT, DELETE) para realizar operaciones CRUD (Crear, Leer, Actualizar, Eliminar) en recursos.

Paso 1: Preparación del entorno

Antes de comenzar, debemos asegurarnos de tener algunos detalles en el ambiente, esto con el fin de que la comunicación con el API funcione:

  • Se debe tener acceso al URL del API a consumir, para ello es bueno que de ping o una respuesta telnet tanto a la ip como al puerto a consumir.
  • Si se consume un API que utilza SSL o bien https, se deben tener los certificados SSL de ese URL destino dentro del wallet de la base de datos para que la base de datos logre comunicación con el API.
  • Se debe crear un ACL (Abajo muestro un ejemplo), esto con el fin de permitir la conexión a la ip o host específico utilizando un schema en específico, para ello se debe tener un usuario con privilegios suficientes para la creación del ACL y la asignación del mismo.
  • Si ya tenemos comunicación con el API, es bueno saber cuál es el método de autenticación que el API utiliza, ya sea OAuth2, JWT, usuario y contraseña; esto se debe consultar en la documentación del API y dependiendo el tipo de acceso, el desarrollo de la autenticación puede variar.

Paso 2: Configuración de la red

Si estás detrás de un firewall, es posible que necesites configurar el acceso a la red. Asegúrate de que la base de datos Oracle tenga permisos para realizar solicitudes HTTP. Para ello podemos usar el siguiente ejemplo donde indicamos el hostname a conectar y los permisos connect y resolve. También podemos colocar un * para pruebas o bien una ip, adicionalmente en el principal_name se debe colocar el schema que se utilizará para conectarse al API.

BEGIN
    DBMS_NETWORK_ACL_ADMIN.APPEND_HOST_ACE(
        host => 'google.com',
        ace => xs$ace_type(privilege_list => xs$name_list('connect', 'resolve'),
                           principal_name => 'mi_schema',
                           principal_type => xs_acl.ptype_db));
END;
/

Paso 3: Creación de la función de consumo

Ahora vamos a utilizar el paquete UTL_HTTP para realizar solicitudes HTTP desde PL/SQL.

CREATE OR REPLACE PROCEDURE post_to_api(
    p_url          IN VARCHAR2,
    p_request_body IN CLOB
)
IS
    l_http_req   UTL_HTTP.REQ;
    l_http_resp  UTL_HTTP.RESP;
    l_response   CLOB;
BEGIN
    -- Crear la solicitud HTTP
    l_http_req := UTL_HTTP.begin_request(p_url, 'POST');

    -- Configurar encabezados si es necesario
    UTL_HTTP.set_header(l_http_req, 'Content-Type', 'application/json');
    UTL_HTTP.set_header(l_http_req, 'User-Agent', 'Mozilla/4.0');

    -- Adjuntar el cuerpo de la solicitud
    UTL_HTTP.write_text(l_http_req, p_request_body);

    -- Obtener la respuesta
    l_http_resp := UTL_HTTP.get_response(l_http_req);
    UTL_HTTP.read_text(l_http_resp, l_response);
    UTL_HTTP.end_response(l_http_resp);

    -- Procesar la respuesta según sea necesario
    DBMS_OUTPUT.put_line(l_response);
EXCEPTION
    WHEN UTL_HTTP.OTHERS THEN
        -- Manejar errores HTTP
        DBMS_OUTPUT.put_line('Error al realizar la solicitud HTTP.');
END;
/

En este ejemplo, la función post_to_api toma dos parámetros: la URL del API y el cuerpo de la solicitud en formato CLOB (puedes ajustar el tipo de contenido según tus necesidades). Luego solo llamaremos este procedimiento y le enviaremos la URL del API y el cuerpo de la solicitud para realizar una solicitud POST.

Paso 4: Consumir el API

Ahora puedes utilizar la función creada para consumir el API. Por ejemplo:

DECLARE
    l_api_url      VARCHAR2(200) := 'https://api.example.com/resource';
    l_request_body CLOB := '{"key": "value"}'; --Enviamos un JSON
BEGIN
    post_to_api(l_api_url, l_request_body);
END;
/

Enviando un Post con autenticación OAuth2:

La función anterior es sencilla y funciona cuando no tenemos un método de autenticación, pero que pasa cuando lo hay?, bueno para ello les dejo un ejemplo de cómo autenticarse usando OAuth2, el cual es una forma de autenticación muy común:

CREATE OR REPLACE PROCEDURE oauth2_authenticate_and_post(
    p_api_url      IN VARCHAR2,
    p_request_body IN CLOB,
    p_client_id     IN VARCHAR2,
    p_client_secret IN VARCHAR2,
    p_username      IN VARCHAR2,
    p_password      IN VARCHAR2,
    p_scope         IN VARCHAR2 DEFAULT NULL
)
IS
    l_http_req   UTL_HTTP.REQ;
    l_http_resp  UTL_HTTP.RESP;
    l_response   CLOB;
    l_token_url  VARCHAR2(200);
    l_token_body VARCHAR2(4000);
    l_access_token VARCHAR2(200);
BEGIN
    -- Construir la URL de autorización del token
    l_token_url := 'https://oauth2.example.com/token';

    -- Construir el cuerpo de la solicitud de token
    l_token_body := 'grant_type=password' ||
                    '&client_id=' || p_client_id ||
                    '&client_secret=' || p_client_secret ||
                    '&username=' || p_username ||
                    '&password=' || p_password;

    -- Crear la solicitud HTTP para obtener el token
    l_http_req := UTL_HTTP.begin_request(l_token_url, 'POST');
    UTL_HTTP.set_header(l_http_req, 'Content-Type', 'application/x-www-form-urlencoded');
    UTL_HTTP.write_text(l_http_req, l_token_body);

    -- Obtener la respuesta y extraer el token de acceso
    l_http_resp := UTL_HTTP.get_response(l_http_req);
    UTL_HTTP.read_text(l_http_resp, l_response);
    UTL_HTTP.end_response(l_http_resp);

    -- Analizar la respuesta JSON para extraer el token de acceso
    SELECT REGEXP_SUBSTR(l_response, '"access_token":"(.*?)"', 1, 1, NULL, 1)
    INTO l_access_token
    FROM DUAL;

    -- Verificar si se obtuvo un token de acceso
    IF l_access_token IS NOT NULL THEN
        -- Ahora puedes usar el token de acceso para hacer solicitudes al API
        l_http_req := UTL_HTTP.begin_request(p_api_url, 'POST');
        UTL_HTTP.set_header(l_http_req, 'Content-Type', 'application/json');
        UTL_HTTP.set_header(l_http_req, 'Authorization', 'Bearer ' || l_access_token);
        UTL_HTTP.write_text(l_http_req, p_request_body);

        -- Obtener la respuesta del API
        l_http_resp := UTL_HTTP.get_response(l_http_req);
        UTL_HTTP.read_text(l_http_resp, l_response);
        UTL_HTTP.end_response(l_http_resp);

        -- Procesar la respuesta según sea necesario
        DBMS_OUTPUT.put_line(l_response);
    ELSE
        DBMS_OUTPUT.put_line('Error al obtener el token de acceso.');
    END IF;
EXCEPTION
    WHEN UTL_HTTP.OTHERS THEN
        -- Manejar errores HTTP
        DBMS_OUTPUT.put_line('Error al realizar la solicitud HTTP.');
END;
/

Con este ejemplo implementamos la autenticación usando un client id y un client secret, además extraemos el access token y lo enviamos por el encabezado de la solicitud POST.

De esta manera podemos consumir un API Restful desde PL/SQL.

2 respuestas a «Cómo consumir un API RESTful desde PL/SQL con autenticación OAuth2»

  1. Hola una consulta tendras un ejemplo de ejecucion de api rest con ORACLE PLSQL pero en esta api rest tengo que enviar 4 archivos pdf que estan una carpeta de mi pc, ademas estos archivos diariamente cambian por esta razon debe ser dinamico son archivos que se deben enviar a la api rest y no encuentro informacion de como enviar archivos .

    1. Para enviar archivos primero debes insertarlos en una tabla ya sea temporal o una tabla fija, el el archivo lo puede añadir en una columna de tipo BLOB, ya con el archivo insertado, puede llamar un proceso o disparar un trigger con la nueva inserción y enviar ese campo blob usando una propiedad json, por ejemplo así:

      {
      archivo : «djbJhjdjBjelslmekfojk287474»
      }

      Entonces usando esta documentación podrás enviarlo, solo debes hacer previamente el proceso que inserte ese archivo a la base de datos, esto lo puede hacer ejecutando un job de base de datos que a X hora llame los archivos de esa carpeta y así ejecute el flujo

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *