Skip to main content
Ben Nadel at CFUNITED 2008 (Washington, D.C.) with: John Mason
Ben Nadel at CFUNITED 2008 (Washington, D.C.) with: John Mason

Dumping Out The CGI Scope Does Not List All Available CGI Values In ColdFusion

By
Published in Comments (22)

I had an interesting / unfortunate journey yesterday, concerning the CGI scope. I was trying to access a value that was being passed-through by the load balancer; and, since I had never dealt with this value before, I naturally tried to CDump-out the CGI scope to see what it would be. Unfortunately, the value was not present in the CGI dump. This lead to several support tickets, which turned out to be useless since, as I am just now learning now for the first time, the CGI scope doesn't "report" all of its available keys.

Unlike a normal Struct in ColdFusion, it looks like the CGI scope will only report on a known subset of key values. You can still ask the CGI scope for which ever key you want; but, as far as CFDump and key-loops are concerned, you may only be seeing a part of the whole picture.

To demonstrate, I'm going to try to "find" the CGI value, "document_root". I will do this though both direct key reference as well as key reporting:

<cfscript>

	target = ucase( "document_root" );

	// Get the document root directly from the CGI scope.
	writeOutput( "#target#: #cgi[ target ]#" );

	writeOutput( "<br />" );
	writeOutput( "- - - - - - - - - - - - - - - - -" );
	writeOutput( "<br />" );

	// Now, try to get the value by looping of the CGI key list
	// and checking to see if the key matches our target.
	for ( key in cgi ) {

		writeOutput( key );

		if ( key == target ) {

			writeOutput( ": #cig[ key ]# <br />" );

		} else {

			writeOutput( ": . . . <br />" );

		}

	}

</cfscript>

As you can see, we try to loop over the CGI scope, looking for the "document_root" key. And, when we run the above code, we get the following output:

DOCUMENT_ROOT: /Sites/bennadel.com


HTTP_USER_AGENT: . . .
WEB_SERVER_API: . . .
PATH_TRANSLATED: . . .
CONTENT_TYPE: . . .
HTTP_ACCEPT_LANGUAGE: . . .
HTTP_REFERER: . . .
HTTP_ACCEPT: . . .
CERT_SERVER_ISSUER: . . .
CERT_SERVER_SUBJECT: . . .
HTTP_ACCEPT_ENCODING: . . .
SERVER_SOFTWARE: . . .
SERVER_NAME: . . .
CF_TEMPLATE_PATH: . . .
CERT_FLAGS: . . .
HTTPS_SERVER_ISSUER: . . .
CONTEXT_PATH: . . .
HTTP_COOKIE: . . .
SERVER_PROTOCOL: . . .
CERT_SECRETKEYSIZE: . . .
REQUEST_METHOD: . . .
HTTPS_SECRETKEYSIZE: . . .
AUTH_PASSWORD: . . .
HTTPS: . . .
CERT_SERIALNUMBER: . . .
CERT_SUBJECT: . . .
SERVER_PORT: . . .
CERT_KEYSIZE: . . .
SCRIPT_NAME: . . .
REMOTE_ADDR: . . .
SERVER_PORT_SECURE: . . .
REMOTE_HOST: . . .
HTTPS_KEYSIZE: . . .
HTTP_HOST: . . .
HTTP_CONNECTION: . . .
AUTH_USER: . . .
REMOTE_USER: . . .
PATH_INFO: . . .
QUERY_STRING: . . .
CERT_ISSUER: . . .
CERT_COOKIE: . . .
HTTPS_SERVER_SUBJECT: . . .
GATEWAY_INTERFACE: . . .
AUTH_TYPE: . . .
CONTENT_LENGTH: . . .

As you can see, while we were able to directly reference the "document_root" key, the CGI scope does not "report" it as a known value. Unfortunately, this little quirk of the language cost me a few hours of head-scratching and support tickets. Hopefully this will prevent you from doing the same!

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

Reader Comments

34 Comments

This is also the reason that the CGI doesn't throw errors if you request variables that don't actually exist. If you ask for CGI["OMGTHISISBAD"] all you get is an empty string, not some kind of undefined error.

15,848 Comments

@Jon,

Word. And, I actually like that particular feature! I find that it makes easier to write conditionals without having to do things like:

if ( structKeyExists( cgi, "xyz" ) && len( cgi.xyz ) ) { .. }

