Skip to main content
Inspiring
September 17, 2019
Answered

restSetResponse content

  • September 17, 2019
  • 1 reply
  • 2442 views

Well, this is an extremely frustrating function. Especially for produces="application/json"

Depending on what you set the status to, your content is overridden by messages or default templates.

A few test functions:


status 401, 404 return body with html default template instead of specified content

 

 

//test function for 404 - returns html default template
remote void function notfound()
	httpmethod="GET"
	restpath="/not-found"
{
	response = {
		content: "Oops, not found",
		status: 404
	};
	restSetResponse(response);					
}

 

 


status 422 returns body with html "The custom error module does not recognize this error."

 

 

//test function for 422 - returns "The custom error module does not recognize this error."
remote void function UnprocessableEntity()
	httpmethod="GET"
	restpath="/unprocessable-entity"
{
	response = {
		content: "Oops, unprocessable entity",
		status: 422
	};
	restSetResponse(response);					
}

 

 

 
The purpose of having produces="application/json" was to always have the body/content a JSON structure -
which obviously isn't going to happen if my content is ignored. For example -

 

 

//json structure for errors
private Struct function handlerError( required string funcName, required any e)
{
	var funcResp	    = structNew();
        funcResp.error	    = true;
        funcResp.msg	    = ARGUMENTS.e.message;
        funcResp.type	    = ARGUMENTS.funcName & " -> " & ARGUMENTS.e.type;
        funcResp.error_code = ARGUMENTS.e.errorCode;

        return SerializedJSON(funcResp);
}

// should return for 422
{"error":true,"msg":"Oops, unprocessable entity","type":"Unprocessible Entity","error_code":"422"}
// should return for 404
{"error":true,"msg":"Oops, not found","type":"Not Found","error_code":"404"}

 

 


How can I override the override, so my content is returned in the body?
Environment: Windows Server 2012R2 v6.2, CF2016, IIS v8

 

Correct answer BKBK

When you serialize to JSON you essentially get a string. But, here, your function is returning a struct instead. 

So, you should modify the code to something like

 

private String function handlerError( required string funcName, required any e)
{
	var funcResp	    = structNew();
        funcResp.error	    = true;
        funcResp.msg	    = ARGUMENTS.e.message;
        funcResp.type	    = ARGUMENTS.funcName & " -> " & ARGUMENTS.e.type;
        funcResp.error_code = ARGUMENTS.e.errorCode;

        return serializeJson(funcResp);
}

  

1 reply

BKBK
Community Expert
BKBKCommunity ExpertCorrect answer
Community Expert
October 5, 2019

When you serialize to JSON you essentially get a string. But, here, your function is returning a struct instead. 

So, you should modify the code to something like

 

private String function handlerError( required string funcName, required any e)
{
	var funcResp	    = structNew();
        funcResp.error	    = true;
        funcResp.msg	    = ARGUMENTS.e.message;
        funcResp.type	    = ARGUMENTS.funcName & " -> " & ARGUMENTS.e.type;
        funcResp.error_code = ARGUMENTS.e.errorCode;

        return serializeJson(funcResp);
}

  

Sergii Melnykov
Participating Frequently
January 29, 2025

Hello,

This seems relevant as I'm trying to add some AJAX to an existing application, but I ran into the same general issue.

Can I have the same JSON handling when output is done with the following approach?

 

 

getPageContext().getResponse().setStatus(422);
getPageContext().getResponse().setContentType('application/json; charset=utf-8');
writeOutput(serializeJson(data));

 

As implemented above all of the 4xx errors are replaced with corresponding HTML stubs, while code 200 works perfectly. I can have a workaround with the status code in the body, but I wanted to keep it semantical on JS error handler side.
My situation is complicated a little bit by no control over CF settings either directly or via the Application.cfc (and IIS likewise).
BKBK
Community Expert
Community Expert
January 29, 2025

Thank you for your prompt answer Charlie!

It's hard to structure by thse points exactly, but I'll try:

1) Yes, no luck. Tried by rebuilding from the inside and just by making a super bare-bones sample with just cfheader and cfcontent - all the same.

2) CFC, but it's called indirectly. I structured my part of the application similar to a typical fw/1 app, except that I don't have Application.cfc or the framework itself, but some of it's functions (including shortcutting to JSON output skipping a layout) are replicated by other CFCs.

3) It's mostly stock CF and stock stub pages identical to what Martie has originally reported on this topic.

4) Sure, I tried on Lucee local env and it doesn't have any issues whatsoever. 

5) It's CF2021 on the target environment

6) Business reasons. They don't want relative outsiders crash anything outside of the job scope. I agree, that would have put a lot of additional strain on their QA.

If I could have my own Application.cfc etc, I'd just drop in a framework that handles all of it, but currently I can't. My goal is to modernize it from the inside without touching any of the older parts.

 

Hope it explains it. I know that it's weird.


@Sergii Melnykov , you should perhaps start a new thread of your own. I say this because it seems your context is different from that of this thread. Your context involves a call to a CFC. Whereas the context of this thread is a request to a REST API, hence the use of 

// The responseStruct has keys such as status, content and headers
RESTSetResponse(responseStruct);