Posted March 3, 2008 at
9:29 AM
Tags:
ColdFusion
There was a chance that I was going to have to write a ColdFusion script that integrated with SalesForce.com. This script would have to login into a SalesForce.com, submit some report criteria, then download an Excel report file. I have done a lot of work with ColdFusion's CFHttp and CFHttpParam tags, so I wasn't too worries about the script; however, I felt that I could come up with a way to make this kind of work easier, not just for SalesForce.com, but for session-oriented CFHttp calls in general. To do this, I created the CFHTTPSession.cfc ColdFusion component. This ColdFusion component is meant to mimic a "real" browser session by wrapping around ColdFusion CFHttp calls and taking care of all the sending and receiving of session cookies behind the scenes. This way, you just make your Get() and Post() calls though the CFHTTPSession.cfc and it will take care of maintaining your session data.
To demonstrate this API action, I am going to run a quick example that logs into Dig Deep Fitness, my iPhone fitness application, and then makes a second page request to grab the list of exercises. The list-grab will only work if the second request announces itself as being part of the same session:
Launch code in new window » Download code as text file »
- <cfset objHttpSession = CreateObject(
- "component",
- "CFHTTPSession"
- ).Init()
- />
-
-
- <cfset objResponse = objHttpSession
- .NewRequest( "http://www.digdeepfitness.com/index.cfm" )
- .AddFormField( "go", "login" )
- .AddFormField( "submitted", 1 )
- .AddFormField( "email", "ben@XXXXXXXX.com" )
- .AddFormField( "password", "YYYYYYYYYYYYY" )
- .Post()
- />
-
- <cfset objResponse = objHttpSession
- .NewRequest( "http://www.digdeepfitness.com/index.cfm" )
- .AddUrl( "go", "exercises" )
- .Get()
- />
-
-
- <cfoutput>
- #objResponse.FileContent#
- </cfoutput>
As you can see, we are creating an instance of the CFHTTPSession.cfc. Then, we create a NewRequest() for the login page, and Post() the data. Then, using the same CFHTTPSession.cfc instance, we create a second request and Get() the data for the exercises list. Running the above code, we get the following response content:
As you can see, we have maintained the session information across multiple ColdFusion CFHttp calls and gotten the secure page data.
The API for ColdFusion component is fairly simple and can handle the most common CFHttp use-cases (I didn't bother building them all in because I simply don't use them all). Whenever you want to create a new request, you use the NewRequest() method. This takes the URL of the request and prepares the object for a new request. Then, you have the Get() method and the Post() method which just uses the different actions (GET vs. POST). Get() and Post() both return the contents of the CFHttp call.
In between those method calls, you have the chance to add data to the outgoing request parameters. This can be done through AddParam() or through the easier, utility methods:
- AddCGI( Name, Value [, Encoded ] )
- AddCookie( Name, Value )
- AddFile( Name, Path [, MimeType ] )
- AddFormField( Name, Value [, Encoded ] )
- AddHeader( Name, Value )
- AddUrl( Name, Value )
- SetBody( Value )
- SetUserAgent( Value )
- SetXml( Value )
All of these methods return the THIS pointer to the CFHTTPSession.cfc instance so that these methods can be chained together for convenience.
The CFHTTPSession.cfc instance can be used on a single page or it can be cached in a persistent scope to be used across multiple page calls in the user's application. Of course, if the remote session times out, then the login will have to be created again - the object does not handle this for you.
I have not thoroughly tested this because, well frankly, I don't use CFHttp for many different use cases. However, much of the API relies on calling other parts of the API. As such, any bugs that pop up should be extremely easy to locate and iron out. Here is the code that is powers the CFHTTPSession.cfc ColdFusion component:
Launch code in new window » Download code as text file »
- <cfcomponent
- output="false"
- hint="Handles a CFHTTP session by sending an receving cookies behind the scenes.">
-
- <cfset VARIABLES.Instance = {} />
-
- <cfset VARIABLES.Instance.Cookies = {} />
-
- <cfset VARIABLES.Instance.RequestData = {} />
- <cfset VARIABLES.Instance.RequestData.Url = "" />
- <cfset VARIABLES.Instance.RequestData.UserAgent = "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.8.1.6) Gecko/20070725 Firefox/2.0.0.6" />
- <cfset VARIABLES.Instance.RequestData.Params = [] />
-
-
- <cffunction
- name="Init"
- access="public"
- returntype="any"
- output="false"
- hint="Returns an initialized component.">
-
- <cfargument
- name="UserAgent"
- type="string"
- required="false"
- hint="The user agent that will be used on the subseqent page requests."
- />
-
- <cfif StructKeyExists( ARGUMENTS, "UserAgent" )>
- <cfset THIS.SetUserAgent( ARGUMENTS.UserAgent ) />
- </cfif>
-
- <cfreturn THIS />
- </cffunction>
-
-
- <cffunction
- name="AddCGI"
- access="public"
- returntype="any"
- output="false"
- hint="Adds a CGI value. Returns THIS scope for method chaining.">
-
- <cfargument
- name="Name"
- type="string"
- required="true"
- hint="The name of the CGI value."
- />
-
- <cfargument
- name="Value"
- type="string"
- required="true"
- hint="The CGI value."
- />
-
- <cfargument
- name="Encoded"
- type="string"
- required="false"
- default="yes"
- hint="Determins whether or not to encode the CGI value."
- />
-
- <cfreturn THIS.AddParam(
- Type = "CGI",
- Name = ARGUMENTS.Name,
- Value = ARGUMENTS.Value,
- Encoded = ARGUMENTS.Encoded
- ) />
- </cffunction>
-
-
- <cffunction
- name="AddCookie"
- access="public"
- returntype="any"
- output="false"
- hint="Adds a cookie value. Returns THIS scope for method chaining.">
-
- <cfargument
- name="Name"
- type="string"
- required="true"
- hint="The name of the CGI value."
- />
-
- <cfargument
- name="Value"
- type="string"
- required="true"
- hint="The CGI value."
- />
-
- <cfreturn THIS.AddParam(
- Type = "Cookie",
- Name = ARGUMENTS.Name,
- Value = ARGUMENTS.Value
- ) />
- </cffunction>
-
-
- <cffunction
- name="AddFile"
- access="public"
- returntype="any"
- output="false"
- hint="Adds a file value. Returns THIS scope for method chaining.">
-
- <cfargument
- name="Name"
- type="string"
- required="true"
- hint="The name of the form field for the posted file."
- />
-
- <cfargument
- name="Path"
- type="string"
- required="true"
- hint="The expanded path to the file."
- />
-
- <cfargument
- name="MimeType"
- type="string"
- required="false"
- default="application/octet-stream"
- hint="The mime type of the posted file. Defaults to *unknown* mime type."
- />
-
- <cfreturn THIS.AddParam(
- Type = "Cookie",
- Name = ARGUMENTS.Name,
- Value = ARGUMENTS.Value
- ) />
- </cffunction>
-
-
- <cffunction
- name="AddFormField"
- access="public"
- returntype="any"
- output="false"
- hint="Adds a form value. Returns THIS scope for method chaining.">
-
- <cfargument
- name="Name"
- type="string"
- required="true"
- hint="The name of the form field."
- />
-
- <cfargument
- name="Value"
- type="string"
- required="true"
- hint="The form field value."
- />
-
- <cfargument
- name="Encoded"
- type="string"
- required="false"
- default="yes"
- hint="Determins whether or not to encode the form value."
- />
-
- <cfreturn THIS.AddParam(
- Type = "FormField",
- Name = ARGUMENTS.Name,
- Value = ARGUMENTS.Value,
- Encoded = ARGUMENTS.Encoded
- ) />
- </cffunction>
-
-
- <cffunction
- name="AddHeader"
- access="public"
- returntype="any"
- output="false"
- hint="Adds a header value. Returns THIS scope for method chaining.">
-
- <cfargument
- name="Name"
- type="string"
- required="true"
- hint="The name of the header value."
- />
-
- <cfargument
- name="Value"
- type="string"
- required="true"
- hint="The header value."
- />
-
- <cfreturn THIS.AddParam(
- Type = "Header",
- Name = ARGUMENTS.Name,
- Value = ARGUMENTS.Value
- ) />
- </cffunction>
-
-
- <cffunction
- name="AddParam"
- access="public"
- returntype="any"
- output="false"
- hint="Adds a CFHttpParam data point. Returns THIS scope for method chaining.">
-
- <cfargument
- name="Type"
- type="string"
- required="true"
- hint="The type of data point."
- />
-
- <cfargument
- name="Name"
- type="string"
- required="true"
- hint="The name of the data point."
- />
-
- <cfargument
- name="Value"
- type="any"
- required="true"
- hint="The value of the data point."
- />
-
- <cfargument
- name="File"
- type="string"
- required="false"
- default=""
- hint="The expanded path to be used if the data piont is a file."
- />
-
- <cfargument
- name="MimeType"
- type="string"
- required="false"
- default=""
- hint="The mime type of the file being passed (if file is being passed)."
- />
-
- <cfargument
- name="Encoded"
- type="string"
- required="false"
- default="yes"
- hint="The determines whether or not to encode Form Field and CGI values."
- />
-
- <cfset var LOCAL = {} />
-
- <cfswitch expression="#ARGUMENTS.Type#">
-
- <cfcase value="Body">
-
- <cfset LOCAL.Param = {
- Type = ARGUMENTS.Type,
- Value = ARGUMENTS.Value
- } />
-
- </cfcase>
-
- <cfcase value="CGI">
-
- <cfset LOCAL.Param = {
- Type = ARGUMENTS.Type,
- Name = ARGUMENTS.Name,
- Value = ARGUMENTS.Value,
- Encoded = ARGUMENTS.Encoded
- } />
-
- </cfcase>
-
- <cfcase value="Cookie">
-
- <cfset LOCAL.Param = {
- Type = ARGUMENTS.Type,
- Name = ARGUMENTS.Name,
- Value = ARGUMENTS.Value
- } />
-
- </cfcase>
-
- <cfcase value="File">
-
- <cfset LOCAL.Param = {
- Type = ARGUMENTS.Type,
- Name = ARGUMENTS.Name,
- File = ARGUMENTS.File,
- MimeType = ARGUMENTS.MimeType
- } />
-
- </cfcase>
-
- <cfcase value="FormField">
-
- <cfset LOCAL.Param = {
- Type = ARGUMENTS.Type,
- Name = ARGUMENTS.Name,
- Value = ARGUMENTS.Value,
- Encoded = ARGUMENTS.Encoded
- } />
-
- </cfcase>
-
- <cfcase value="Header">
-
- <cfset LOCAL.Param = {
- Type = ARGUMENTS.Type,
- Name = ARGUMENTS.Name,
- Value = ARGUMENTS.Value
- } />
-
- </cfcase>
-
- <cfcase value="Url">
-
- <cfset LOCAL.Param = {
- Type = ARGUMENTS.Type,
- Name = ARGUMENTS.Name,
- Value = ARGUMENTS.Value
- } />
-
- </cfcase>
-
- <cfcase value="Xml">
-
- <cfset LOCAL.Param = {
- Type = ARGUMENTS.Type,
- Value = ARGUMENTS.Value
- } />
-
- </cfcase>
-
- </cfswitch>
-
-
- <cfset ArrayAppend(
- VARIABLES.Instance.RequestData.Params,
- LOCAL.Param
- ) />
-
- <cfreturn THIS />
- </cffunction>
-
-
- <cffunction
- name="AddUrl"
- access="public"
- returntype="any"
- output="false"
- hint="Adds a url value. Returns THIS scope for method chaining.">
-
- <cfargument
- name="Name"
- type="string"
- required="true"
- hint="The name of the header value."
- />
-
- <cfargument
- name="Value"
- type="string"
- required="true"
- hint="The header value."
- />
-
- <cfreturn THIS.AddParam(
- Type = "Url",
- Name = ARGUMENTS.Name,
- Value = ARGUMENTS.Value
- ) />
- </cffunction>
-
-
- <cffunction
- name="Get"
- access="public"
- returntype="struct"
- output="false"
- hint="Uses the GET method to place the next request. Returns the CFHttp response.">
-
- <cfargument
- name="GetAsBinary"
- type="string"
- required="false"
- default="auto"
- hint="Determines how to return the file content - return as binary value."
- />
-
- <cfreturn THIS.Request(
- Method = "get",
- GetAsBinary = ARGUMENTS.GetAsBinary
- ) />
- </cffunction>
-
-
- <cffunction
- name="GetCookies"
- access="public"
- returntype="struct"
- output="false"
- hint="Returns the internal session cookies.">
-
- <cfreturn VARIABLES.Instance.Cookies />
- </cffunction>
-
-
- <cffunction
- name="NewRequest"
- access="public"
- returntype="any"
- output="false"
- hint="Sets up the object for a new request. Returns THIS scope for method chaining.">
-
- <cfargument
- name="Url"
- type="string"
- required="true"
- hint="The URL for the new request."
- />
-
- <cfset VARIABLES.Instance.RequestData.Url = ARGUMENTS.Url />
-
- <cfset VARIABLES.Instance.RequestData.Params = [] />
-
- <cfreturn THIS />
- </cffunction>
-
-
- <cffunction
- name="Post"
- access="public"
- returntype="struct"
- output="false"
- hint="Uses the POST method to place the next request. Returns the CFHttp response.">
-
- <cfargument
- name="GetAsBinary"
- type="string"
- required="false"
- default="auto"
- hint="Determines how to return the file content - return as binary value."
- />
-
- <cfreturn THIS.Request(
- Method = "post",
- GetAsBinary = ARGUMENTS.GetAsBinary
- ) />
- </cffunction>
-
-
- <cffunction
- name="Request"
- access="public"
- returntype="struct"
- output="false"
- hint="Performs the CFHttp request and returns the response.">
-
- <cfargument
- name="Method"
- type="string"
- required="false"
- default="get"
- hint="The type of request to make."
- />
-
- <cfargument
- name="GetAsBinary"
- type="string"
- required="false"
- default="auto"
- hint="Determines how to return body."
- />
-
- <cfset var LOCAL = {} />
-
- <cfhttp
- url="#VARIABLES.Instance.RequestData.Url#"
- method="#ARGUMENTS.Method#"
- useragent="#VARIABLES.Instance.RequestData.UserAgent#"
- getasbinary="#ARGUMENTS.GetAsBinary#"
- redirect="no"
- result="LOCAL.Get">
-
- <cfloop
- item="LOCAL.Key"
- collection="#VARIABLES.Instance.Cookies#">
-
- <cfhttpparam
- type="cookie"
- name="#LOCAL.Key#"
- value="#VARIABLES.Instance.Cookies[ LOCAL.Key ].Value#"
- />
-
- </cfloop>
-
-
-
-
- <cfloop
- index="LOCAL.Param"
- array="#VARIABLES.Instance.RequestData.Params#">
-
- <cfhttpparam
- attributecollection="#LOCAL.Param#"
- />
-
- </cfloop>
-
- </cfhttp>
-
-
- <cfset StoreResponseCookies( LOCAL.Get ) />
-
-
- <cfif StructKeyExists( LOCAL.Get.ResponseHeader, "Location" )>
-
- <cfif REFindNoCase(
- "^http",
- LOCAL.Get.ResponseHeader.Location
- )>
-
- <cfreturn THIS
- .NewRequest( LOCAL.Get.ResponseHeader.Location )
- .Get()
- />
-
- <cfelse>
-
- <cfreturn THIS
- .NewRequest(
- GetDirectoryFromPath( VARIABLES.Instance.RequestData.Url ) &
- LOCAL.Get.ResponseHeader.Location
- )
- .Get()
- />
-
- </cfif>
-
- <cfelse>
-
- <cfreturn LOCAL.Get />
-
- </cfif>
- </cffunction>
-
-
- <cffunction
- name="SetBody"
- access="public"
- returntype="any"
- output="false"
- hint="Sets the body data of next request. Returns THIS scope for method chaining.">
-
- <cfargument
- name="Value"
- type="any"
- required="false"
- hint="The data body."
- />
-
- <cfreturn THIS.AddParam(
- Type = "Body",
- Name = "",
- Value = ARGUMENTS.Value
- ) />
- </cffunction>
-
-
- <cffunction
- name="SetUserAgent"
- access="public"
- returntype="any"
- output="false"
- hint="Sets the user agent for next request. Returns THIS scope for method chaining.">
-
- <cfargument
- name="Value"
- type="string"
- required="false"
- hint="The user agent that will be used on the subseqent page requests."
- />
-
- <cfset VARIABLES.Instance.RequestData.UserAgent = ARGUMENTS.UserAgent />
-
- <cfreturn THIS />
- </cffunction>
-
-
- <cffunction
- name="SetXml"
- access="public"
- returntype="any"
- output="false"
- hint="Sets the XML body data of next request. Returns THIS scope for method chaining.">
-
- <cfargument
- name="Value"
- type="any"
- required="false"
- hint="The data body."
- />
-
- <cfreturn THIS.AddParam(
- Type = "Xml",
- Name = "",
- Value = ARGUMENTS.Value
- ) />
- </cffunction>
-
-
- <cffunction
- name="StoreResponseCookies"
- access="public"
- returntype="void"
- output="false"
- hint="This parses the response of a CFHttp call and puts the cookies into a struct.">
-
- <cfargument
- name="Response"
- type="struct"
- required="true"
- hint="The response of a CFHttp call."
- />
-
- <cfset var LOCAL = StructNew() />
-
- <cfset LOCAL.Cookies = StructNew() />
-
- <cfif NOT StructKeyExists(
- ARGUMENTS.Response.ResponseHeader,
- "Set-Cookie"
- )>
-
- <cfreturn />
-
- </cfif>
-
-
-
-
- <cfif IsSimpleValue( ARGUMENTS.Response.ResponseHeader[ "Set-Cookie" ] )>
-
- <cfset LOCAL.ReturnedCookies = {} />
- <cfset LOCAL.ReturnedCookies[ 1 ] = ARGUMENTS.Response.ResponseHeader[ "Set-Cookie" ] />
-
- <cfelse>
-
- <cfset LOCAL.ReturnedCookies = ARGUMENTS.Response.ResponseHeader[ "Set-Cookie" ] />
-
- </cfif>
-
-
- <cfloop
- item="LOCAL.CookieIndex"
- collection="#LOCAL.ReturnedCookies#">
-
- <cfset LOCAL.CookieString = LOCAL.ReturnedCookies[ LOCAL.CookieIndex ] />
-
-
- <cfloop
- index="LOCAL.Index"
- from="1"
- to="#ListLen( LOCAL.CookieString, ';' )#"
- step="1">
-
- <cfset LOCAL.Pair = ListGetAt(
- LOCAL.CookieString,
- LOCAL.Index,
- ";"
- ) />
-
- <cfset LOCAL.Name = ListFirst( LOCAL.Pair, "=" ) />
-
- <cfif (ListLen( LOCAL.Pair, "=" ) GT 1)>
-
- <cfset LOCAL.Value = ListRest( LOCAL.Pair, "=" ) />
-
- <cfelse>
-
- <cfset LOCAL.Value = "" />
-
- </cfif>
-
-
- <cfif (LOCAL.Index EQ 1)>
-
- <cfset LOCAL.Cookies[ LOCAL.Name ] = StructNew() />
-
- <cfset LOCAL.Cookie = LOCAL.Cookies[ LOCAL.Name ] />
-
-
- <cfset LOCAL.Cookie.Value = LOCAL.Value />
-
-
- <cfset LOCAL.Cookie.Attributes = StructNew() />
-
- <cfelse>
-
- <cfset LOCAL.Cookie.Attributes[ LOCAL.Name ] = LOCAL.Value />
-
- </cfif>
-
- </cfloop>
-
-
- </cfloop>
-
-
- <cfset StructAppend(
- VARIABLES.Instance.Cookies,
- LOCAL.Cookies
- ) />
-
- <cfreturn />
- </cffunction>
-
- </cfcomponent>
I am looking forward to possibly putting this to the test with a ColdFusion / SalesForce.com integration, but really, this should work with any kind of cookie-based session application.
Download Code Snippet ZIP File
Comments (41) |
Post Comment |
Ask Ben |
Permalink |
Other Searches |
Print Page
What Other People Are Searching For
[ local search ]
maintain session cfhttp calls
dude, badass! I can see great potential for this kind of thing in programmatic, automated testing, too. Particularly "smoke test" kind of tests where you just want your tests to run through the site and make sure you don't get any 400/500 errors.
Posted by marc esher
on Mar 3, 2008
at 9:44 AM
You should riaforge this!
Posted by Raymond Camden
on Mar 3, 2008
at 12:33 PM
Hey Ben
This is cool - is there a specific reason for using Firefox as the user agent?
Dom
Posted by DrDom
on Mar 3, 2008
at 4:14 PM
Does this cfc handle cookies based on domain? I have a login that goes through several redirects between different servers, and through all the redirects, I only need to send the cookies based on the current domain. I have written something like this, but just a recursive function. It is not as clean as yours. Also does this handle the SSL certificates if I import them in the keystore?
Posted by Matthew
on Mar 3, 2008
at 7:49 PM
Thanks, great post and source. This gives me a great example of coding, cause I´m still learning. Is there a special reason why to use Firefox as client?
Posted by Werbeagentur
on Mar 5, 2008
at 4:11 AM
@DrDom,
I use FireFox cause when I make a web call, I like to announce myself as the most awesome browser in town :)
@Matthew,
I never considered changing domains. I guess, this would just keep accumulating cookies and then send them across no matter what the next domain is. Since it manually follows the Location redirects sent back by CFLocation type tags, I think it will keep sending cookies.
Do you think I should make the cookies domain based? I could keep all the information keyed in a structure that is domain specific.
@Ray,
When I get some time, I will put it up.
Posted by Ben Nadel
on Mar 6, 2008
at 8:47 AM
No you dont have to worry about domain cookies. For my situation i just needed to hold onto the last set of cookies for that last redirect that was made.
I just dont want to send unecessary cookies. Once all the redirects happened, i just need the cookies from that final redirect.
Good job ben.
-Matthew
Posted by Matthew
on Mar 6, 2008
at 11:41 AM
@Matthew,
Sounds good. If you see anywhere that this can be improved, let me know.
Posted by Ben Nadel
on Mar 6, 2008
at 11:47 AM
I was trying to write something like this the other day... couldn't figure it out and gave up. But THIS IS TOO COOL. Thanks for the lesson. Can't wait to try it out.
Posted by Alan Johnson
on Mar 10, 2008
at 11:29 PM
@Alan,
Glad you are excited about this. Let me know if you see any ways that it can be improved.
Posted by Ben Nadel
on Mar 11, 2008
at 7:20 AM
Coldfusion Server complained about the invalid token '{' in CFHTTPSession.cfc. Is it because we are running CFMX 6.1?
Posted by Joshua Shaffner
on Mar 12, 2008
at 4:24 PM
@Joshua,
Yeah, that's a version issue. This is ColdFusion 8 compatible code. The {} notation is an implicit struct. YOu can try to replace things like:
<cfset var LOCAL = {} />
... with:
<cfset var LOCAL = StructNew() />
There might be some other areas that are not compatible as well, but I believe that all of this should be able to be converted in ColdFusion MX 6 compatible.
Unfortunately, I don't have access to an MX6 machine and cannot test any of the code.
Posted by Ben Nadel
on Mar 12, 2008
at 4:40 PM
Okay. What about []? Put in ArrayNew(1)?
After I did just that, I am now looking at this piece of code where attribute, "array" is not supported.
<cfloop index="LOCAL.Param" array="#VARIABLES.Instance.RequestData.Params#">
Posted by Joshua Shaffner
on Mar 12, 2008
at 5:26 PM
@Joshua,
<cfloop index="LOCAL.Param" array="#VARIABLES.Instance.RequestData.Params#">
Becomes:
<cfloop
index="LOCAL.ParamIndex"
from="1"
to="#ArrayLen( VARIABLES.Instance.RequestData.Params )#"
step="1">
<!--- Get short hand to next param. --->
<cfset LOCAL.Param = VARIABLES.Instance.RequestData.Params[ LOCAL.ParamIndex] />
Posted by Ben Nadel
on Mar 12, 2008
at 5:29 PM
@Ben
I am now looking at the error where cfhttpparam's attribute, "attributecollection" is not supported.
Note: It has been few years since I last worked with ColdFusion. Much appreciated for your help!
Posted by Joshua Shaffner
on Mar 12, 2008
at 5:36 PM
@Joshua,
Oooh :( That's a bit of a tougher one! You have to take a little bit more code here to actually get that to work. Instead of just passing in the attribute collection, you are gonna have to define the individual CFHttpParam tags.
For example:
<cfcase value="Header">
<cfhttpparam
type="header"
name="#LOCAL.Param.Name#"
value="#LOCAL.Param.Value#"
/>
</cfcase>
<cfcase value="CGI">
<cfhttpparam
type="cgi"
name="#LOCAL.Param.Name#"
value="#LOCAL.Param.Value#"
encode="#LOCAL.Param.Encode#"
/>
</cfcase>
Basically, you have to enumerate each CFCase tag rather than just using the one tag.
Posted by Ben Nadel
on Mar 12, 2008
at 5:51 PM
@Ben
After putting in a bunch of code replacing a single line of attribute collection. I no longer get any compile error from CFHTTPSession.cfc.
I am now figuring out why I would get different JSESSIONID on every request against java/jsp off a tomcat. Am I supposed to see same JSESSION on every request?
Thanks.
Posted by Joshua Shaffner
on Mar 13, 2008
at 9:12 AM
@Joshua,
I don't know too much about jsessionID. I think you should keep it from page to page. Hmmm :( That's awesome that you got it to compile, though. Very well done.
Posted by Ben Nadel
on Mar 13, 2008
at 9:26 AM
@Joshua,
I have another person who is having trouble with maintaining session across pages. I am gonna try to debug that at lunch; I might find some good stuff. I will let you know.
Posted by Ben Nadel
on Mar 13, 2008
at 9:27 AM
Very good article.
Posted by Fredy
on Mar 13, 2008
at 10:13 AM
When you call a cfhttp it will always open up a new request, unless you store the cookie info (jsession) in a session, or some kind of persistant state.
When i do these types of things with Cfhttp, i hold on to the object in a session so the cookies persist.
Hope that makes sense.
-Matthew
Po