Skip to main content
Ben Nadel at BFusion / BFLEX 2009 (Bloomington, Indiana) with: Aaron Wolfe and Lance Smith
Ben Nadel at BFusion / BFLEX 2009 (Bloomington, Indiana) with: Aaron Wolfe ( @Wolfeman77 ) Lance Smith ( @outlan )

Extending The Current Request Timeout In ColdFusion / CFML

By on
Tags:

The request timeout determines how long the current request / CFThread can execute before the request throws a timeout exception. For the most part, this value is either never set (which then uses the default timeout defined in the ColdFusion admin); or, it's set once at the top of the request. Sometimes, however, I run into situations where I need to dynamically update the timeout of the current page. Unfortunately, the CFSetting tag doesn't support this; as such, I wanted to outline ways in which this can be hacked into the request in either Adobe ColdFusion or Lucee CFML.

ASIDE: Over on the Lucee Dev Forum, I put out a suggestion that the CFSetting tag add an "extend" attribute to perform this operation. I'm not married to the idea - it was just a thought.

When you use the CFSetting tag to set the timeout for the current request, you're setting an absolute value, not a relative value. Which means, if your request has already been running for 5-seconds, and then you set the request timeout to be 10-seconds, the new timeout threshold for the request will be 10-seconds - not 15 (which would have been 5 + 10).

To see this absolute value in action, we can attempt to increment the timeout value while making CFHttp requests that we know will exceed the defined threshold:

<cfscript>

	requestSetTimeout( 5 );
	blockForSeconds( 4 );

	// CAUTION: !! DOES NOT WORK !!
	requestSetTimeout( 5 );
	blockForSeconds( 4 );

	writeOutput( "Done" );

	// ------------------------------------------------------------------------------- //
	// ------------------------------------------------------------------------------- //

	/**
	* I set the request timeout to the given seconds using the native CFSetting tag.
	*/
	public void function requestSetTimeout( required numeric timeoutInSeconds ) {

		cfsetting( requestTimeout = timeoutInSeconds );

	}


	/**
	* I block for the given duration in seconds by using HTTP requests that block for one
	* second. By performing this blocking in 1-second increments (essentially), this gives
	* the overall page request more opportunities to step in and throw a timeout.
	*/
	public void function blockForSeconds( required numeric durationInSeconds ) {

		for ( var i = 1 ; i <= durationInSeconds ; i++ ) {

			// Will block for 1-second on target page.
			cfhttp(
				result = "local.apiResponse",
				method = "get",
				url = "http://#cgi.server_name#:#cgi.server_port#/request-timeout/block-and-lock.cfm"
			);

		}

	}

</cfscript>

This code might look like I'm increasing the timeout by 5-seconds before I make my long-running requests; but, again, that's not how the CFSetting tag works. As such, when we run this ColdFusion code, we get the following errors (truncated):

Lucee CFML: RequestTimeoutException: request index.cfm has run into a timeout (timeout: 5 seconds) and has been stopped. The thread started 5028ms ago.

Adobe ColdFusion: RequestTimedOutException: The request has exceeded the allowable time limit Tag: cfhttp.

That second call to set the request timeout was, essentially, a no-op since I was setting it from 5 to 5.

In order to extend the current request timeout, our subsequent calls to the CFSetting tag have to set an increasingly large absolute value. Unfortunately, this isn't obvious; and, there's no single way to do this cross-platform (that I know of). But, it can be finagled in both Lucee CFML and Adobe ColdFusion through the use of the getPageContext() system function.

Here's an updated version of the above approach; but, instead of calling requestSetTimeout() a second time, I'm calling requestExtendTimeout()! This method attempts to encapsulate the cross-platform complexity.

<cfscript>

	requestSetTimeout( 5 );
	blockForSeconds( 4 );

	// NOTE: I'm EXTENDING here, NOT setting.
	requestExtendTimeout( 5 );
	blockForSeconds( 4 );

	writeOutput( "Done" );

	// ------------------------------------------------------------------------------- //
	// ------------------------------------------------------------------------------- //

	/**
	* I EXTEND the request timeout by the given seconds using the native CFSettings tag.
	* 
	* CAUTION: In Lucee CFML, this extends the existing request timeout. In Adobe
	* ColdFusion, this extends the current execution time of the request.
	*/
	public void function requestExtendTimeout( required numeric timeoutInSeconds ) {

		var pageContext = getPageContext();
		var requestTimeout = pageContext?.getRequestTimeout();

		// ADOBE COLDFUSION does NOT support request timeout functions in the page
		// context. As such, we'll have to go a bit more low-level.
		if ( isNull( requestTimeout ) ) {

			var startedAt = getPageContext().getFusionContext().getStartTime();
			var startedSecondsAgo = now().diff( "s", startedAt );

			cfsetting(
				requestTimeout = ( startedSecondsAgo + timeoutInSeconds )
			);

		// LUCEE CFML allows request timeouts to be configured on the page context.
		} else {

			cfsetting(
				requestTimeout = ( ( requestTimeout / 1000 ) + timeoutInSeconds )
			);

		}

	}

	// ... truncated - other two methods are the same in first example ... //

</cfscript>

As you can see, I attempt to call pageContext?.getRequestTimeout() which will fail gracefully on Adobe ColdFusion thanks to the safe navigation operator. I use the result of this call to determine which platform I'm on; and, then, branch into a platform-specific approach for calculating the new request timeout.

And, when we run this in both Lucee CFML and Adobe ColdFusion, we get the following output:

Done.

The request timeout was successfully extended to 10-seconds on both CFML platforms, allowing 8-seconds worth of CFHttp calls to execute. I don't love having to reach into the Page Context in order to accomplish our goals here. But, to be fair, I don't have to extend the request timeout very often.

UPDATE: Using the coldfusion.runtime.RequestMonitor Class

Right after I published this article, I came across another article that I wrote in 2007 dealing with the same exact topic. In that article, I use the internal ColdFusion class, coldfusion.runtime.RequestMonitor to get the current request timeout. And, unlike the getPageContext() approach that I used above, this RequestMonitor class appears to work in both Lucee CFML and Adobe ColdFusion.

Here's an updated demo that gets the current request timeout from this Java class:

<cfscript>

	requestSetTimeout( 5 );
	blockForSeconds( 4 );

	// NOTE: I'm EXTENDING here, NOT setting.
	requestExtendTimeout( 5 );
	blockForSeconds( 4 );

	writeOutput( "Done" );

	// ------------------------------------------------------------------------------- //
	// ------------------------------------------------------------------------------- //

	/**
	* I EXTEND the request timeout by the given seconds using the native CFSettings tag.
	*/
	public void function requestExtendTimeout( required numeric timeoutInSeconds ) {

		// CAUTION: Your ColdFusion platform needs to have permissions to access Java
		// objects in order to use this (I think).
		var currentTimeout = createObject( "java", "coldfusion.runtime.RequestMonitor" )
			.getRequestTimeout()
		;

		cfsetting(
			requestTimeout = ( currentTimeout + timeoutInSeconds )
		);

	}

	// ... truncated - other two methods are the same in first example ... //

</cfscript>

This approach is more akin to the approach that I used with Lucee CFML.

Want to use code from this post? Check out the license.

Reader Comments

Post A Comment — I'd Love To Hear From You!

Post a Comment

I believe in love. I believe in compassion. I believe in human rights. I believe that we can afford to give more of these gifts to the world around us because it costs us nothing to be decent and kind and understanding. And, I want you to know that when you land on this site, you are accepted for who you are, no matter how you identify, what truths you live, or whatever kind of goofy shit makes you feel alive! Rock on with your bad self!
Ben Nadel