tracker issue : CF-4198298

select a category, or use search below
(searches all categories and all time range)
Title:

[ANeff] Bug for: RestSetResponse() ignored if returntype non-void (CF-3546046 regression)

| View in Tracker

Status/Resolution/Reason: Closed/Fixed/Fixed

Reporter/Name(from Bugbase): Aaron Neff / Aaron Neff ()

Created: 02/01/2017

Components: REST Services

Versions: 2016

Failure Type: Incorrectly functioning

Found In Build/Fixed In Build: 2016.0.01.298513 / 2018.0.0.303768

Priority/Frequency: Normal / Some users will encounter

Locale/System: / Win All

Vote Count: 1

History: The fix for CF-3546046 allows RestSetResponse() to be used even when the containing functions returntype is non-void. Good.

Issue: The fix for CF-3546046 introduced a regression wherein RestSetResponse() is ignored if the containing function's returntype non-void. Bad.

Repro:

1) Run index.cfm
2) Run mypage.cfm

Application.cfc
--------------------------------------------
component {
	THIS.name = "ticket_3546046NotFixedProperly";
	THIS.secureJSONPrefix="";
	THIS.mappings["/mymapping"] = expandPath("./");
	THIS.restSettings.skipCFCWithError = true;
	public void function onApplicationStart() {
	  restInitApplication("/mymapping", "MyRestApp");
	}
	public boolean function onRequestStart() {
	  if(structKeyExists(URL, "reinit")) {
		applicationStop();
		location(url='http://' & CGI.HTTP_HOST & getDirectoryFromPath(CGI.SCRIPT_NAME));
	  }
	  return true;
	}
}
--------------------------------------------

index.cfm (empty file)

MyCFC.cfc
--------------------------------------------
component rest="true" restpath="cfcrestpath" {
	remote void function returnVoid(string foobar restargsource="path") httpmethod="GET" restpath="void/{foobar}" produces="application/json" {
		var response = {status=404, content=serializeJSON({message="Not Found"}), headers={myHeader=ARGUMENTS.foobar}};
		if(ARGUMENTS.foobar is "foo") {
			response.status = 200;
			response.content = serializeJSON({message="Found"});
		}
		restSetResponse(response);
	}
	remote struct function returnNonVoid(string foobar restargsource="path") httpmethod="GET" restpath="nonvoid/{foobar}" produces="application/json" {
		var response = {status=404, content=serializeJSON({message="Not Found"}), headers={myHeader=ARGUMENTS.foobar}};
		if(ARGUMENTS.foobar is "foo") {
			response.status = 200;
			response.content = serializeJSON({message="Found"});
		}
		restSetResponse(response);
		return response;
	}
}
--------------------------------------------

mypage.cfm
--------------------------------------------
<cfscript>
  //test 1
  cfhttp(url='http://' & CGI.HTTP_HOST & '/rest/myrestapp/cfcrestpath/void/foo');//Filecontent is {"MESSAGE":"Found"} (good)
  writeDump(CFHTTP);
  //test 2
  cfhttp(url='http://' & CGI.HTTP_HOST & '/rest/myrestapp/cfcrestpath/void/bar');//Filecontent is {"MESSAGE":"Not Found"} (good)
  writeDump(CFHTTP);
  //test 3
  cfhttp(url='http://' & CGI.HTTP_HOST & '/rest/myrestapp/cfcrestpath/nonvoid/foo');//Filecontent is {"STATUS":200,"HEADERS":{"MYHEADER":"foo"},"CONTENT":"{\"MESSAGE\":\"Found\"}"} (bad - should return same as test 1)
  writeDump(CFHTTP);
  //test 4
  cfhttp(url='http://' & CGI.HTTP_HOST & '/rest/myrestapp/cfcrestpath/nonvoid/bar');//Filecontent is {"STATUS":404,"HEADERS":{"MYHEADER":"bar"},"CONTENT":"{\"MESSAGE\":\"Not Found\"}"} (bad - should return same as test 2)
  writeDump(CFHTTP);
  myCFC = new MyCFC();
  //test 5
  writeDump(serializeJSON(myCFC.returnNonVoid(foobar="foo")));//returns {"STATUS":200,"HEADERS":{"MYHEADER":"foo"},"CONTENT":"{\"MESSAGE\":\"Found\"}"} (good)
  //test 6
  writeDump(serializeJSON(myCFC.returnNonVoid(foobar="bar")));//returns {"STATUS":404,"HEADERS":{"MYHEADER":"bar"},"CONTENT":"{\"MESSAGE\":\"Not Found\"}"} (good)
</cfscript>
--------------------------------------------

Actual result: If a non-void REST method is invoked directly, RestSetResponse() is ignored and the function returns its result variable (good). If a non-void REST method is invoked via HTTP, RestSetResponse() is ignored and the function returns its result variable (bad).

Expected result: If a non-void REST method is invoked directly, RestSetResponse() is ignored and the function returns its result variable. If a non-void REST method is invoked via HTTP, ColdFusion ignores the function's return value and uses the response set using the RestSetResponse() function.

For more details regarding actual and expected results, see comments in mypage.cfm.

Attachments:

Comments:

Hi Adobe, I see the Status/ReasonCode is currently "To Test/Fixed". I'm just wondering if the fix would be coming in CF2016 or Aether. Thanks!, -Aaron
Comment by Aaron N.
1270 | August 04, 2017 09:17:04 AM GMT
Currently it is lined up for the next bug fix update cycle for 2016. We need to get the fix QE-certified and can confirm only after that.
Comment by Vamseekrishna N.
1271 | August 04, 2017 09:34:48 AM GMT
What's going to happen to this fix with regards to CF10? I understand CF10 is no longer under support, but the original bug (CF-3546046), which was supposed to have been fixed but wasn't, was filed years before CF10 support ended. We are still struggling with this in CF10.
Comment by Legorol S.
1272 | August 04, 2017 09:42:31 AM GMT
@Legoral San - I can see where you are coming from but unfortunately we cannot make the fix available in 10. We would urge you move to a supported version (11 and higher) so that you continue to receive critical updates on the security side.
Comment by Vamseekrishna N.
1273 | August 04, 2017 09:50:12 AM GMT
Summary: Initially: 1) In non-void UDF, restSetResponse() was ignored 2) In void UDF, cfthrow returned custom REST response as HTML of error handler page (instead of JSON) Both were filed as CF-3546046, but only #2 was fixed (which I've verified in CF2016 Update 1). #1 was re-filed as CF-4198298. In Aether Public Beta Update 1, #1 is fixed but #2's fix was reverted/undone/unfixed. Filed CF-4202547 to re-fix #2. Thanks!, -Aaron
Comment by Aaron N.
27915 | May 22, 2018 07:32:38 AM GMT