Is it possible to access the matrix parameters (name-value pair separated by semicolon) in ColdFusion?

StackOverflow https://stackoverflow.com/questions/19253722

  •  30-06-2022
  •  | 
  •  

Question

I'm new to matrix parameter and I know CF10 can access them through their new RESTful API support.

However, is there a way to access these parameters without using RESTful API support?

E.g. http://moremaps.com/map/color.cfm;lat=50;long=20;scale=32000

Was it helpful?

Solution

You can use:

color.cfm;lat=50;long=20;scale=32000

Then get the param string with:

ListRest(getPageContext().getRequest().getRequestUri(),';')

This worked back in CFMX - it's not specific to CF10 or part of the RESTful API, and is available due to the servlet container (Tomcat/Jrun/etc) following the servlet spec with the ability to get the original URL.

(And you can of course use URL rewriting to hide the .cfm from the user.)


There isn't a matrix scope because CF hasn't implemented it fully - it is done as part of REST webservices, (where it's as an argument with the appropriate RestArgSource attribute). Only the CF team can say why they designed it that way.

However, you can easily create your own scope/struct like so:

var MatrixString = ListRest(getPageContext().getRequest().getRequestUri(),';');
var Matrix = {};

for ( var CurParam in ListToArray(MatrixString,';') )
    Matrix[ UrlDecode( ListFirst(CurParam,'=') ) ] = UrlDecode( ListRest(CurParam,'=') );

(Obviously, remove the var scoping if not using inside a function.)

That works both directly and via IIS, and should work fine on other servers too, even where path_info may have been modified.


Update: This answer is incomplete/inaccurate.

Reading up further on matrix params, they can actually appear at any point in the request_uri (the entire part after the host_name, before the query_string) - that is, both script_name and path_info can contain parameters, without affecting their final value.

To clarify this, both these URLs:

htp://domain.com/a/b.cfm/c/d
http://domain.com/a;alpha=1/b.cfm;beta=2/c;gamma=3/d;delta=4

Result in these CGI vars:

script_name = /a/b.cfm
path_info = /c/d

(Except in IIS, where path_info is incorrectly implemented.)

Obviously extracting and acting upon these properties is more complex than the code above - I'll update this answer again once I've made sure I understand them more fully.

In the meantime, here's a couple of potential options - the first returns a struct of params if a path element has one, the second returns an array containing every path element - whether either of these are suitable will depend on how the matrix params are to be used:

<cffunction name="getMatrixStruct" returntype="Struct" output=false
    hint="Returns struct with item for each path element with params"
    >
    <cfargument name="RequestUri" type="String" required hint="The non-host and non-querystring part of a URL." />
    <cfscript>
        var Result = {};

        for ( var CurSegment in ListToArray(RequestUri,'/') )
        {
            var SegName = UrlDecode( ListFirst(CurSegment,';') );

            for ( var CurParam in ListToArray(ListRest(CurSegment,';')) )
                Result[SegName][UrlDecode( ListFirst(CurParam,'=') ) ] = UrlDecode( ListRest(CurParam,'=') );

        }

        return Result;
    </cfscript>
</cffunction>


<cffunction name="getMatrixArray" returntype="Array" output=false
    hint="Returns array of structs for all path element, with any parameters included."
    >
    <cfargument name="RequestUri" type="String" required hint="The non-host and non-querystring part of a URL." />
    <cfscript>
        var Result = [];
        var Pos = 0;

        for ( var CurSegment in ListToArray(RequestUri,'/') )
        {
            Result[++Pos] = { 'Name' = UrlDecode( ListFirst(CurSegment,';') ) };

            for ( var CurParam in ListToArray(ListRest(CurSegment,';')) )
                Result[Pos][UrlDecode( ListFirst(CurParam,'=') ) ] = UrlDecode( ListRest(CurParam,'=') );

        }

        return Result;
    </cfscript>
</cffunction>

OTHER TIPS

You can access it via cgi.path_info. For example:

 http://localhost/myApp/index.cfm;this=that;pet=cat

Becomes

cgi.PATH_INFO=/MyApp/index.cfm;this=that;pet=cat

Then you can

struct function getMatrix() output="false"  {

   var arURLData = ListToArray(cgi.path_Info, ";");

   var stData = {};

   if (arrayLen(arData) <= 1) {
      return stData;
   }

   for(var i = 2; i <= ArrayLen(arData); i++) {

     // setVariable("stData.#listfirst(arURLData[i], "=")#", listlast(arURLData[i]);
     stData[listfirst(arURLData[i], "=")] = getToken(arURLData[i], 2, "=");
   }

   return stData;
}

You will probably want to add some code to protect against URL injection attacks.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top