How to catch a ColdFusion CFHTTP timeout exception? - coldfusion

I have a page where I make a remote request to an external API. I sometimes get request timeouts when making the request, so, my plan to set a timeout in the CFHTTP tag that is lower than my default requesttimeout setting and catch it. However, I can't get my CFTRY/CFCATCH to catch it. Here is my pseudo code:
private void function makeRequest(){
cfhttp(
url="https://api.somesite.com/",
method="POST",
timeout="1",
throwonerror="true",
result="LOCAL.ApiHttpResult"
) {
...
}
}
public void function tryRequest() {
try {
makeRequest();
}
catch(coldfusion.runtime.RequestTimeoutException e) {
abort;
}
}
I get the same result out of CFSCRIPT:
<cffunction access="public" returntype="void" name="tryRequest">
<cftry>
<cfscript>
makeRequest();
</cfscript>
<cfcatch type="coldfusion.runtime.RequestTimeoutException">
<cfabort />
</cfcatch>
</cffunction>
Is there something special about the CFHTTP timing out that makes this impossible to catch programmatically? Any ideas on how to do this?
Thanks....

You just misspelled the exception type: It's coldfusion.runtime.RequestTimedOutException (coldfusion.runtime.RequestTimedOutException).
But there's another way to do this without exception handling. Just do a regular cfhttp, but don't specify the throwOnError attribute (or keep it false). This will still return a response struct after the request has timed out. It will be populated with status code 408 Request Time-out. You can access it like this:
if (left(LOCAL.ApiHttpResult.Statuscode, 3) eq "408") {
writeOutput("HTTP request timed out");
} else {
writeOutput("HTTP request successful with status: #LOCAL.ApiHttpResult.Statuscode#");
}

More of a comment, but this is way too long. Just do a dump off whatever exception is happening. Then filter on the specific exception
public void function tryRequest() {
try {
makeRequest();
}
catch(any e) {
writedump(e);
// then find the details on the specific exception type
}
}

Related

AWS .Net Core SDK Simple Email Service Suppression List Not Working

I am trying to retrieve the SES account-level suppression list using AWS SDK in .Net Core:
Below is my code:
public class SimpleEmailServiceUtility : ISimpleEmailServiceUtility
{
private readonly IAmazonSimpleEmailServiceV2 _client;
public SimpleEmailServiceUtility(IAmazonSimpleEmailServiceV2 client)
{
_client = client;
}
public async Task<ListSuppressedDestinationsResponse> GetSuppressionList()
{
ListSuppressedDestinationsRequest request = new ListSuppressedDestinationsRequest();
request.PageSize = 10;
ListSuppressedDestinationsResponse response = new ListSuppressedDestinationsResponse();
try
{
response = await _client.ListSuppressedDestinationsAsync(request);
}
catch (Exception ex)
{
Console.WriteLine("ListSuppressedDestinationsAsync failed with exception: " + ex.Message);
}
return response;
}
}
But it doesn't seem to be working. The request takes too long and then returns empty response or below error if I remove try/catch:
An unhandled exception occurred while processing the request.
TaskCanceledException: A task was canceled.
System.Threading.Tasks.TaskCompletionSourceWithCancellation<T>.WaitWithCancellationAsync(CancellationToken cancellationToken)
TimeoutException: A task was canceled.
Amazon.Runtime.HttpWebRequestMessage.GetResponseAsync(CancellationToken cancellationToken)
Can anyone please guide if I am missing something?
Thank you!
I have tested your code and everything works correctly.
using Amazon;
using Amazon.SimpleEmailV2;
using Amazon.SimpleEmailV2.Model;
internal class Program
{
private async static Task Main(string[] args)
{
var client = new AmazonSimpleEmailServiceV2Client("accessKeyId", "secrectAccessKey", RegionEndpoint.USEast1);
var utility = new SimpleEmailServiceUtility(client);
var result = await utility.GetSuppressionList();
}
}
<PackageReference Include="AWSSDK.SimpleEmailV2" Version="3.7.1.127" />
Things that you can check:
Try again, maybe it was a temporary problem.
Try with the latest version that I am using(if not already)
How far are you from the region that you try to get the list? Try making the same request from an EC2 instance in that region.
Finally found the issue, I was using awsConfig.DefaultClientConfig.UseHttp = true;' in startup` which was causing the issue. Removing it fixed the issue and everything seems to be working fine now.

How can I send HTTP Status Code and a Response messages to the client in ColdFusion?

I am implementing the Single Sign On functionality. I have an ColdFusion application which takes input parameters from Java application (POST request). What I need to do is return status codes and a description to indicate whether the user has access and the failed reason if the user does not have access to my CF application.
Something like below:
I have created a cfc and provided this as an API to allow Java users to pass in their UserName, CustomerID to my CF application.
Do I need to write the return response logic in the same file? Like a function which "throw" error code (cfthrow).
Or may be I can use "cfheader"....something like this:
<cfif form.CustomerId EQ queryname.CustID>
<CFHEADER
STATUSCODE="200"
STATUSTEXT="Success">
<cfelse>
<CFHEADER
STATUSCODE="400"
STATUSTEXT="Insufficient Input">
</cfif>
Can anyone please help me here?
You can use:
component restpath = "your/rest/path" rest="true"
{
remote void function errorTest()
httpmethod = "GET"
restpath = ""
{
cfheader(
statuscode = 401,
statustext = "Invalid Password"
);
// or
restSetResponse({
status = 401,
headers = { explanation = "Invalid Password" }
});
// or, using Java
getPageContext()
.getResponse()
.getResponse()
.sendError( JavaCast( 'int', 401 ), "Invalid Password" );
// or, using the deprecated setStatus(int,string) method in Java
getPageContext()
.getResponse()
.getResponse()
.setStatus( JavaCast( 'int', 401 ), "Invalid Password" );
}
}
Note: I have not found a way to directly set the message using restSetResponse() so this returns a custom header with the message instead.