... just simply go:

if ( len( cgi.xyz ) ) { .. }

Much easier :)

2 Comments

I found this issue a couple years ago when I noticed one of custom Apache CGI variables wouldn't show up in our CGI dumps.

In order to get the custom variable to show up, I used structCopy/structInsert and then dumped the new customCGI scope:

<cfset customCGI = structCopy(cgi) />
<cfset structInsert(customCGI,"WEB_ENV",cgi.web_env) />
<cfdump var="#customCGI#" label="CGI object" />

Now all CGI variables are dumped. :-)

15,848 Comments

@David,

Thanks for the typo. I didn't catch it because the IF-statement never fires (hence no exception). I'll fix that after work.

71 Comments

This makes no sense to me.

A scope that behaves in a unique manner to other scopes. I'm find that scopes have some core differences, like whether they are persistent or not, but when I tell something to dump, you best give up the goods... and NOT be taking a cut off the top.

Gotta say, I'm not liking CGI acting in this manner. If the variables are there, show them. If you reference a variable that doesn't exist, throw an error (even to Ben's dismay) :) One of the core truths we try to hold onto when coding is that we stay consistent with our methodologies and don't invoke a haphazard logic that does Action A THIS way, but would in other instances perform Action A THAT way.

Consistency!

34 Comments

@Aaron,

I'm with you; I absolutely hate that CGI gives back empty strings. Its essentially a unique behavior that goes against all documentation and language expectations.

15,848 Comments

@Aaron, @Jon,

It would be cool if ColdFusion implemented the "Elvis Operator" that does a sort of conditional check:

var value = structKeyExists( cgi, "foo" ) ? cgi.foo : "";
 
var value = cgi.foo ?: ""

I saw this in a presentation on Groovy. It's sort of a short-hand for the conditional check / ternary operator.

1 Comments

@Aaron @Jon

Agreed, it makes no sense. Has someone raised a bug with adobe/railo that I can vote on?

Really the only way to find out what is there right now is to do a brute force on the cgi scope to see what is hidden away. Not cool :(

1 Comments

@Ben,
CF9 & CF10 both support the "Elvis" syntax that you list -- I've got production code running it now. I was introduced to it by a front-end guy who asked if it was possible and I was like -- what is that?!?

Turns out it worked and I said goodbye to IIF and silly if else variable sets forever!

That syntax is what IIF dreams of at night...

71 Comments

@Ben,

The closest I use is:

<cfset x = iif( structKeyExists( CGI, 'foo' ), de( 'this' ), de( 'that' ) ) />

Seems to work well enough, but it's not as sunccinct. :)

27 Comments

Fyi you can get all those vars via any decent debugging tools that shows u all http headers such as chrome developer tools and several firefox plugins

71 Comments

@snake,

Absolutely. I've sent the developers of Firebug and the Web Developer Toolbar money because I freaking LOVE those tools, but it *is* still 1 more step you'd have to take to make up for an odd shortcoming with ColdFusion.

Maybe introduce a new application variable, if Adobe wants to keep it like it is so bad.

<cfset this.GimmeAllDaDangVarsInDaClientScopeWhenIAskFerDem = true />

27 Comments

@Aaron,

If you have those tools Installed which I think most devs do now, it's not really an extra step. And tbh I think anyone who is not a newb must be used to the deficiencies in cf by now or switched to Railo :)

14 Comments

@Jason The "Elvis operator" is the "?:" in Ben's second example. CF9 doesn't support this and I don't believe CF10 does either, but Railo 4.1 does.

I think you must mean the "ternery operator" in Ben's first example.

1 Comments

Coldfusion absolutely has the ternary operator with <boolean expression> ? <true op> : <false op>. See Ben's page on it at:

www.bennadel.com/blog/1643-Learning-ColdFusion-9-The-Ternary-Operator.htm

We use Smart Cards here to login in and the person's info is dumped into variables in the CGI scope with the single sign on. Unfortunatley not all the variables show up in Coldfusion. I wrote an ASP page to dump all of them out and they are all there in the ASP page. However in Coldfusion, 3 of them are missing such as the person's middle name and couple of others. I don't know if this is because of tomcat or Coldfusion.

3 Comments

deja vu ..
i was really convinced you already posted something like this many moons ago, but since the collective memory of the human race (google) does not record it, it does not exist

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