Client-Side Error Handling: "Curl"-ing with Confidence
The curl command (short for "Client URL"), is a versatile command-line tool used for transferring data to and from a server. In infrastructure management, it is frequently employed in deployment scripts to initiate changes in administered systems, such as submitting configurations, creating or modifying resources, and starting tasks.
With the advent of cloud-based and self-healing systems, there is a tendency to trust more in stability than it probably should be and overlook potential unavailability issues. While these problems are more common in traditional physical and legacy environments, even contemporary infrastructure is not immune to network unreliability (consider distributed systems connected over the Internet). Services may not always be able to handle requests with 100% reliability. Therefore, being prepared for outages and errors and taking appropriate actions is a best practice to follow.
In this article, I present a pattern that can make the use of curl more robust in addressing similar issues.
The forms of errors
When sending a request to a service, the following errors may typically occur:
The service responds with an error message indicating the reason:
- User error: The request is malformed or unprocessable (e.g., the entity the request refers to is missing).
- System error: The request failed due to infrastructure issues (e.g., the web proxy is unable to reach the backend service) or functional errors (e.g., a bug or improper error handling in the backend code).
The request times out (the underlying system is unable to respond within a reasonable time).
The connection cannot be established to the target system or gets broken (e.g., physical layer issues, firewall settings, network congestion).
Handling errors on the client side
Handling errors is always a case-by-case matter.
Key considerations include:
There is no one-size-fits-all solution. In the example below, a REST API is invoked with a JSON payload. Curl is equipped with error handling, security, timeout and retry settings, which can serve as a starting point for implementing your own:
领英推荐
# Create the JSON payload
REQUEST_PAYLOAD=$(cat <<EOF
{
"attr": "$SOME_ENV_VAR",
...
}
EOF
)
SERVER_URL=https://api.some-awesome-service.net/v1/some-entity/
# Send the request to the REST API
set +e # do not exit the script immediately on errors
HTTP_STATUS=$(curl -w "%{http_code}" -o /tmp/curl_response_body -s -S -i \
--retry-connrefused --connect-timeout 10 \
--fail-with-body --retry 3 --retry-delay 5 \
-m 10 \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-X POST \
-d "$REQUEST_PAYLOAD" \
$SERVER_URL)
CURL_RETURN_CODE=$?
set -e # exit on errors
if [ "$CURL_RETURN_CODE" -ne 0 ]; then
echo $(date) "Failed to reach the API or process the payload. (HTTP Status: $HTTP_STATUS)" >&2
[ -f /tmp/curl_response_body ] && cat /tmp/curl_response_body >&2
rm /tmp/curl_response_body || true # cleanup
exit 1
fi
rm /tmp/curl_response_body || true # Clean-up:
# the client code continues...
Explanation of the used curl Flags
Response Handling
Retries
Timeout
Security
Request Content
Conclusion
In summary, the curl command is an invaluable tool for managing data transfers in infrastructure management.
By understanding and utilizing its various flags for error handling, retries, timeouts, security, and request content, you can significantly enhance the robustness and reliability of your deployment scripts.
This article has provided a detailed explanation of these flags and demonstrated how to effectively handle common issues that may arise during data transfers. By implementing these practices, you can ensure smoother operations and better resilience against potential errors and outages in your systems.