Skip to main content
Participant
August 11, 2021
Answered

ColdFusion REST Services not allowing a struct to be sent back in "content" when status code is 4xx

  • August 11, 2021
  • 2 replies
  • 1652 views

I am using CF REST Services and we would like to send back a detailed error struct when a requestor submits data that does not pass our internal validation check. I am using setRestResponse to manipulate the status code (which works fine on all accounts). However when someone fails validation I would like to send a struct back to the user with a 400 or a 401. My research lead me to putting the struct in the "content" part of my return struct to setRestResponse however when I do that, I get the correct statuscode but not the JSON struct of the error detail.

One thing Im observing is my api seems to be returning HTML, even though I have set the "produces" attribute of my function to "application/json". I have also set the function to void since we are using setRestResponse. Can you help me figure out how to send back an error detail struct with a 400 error? What exactly needs to happen to make the API respond with JSON beyond what Ive done already?

 

Ive included a snippet of my code.

    This topic has been closed for replies.
    Correct answer Gerry5C74

    Thanks again!  

    I think Ive made some headway, however Im getting a new error.  

    For background I went ahead and used the second reccomendation (which incidentally created the same condition that the first suggestion did).  I tried the first stuggestion, and would up getting a 204/No Content error (my code is was suppsoed to surface a 200).  Then I employed the section suggestion and got the same condition.  So after employing these changes, I can no longer affect the status or the content variable in my response struct.  However for some reason it seems like I just need to do something else and this will work.  Trying to figure out what it is.  For reference at the end of this function Im building a struct called "response" which has two keys.  response.status which is the status code Id like to return, and response.content which contains either a success or an error struct.  

     

    Can you think of anything I should be doing differently?


    UPDATE!

    I figured out my issue.  I had to change the returntype of "putRequest" to "struct" and now everything works dandy!!

    Thank you so much for sticking with me and helping me get to the bottom of it. restSetResponse() should get more attention.  Its a very simple way to do this that would encourage more to get involved with CF REST Services.

    Regards!!!!

    2 replies

    BKBK
    Community Expert
    Community Expert
    August 13, 2021

    I tried to understand the issue, but two things confuse me. Firstly, you mention "arguments.messageID", suggesting we're in a function. But I see no var-scoped variables. Where are we? If in a function, could you share the code of the entire function?

     

    Secondly, it's unclear to me why so many variables are defined. I expected something like

    <cfset var response = structNew()/>
    <cfset var out_struct = "">
    
    <!--- Scope necessary. Variables scope assumed --->
    <cfif IsDefined('variables.val_check_fail')>
    	<!---The val_check returned an error.  Stop processing and return a REST error--->
    	<cfscript>
    	var error_struct = StructNew();
    	
    	error_struct.errorText = val_check;
    	error_struct.errorCode = 3254;
    	
    	out_struct = serializeJSON(error_struct);
    	</cfscript>
    
    	<cfset response.status = 400/>
    
    <cfelse> 
    	<cfscript>
    	var ins_payload = invoke(val_obj, 'insert_payload', {value_string:#insert_value_list#,col_string:#insert_list#});
    	
    	var success_struct = StructNew();
    	success_struct.message =  "Validated and Accepted For: " & arguments.messageID;
    	
    	out_struct = serializeJSON(success_struct);
    	</cfscript>
    	
    	<cfset response.status =200>
    	
    </cfif>
    
    <cfset response.content = out_struct> 
    <cfset restSetResponse(response)>

     

    Inspiring
    August 16, 2021

    Thanks so much for taking a look!

    Much of that code is not germaine to my issue.  I should proably have left that out.  Thanks for the note about scoping, I made that change.

    That said my problem is specfically here (all othter parts of this function work fine, and yes, it is a REST function using returntype="void").  If the validation check (variables.val_check_vail) fails, I want to send a 4XX statuscode error and an error payload.  When I do this for a 2XX statuscode, I can successfully send the payload structure with it.  When I do this for a 4XX this seems to somehow be overridden and the server returns HTML (despite my setting produces="application/JSON") with the generic 4XX error, and no payload structure.  Could this be the webserver overriding ColdFusion on errors and not success statuscodes?  If that is the case, how do you override it if your function is set to returntype="void".  Can I send a structure back in the "content" variable when using a 4XX statuscode and restSetResponse()?

     

    <cfif IsDefined('variables.val_check_fail')>
                    <!---The val_check returned an error.  Stop processing and return a REST error--->
                       <cfscript>
                           error_struct = StructNew();
    
                           error_struct.errorText = val_check;
                           error_struct.errorCode = 3254;
                           out_struct = serializeJSON(error_struct);
                       </cfscript>
                    
                       <cfset response.status = 400/>
                       <cfset response.content =  #out_struct#/>
                       <Cfset pyld = response/>
                      
                <cfelse> 
                     <cfscript>
                        success_struct = StructNew();
                        success_struct.message =  "Validated and Accepted For: " & #arguments.messageID#;
                        
                        out_struct = serializeJSON(success_struct);
                    </cfscript>
    
                    <cfset response.status =200>
                    <cfset response.content = #out_struct#> 
                    <cfset pyld = response/>
                </cfif>
              <cfscript>
                    restSetResponse( pyld );
                </cfscript>
    Gerry5C74Correct answer
    Inspiring
    August 17, 2021

    Thanks again!  

    I think Ive made some headway, however Im getting a new error.  

    For background I went ahead and used the second reccomendation (which incidentally created the same condition that the first suggestion did).  I tried the first stuggestion, and would up getting a 204/No Content error (my code is was suppsoed to surface a 200).  Then I employed the section suggestion and got the same condition.  So after employing these changes, I can no longer affect the status or the content variable in my response struct.  However for some reason it seems like I just need to do something else and this will work.  Trying to figure out what it is.  For reference at the end of this function Im building a struct called "response" which has two keys.  response.status which is the status code Id like to return, and response.content which contains either a success or an error struct.  

     

    Can you think of anything I should be doing differently?


    UPDATE!

    I figured out my issue.  I had to change the returntype of "putRequest" to "struct" and now everything works dandy!!

    Thank you so much for sticking with me and helping me get to the bottom of it. restSetResponse() should get more attention.  Its a very simple way to do this that would encourage more to get involved with CF REST Services.

    Regards!!!!

    Gerry5CF4Author
    Participant
    August 11, 2021

    Below is my code

                <cfset response = structNew()/>
    
                <cfif IsDefined('val_check_fail')>
                    <!---The val_check returned an error.  Stop processing and return a REST error--->
                       <cfscript>
                           error_struct = StructNew();
    
                           error_struct.errorText = val_check;
                           error_struct.errorCode = 3254;
                           out_struct = serializeJSON(error_struct);
                       </cfscript>
                    
                       <cfset response.status = 400/>
                       <cfset response.content =  #out_struct#/>
                       <Cfset pyld = response/>
                      
                <cfelse> 
                    <cfscript>
                        ins_payload = invoke(val_obj, 'insert_payload', {value_string:#insert_value_list#,col_string:#insert_list#});
                    </cfscript>
    
                    <cfscript>
                        success_struct = StructNew();
                        success_struct.message =  "Validated and Accepted For: " & #arguments.messageID#;
                        
                        out_struct = serializeJSON(success_struct);
                    </cfscript>
    
                    <cfset response.status =200>
                    <cfset response.content = #out_struct#> 
                    <cfset pyld = response/>
                </cfif>
                
               
                <cfscript>
                    restSetResponse( pyld );
                </cfscript>