Appending cookies in ASP.Net core when response status code = 500

In ASP.Net Core application, how can I set a cookie and throw an exception during the same request?
In a Web API call, whenever I set a cookie using Response.Cookies.Append() the cookie header is only sent to the browser when returning from the call without throwing any exception.
If I append the cookie and then throw an exception, the cookie header is lost.
What gives? Am I missing something fundamental here? This doesn't seem like expected behavior.
Instead of not handling the exception (returning a 500), you could catch the exception and output a cookie with a controlled response. Something like:
[HttpGet]
public IActionResult Get()
{
try
{
throw new Exception("some exception");
}
catch (Exception ex)
{
// issue cookie and return response
Response.Cookies.Append("someCookie", "my value");
return BadRequest();
}
}

Camel exchange expired via jetty continuation

Is there a possibility in Apache Camel to register a handler for managing exchanges that cannot be written to jetty endpoint http response because continuation timeout has been reached?
I'll just add my notes on that because I made it available in my project by modifying CamelContinuationServlet in the if (continuation.isExpired()) block like this
if (continuation.isExpired()) {
String id = (String) continuation.getAttribute(EXCHANGE_ATTRIBUTE_ID);
// remember this id as expired
expiredExchanges.put(id, id);
log.warn("Continuation expired of exchangeId: {}", id);
consumer.getBinding().doWriteExceptionResponse(new TimeoutException(), response);
return;
}
in combination with a custom HttpBinding called ErrorHandlingHttpBinding in my code like this
public class ErrorHandlingHttpBinding extends DefaultHttpBinding {
#Override
public void doWriteExceptionResponse(Throwable exception, HttpServletResponse response) throws IOException {
if (exception instanceof TimeoutException) {
response.setStatus(HttpServletResponse.SC_GATEWAY_TIMEOUT);
response.getWriter().write("Continuation timed out...");
} else {
super.doWriteExceptionResponse(exception, response);
}
}
}
registered as spring bean with id="errorHandlingHttpBinding" and referred in the component string as jetty:http://localhost:21010/?useContinuation=true&continuationTimeout=1&httpBindingRef=errorHandlingHttpBinding.
No this is not possible. Maybe you need to set a higher timeout if you have some slow processing exchanges.
You are welcome to dive in the Jetty APIs to see if you can find a hook for such a onTimeout event and see what it takes to support that in camel-jetty.

How to I unit test a #future method that uses a callout?

I have a trigger that fires when an opportunity is updated, as part of that I need to call our API with some detail from the opportunity.
As per many suggestions on the web I've created a class that contains a #future method to make the callout.
I'm trying to catch an exception that gets thrown in the #future method, but the test method isn't seeing it.
The class under test looks like this:
public with sharing class WDAPIInterface {
public WDAPIInterface() {
}
#future(callout=true) public static void send(String endpoint, String method, String body) {
HttpRequest req = new HttpRequest();
req.setEndpoint(endpoint);
req.setMethod(method);
req.setBody(body);
Http http = new Http();
HttpResponse response = http.send(req);
if(response.getStatusCode() != 201) {
System.debug('Unexpected response from web service, expecte response status status 201 but got ' + response.getStatusCode());
throw new WDAPIException('Unexpected response from web service, expecte response status status 201 but got ' + response.getStatusCode());
}
}
}
here's the unit test:
#isTest static void test_exception_is_thrown_on_unexpected_response() {
try {
WDHttpCalloutMock mockResponse = new WDHttpCalloutMock(500, 'Complete', '', null);
WDAPIInterface.send('https://example.com', 'POST', '{}');
} catch (WDAPIException ex) {
return;
}
System.assert(false, 'Expected WDAPIException to be thrown, but it wasnt');
}
Now, I've read that the way to test #future methods is to surround the call with Test.startTest() & Test.endTest(), however when I do that I get another error:
METHOD RESULT
test_exception_is_thrown_on_unexpected_response : Skip
MESSAGE
Methods defined as TestMethod do not support Web service callouts, test skipped
So the question is, how do I unit test a #future method that makes an callout?
The callout is getting skipped because the HttpCalloutMock isn't being used.
I assume that WDHttpCalloutMock implements HttpCalloutMock?
If so, a call to Test.setMock should have it return the mocked response to the callout.
WDHttpCalloutMock mockResponse = new WDHttpCalloutMock(500, 'Complete', '', null);
Test.setMock(HttpCalloutMock.class, mockResponse);
WDAPIInterface.send('https://example.com', 'POST', '{}');
Incidentally, the Salesforce StackExchange site is a great place to ask Salesforce specific questions.