Skip to main content
Ben Nadel
On User Experience (UX) Design, JavaScript, ColdFusion, Node.js, Life, and Love.

Spreading Http And HttpParam Tags Across Multiple Function Calls In Lucee CFML 5.3.8.201

By Ben Nadel on
Tags: ColdFusion

Back when InVision was running on Adobe ColdFusion 10, I leaned heavily on the native Http.cfc component when making network requests. However, once we switched over to Lucee CFML 5.3, where tag support in CFScript is much more robust, I found myself reverting back to the http and httpParam tags for network requests. There's something I find so elegant about the syntax of tags and their builder-like pattern of construction. One nice about using the Http.cfc ColdFusion component, however, is that it can be passed around and augmented such as with the injection of tracing headers. This got me thinking about augmenting http tags with httpParam tags; and, whether such an augmentation could be spread across function calls in Lucee CFML 5.3.8.201.

This isn't the first time that I've considered such a pattern. Last year, I demonstrated that you could compose a SQL statement along with its cfqueryparam tags across multiple function calls. At the time, I didn't know if that was something specific to the cfquery tags; or, if that was a technique that would generally work with all tags in Lucee CFML.

To explore this concept, I'm going to create a page that composes httpParam tags inside Function calls. Then, I'm going to make an HTTP request to an end-point that echoes the incoming HTTP headers in its response. First, let's just take a look at the target.cfm template - our HTTP end-point:

<cfscript>

	// Extract inbound HTTP headers.
	incomingHeaders = getHttpRequestData( false ).headers;

	// Prepare HTTP headers to be echoed in BODY of response.
	serializedHeaders = serializeJson( incomingHeaders );
	responsePayload = charsetDecode( serializedHeaders, "utf8" );

	content
		type = "application/json; charset=utf8"
		variable = responsePayload
	;

</cfscript>

As you can see, this simply grabs the .headers property out of the request context, serializes it as JSON (JavaScript Object Notation), and dumps it in to the response body.

Now, we can go about generating that request using the http tag and several httpParam tags. Note that two of the httpParam tags are defined in UDFs (User Defined Functions):

<cfscript>

	// Construct the root URL that we are going to hit (sibling to this template).
	host = "http://#cgi.server_name#:#cgi.server_port#";
	wwwRoot = getDirectoryFromPath( cgi.script_name );
	targetUrl = ( host & wwwRoot & "target.cfm" );

	// The "target.cfm" end-point does nothing but serialize and return the incoming HTTP
	// HEADERS as a JSON (JavaScript Object Notation) payload. Our goal here is to see if
	// we can compose that set of HTTP headers across a series of Function calls.
	http
		result = "targetResponse"
		method = "get"
		url = targetUrl
		{

		// Gather "httpParam" TAGS across external function calls.
		injectAuthorizationHeaders();
		injectTracingHeaders();

		// Mix-in our own "local" header.
		httpParam
			type = "header"
			name = "X-Meep"
			value = "moop"
		;
	}

	// Output the HTTP HEADERS that the target end-point found and returned.
	dump( deserializeJson( targetResponse.fileContent ) );

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

	/**
	* I apply the Authorization HTTP header to the current HTTP context.
	*/
	public void function injectAuthorizationHeaders() {

		httpParam
			type = "header"
			name = "Authorization"
			value = "Bearer: ICANHASCHEEZEBURGER"
		;

	}


	/**
	* I apply the tracing HTTP headers to the current HTTP context.
	*/
	public void function injectTracingHeaders() {

		param
			name = "request.requestID"
			type = "string"
			default = "request-#createUuid()#"
		;

		httpParam
			type = "header"
			name = "X-Request-ID"
			value = request.requestID
		;

	}

</cfscript>

As you can see, inside our http tag context, we're calling two methods:

  • injectAuthorizationHeaders()
  • injectTracingHeaders()

Each of these methods contains an httpParam tag that magically attaches to and augments the http context in current the call-stack. And, when we run this ColdFusion template, we get the following output:

HTTP headers echoed in a ColdFusion API response.

As you can see, all three httpParam header values were attached to the outgoing HTTP request. This demonstrates that http and httpParam tags can be aggregated across several method calls. This means that we can easily create functions that apply "behaviors" (such as Authorization and Tracing) to any contextual http tag in our application.

Freaking Lucee CFML - it's just awesome!



Reader Comments

@Gavin,

That looks pretty cool. I feel like I've heard you all talk about that on the Modernize or Die show. Looks like it has a lot of flexibility. And, the ability to set defaults across the board is very nice. 💪

Reply to this Comment

Post A Comment

You — Get Out Of My Dreams, Get Into My Blog
Live in the Now
Oops!
Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.