Impossible to modify headers and status in a %CSP.REST %response
Hi everybody,
I'm modifying a REST interface for a client but it seems impossible to me to modify HTTP Response Status and including custom HTTP Headers either.
My dispatch class (extending %CSP.REST) is contacted through a POST request and the latter is processed in a custom class (extending %CSP.REST as well) accessed as shown in the example below:
<Route Url="/test" Method="POST" Call="Custom.Test:Process" />
Within the processing class I tried executing the following statements with no success:
Do %response.SetHeader("totalcount",totalcount)
Set %response.Status = ..#HTTP400BADREQUEST
ObjectScriptObjectScript
The following message is always returned, even if an error occurred:
Moreover, I tried to print %response.Status just before the end of the code in the processing class and it seems to have the right value ("400 Bad Request"), even it is always 200 within the response.
Finally, I tried adding a custom header with no success, again. I tried with "x-totalcount" also, as a user suggested in another question but it haven't worked.
Can somebody help me?
Thanks
Is there a write command happening somewhere in your method before you try to set the header? If so, the headers will be sent before the write command, and will mean that it's too late to modify them after that. You can check %response.InProgress to see if that has already happened.
Hi David, thank for your response. I've solved the issue but I didn't know about this %response.InProgress, it seems a very useful statement!
Ciao Pietro,
difficult to tell without looking at the code.
Looking at the response my guess (bet?😉) is that your code has some error processing and if "somewhere" an error status is returned, then the error processing is triggered and is returning the response you see, including headers etc.
Ciao Enrico,
thanks for your response. However, I identified and solved the issue. It was a bit tricky to find because, basically, who developed this REST interface before, returned a response through the following statements:
Set ListaPrenotazioni = ##class(%Library.ListOfDataTypes).%New() [... Populate the list of data types ...] Do ##class(%ZEN.Auxiliary.jsonProvider).%WriteJSONStreamFromObject(.jsonStream,ListaPrenotazioni,,,,"eu") Do jsonStream.Rewind() Do jsonStream.OutputToDevice()
Since at first I put my statements after this code (before OutputToDevice()), I wasn't able to modify the status or the header. I found it out while reading the comment to the method SetHeader, which says:
It was a bit unintuitive because I didn't expected that generating the stream will prevent any further header or status modification. Basically, I solved just moving all my statements before the code that creates the variable jsonStream:
Set ListaPrenotazioni = ##class(%Library.ListOfDataTypes).%New() [... Populate the list of data types ...] [ In case of error: ] Do %response.SetHeader("totalcount",totalcount) Set %response.Status = ..#HTTP400BADREQUEST [ ... ] Do ##class(%ZEN.Auxiliary.jsonProvider).%WriteJSONStreamFromObject(.jsonStream,ListaPrenotazioni,,,,"eu") Do jsonStream.Rewind() Do jsonStream.OutputToDevice()
Are you able to set those Status and HTTPheaders straight into the instance of EnsLib.HTTP.GenericMessage in your code. like below
Set httpGeneric = ##Class(EnsLib.HTTP.GenericMessage).%New() ; this was already initiated in your business host via code. set att("Status")=..#HTTP400BADREQUEST do httpGeneric.SetAttributes(.att) set httpHeader("ContentType")="application/json" set httpHeader("totalcount")=totalcount do httpGeneric.SetHTTPHeaders(.httpHeader)
Thanks Ashok, it is interesting and I used it in another project. However, I've solved this issue but while reading your answer I wonder how to use this HTTP GenericMessage as the response stream within the CSP %response. Do you have any idea? Thanks