Using HTTP_POST_VERBOSE on IBM i for REST API Calls
IBM i provides powerful SQL functions for making HTTP requests, allowing seamless integration with REST APIs. One of the most useful functions is QSYS2.HTTP_POST_VERBOSE, which sends a POST request and returns detailed response data. This capability is perfect for connecting IBM i applications to modern web services, whether you’re sending data to an external API or caching results with Redis, as I’ve done in my redis400 project.
In this article, we’ll cover:
- How to construct HTTP headers (including authentication and SSL settings)
- Making POST requests with HTTP_POST_VERBOSE
- Processing the response (status code, headers, and body)
Let’s dive in!
1. Building the HTTP Request Headers
The HTTP_POST_VERBOSE function requires HTTP headers to be passed in JSON format. Depending on your security requirements, you may need to include headers like Content-Type, Content-Length, Authorization, and SSL settings for secure connections.
Key Headers to Include
- Content-Type: Typically application/json for REST APIs.
- Content-Length: The length of the input data (calculated dynamically).
- Authorization: A Bearer token for authenticated APIs.
- SSL Settings: Options like sslCertificateStoreFile for custom certificates or sslTolerate to handle certificate issues.
-- If HTTPS is enabled
If IN_USE_HTTPS = 1 Then
-- Use a custom certificate store (if not default)
If IN_USE_DEFAULT_CERT_STORE = 0 Then
Set REQ_HEADER = Json_Object(
'header' Value 'content-type, application/json',
'header' Value 'content-length, ' Concat Length(RTrim(IN_DATA)),
'header' Value 'Authorization, Bearer ' Concat Trim(TOKEN),
'sslCertificateStoreFile' Value Trim(APP_CERT_STORE)
);
Else
-- Use default SSL trust (ignore some cert issues)
Set REQ_HEADER = Json_Object(
'header' Value 'content-type, application/json',
'header' Value 'content-length, ' Concat Length(RTrim(IN_DATA)),
'header' Value 'Authorization, Bearer ' Concat Trim(TOKEN),
'sslTolerate' Value 'true'
);
End If;
Else
-- Plain HTTP (no SSL)
Set REQ_HEADER = Json_Object(
'header' Value 'content-type, application/json',
'header' Value 'content-length, ' Concat Length(RTrim(IN_DATA)),
'header' Value 'Authorization, Bearer ' Concat Trim(TOKEN)
);
End If;
This code checks if HTTPS is enabled (IN_USE_HTTPS = 1) and whether to use a custom certificate store (IN_USE_DEFAULT_CERT_STORE = 0). It then builds the REQ_HEADER JSON object with the necessary headers, including Content-Type, Content-Length, and Authorization. For HTTPS, it either specifies a custom certificate store (sslCertificateStoreFile) or tolerates minor certificate issues (sslTolerate).
2. Making the POST Request with HTTP_POST_VERBOSE
The QSYS2.HTTP_POST_VERBOSE function is designed to send HTTP POST requests and return detailed response data. It takes three parameters:
- URL: The API endpoint (e.g., https://api.example.com/data).
- IN_DATA: The JSON payload (as a CLOB).
- REQ_HEADER: The headers in JSON format (constructed in the previous step).
Example: Executing the POST Request
Here’s how to execute the POST request and extract the HTTP status code from the response:
SELECT
IFNULL(R.HTTP_CODE, '5xx')
INTO
RESP_CODE
FROM
TABLE(QSYS2.HTTP_POST_VERBOSE(RTRIM(URL), RTRIM(IN_DATA), RTRIM(REQ_HEADER))) A
CROSS JOIN
JSON_TABLE(
REPLACE(A.RESPONSE_HTTP_HEADER, '=', ':'),
'$' COLUMNS(
HTTP_CODE CHAR(3) PATH '$.HTTP_STATUS_CODE'
)
) R;
Key Points
- HTTP_POST_VERBOSE returns a table with columns like RESPONSE_HTTP_HEADER (headers as a key=value string) and RESPONSE_BODY (the response data).
- The RESPONSE_HTTP_HEADER is in a Key=Value format, so we use Replace(A.RESPONSE_HTTP_HEADER, ‘=’, ‘:’) to convert it to JSON (Key:Value) for parsing with JSON_TABLE.
- We extract the HTTP_STATUS_CODE (e.g., 200, 401, 500) using JSON_TABLE and store it in RESP_CODE.
- If the request fails and no status code is returned, we default to ‘5xx’ (indicating a server error).
This approach is useful for scenarios like sending data to an external API and confirming the request succeeded before proceeding with further processing.
3. Handling the Response
The HTTP_POST_VERBOSE function provides detailed response data, including:
- HTTP Status Code: E.g., 200 (success), 401 (unauthorized), 500 (server error).
- Response Headers: Useful for pagination, rate limits, or debugging.
- Response Body: The actual data returned by the API (e.g., JSON, XML).
Example: Extracting Response Data
To retrieve both the status code and the response body, you can modify the query like this:
SELECT
R.HTTP_CODE,
A.RESPONSE_BODY
FROM
TABLE(QSYS2.HTTP_POST_VERBOSE(
RTRIM(URL),
RTRIM(IN_DATA),
RTRIM(REQ_HEADER)
) A
CROSS JOIN
JSON_TABLE(
REPLACE(A.RESPONSE_HTTP_HEADER, '=', ':'),
'$' COLUMNS(
HTTP_CODE CHAR(3) PATH '$.HTTP_STATUS_CODE'
)
) R;
This query returns the HTTP status code (HTTP_CODE) and the response body (RESPONSE_BODY), which you can then parse further (e.g., using JSON_TABLE if the body is JSON). For example, in my redis400 project, I use this to retrieve data from a Redis server via a REST API, ensuring I can cache the response efficiently.
Best Practices
To make the most of HTTP_POST_VERBOSE, follow these best practices:
- Always Check the Response Code: Handle 4xx (client errors) and 5xx (server errors) appropriately. For example, a 401 might indicate an expired token, while a 429 suggests rate limiting.
- Use HTTPS in Production: Avoid plain HTTP to ensure data security, especially when sending sensitive data.
- Log Errors and Performance: Track API failures and response times to identify issues early. You can store logs in a database table or a user space on IBM i.
- Retry on Transient Failures: For errors like 429 Too Many Requests, implement a retry mechanism with exponential backoff to handle transient issues gracefully.
Conclusion
IBM i’s QSYS2.HTTP_POST_VERBOSE function is a powerful tool for integrating with REST APIs directly from SQL, enabling seamless communication with modern web services. By properly constructing headers, making POST requests, and handling responses, you can connect IBM i to a wide range of systems—whether it’s caching data with Redis in my redis400 project or integrating with AI APIs for advanced analytics. This approach simplifies development and ensures your IBM i applications can interact with the modern web efficiently.