Question
· Jan 13, 2021

How to set HTTP Response Status Code in httpResponse object

Hi all,

I have a passthru REST setup using EnsLib.HTTP.GenericService and EnsLib.HTTP.GenericOperation. Works well.

I am adding some logic to the Operation and for some scenarios I want to return an HTTP 40x response status code.

I create an httpResponse object within the Business Operation, but I can't figure out how to set the http response status code that is returned to my Posstman client that initiated the request. I set StatusCode=400, and StatusLine and ReasonPhrase properties - but when the ultimate requestor (Postman) receives the response back it is a 200 status code. I am quitting the OnMessage method with status of $$$OK - which I suspect is being interpreted as HTTP response status code of 200. But I thought the httpResponse.StatusCode property setting of 400 would override that (?)

So how do I control the status code of the response? Can that be done within the httpResponse object within the Business Operation? Or do I need to subclass the related Business Service?

Product version: IRIS 2020.4
Discussion (9)2
Log in or sign up to continue

Hi Mike,

I have been having the same problem and could only ever return a 200 or 500 status code from my REST Business Service, so I was very disheartened to see your post that WRC said you have to CSP layer to get round this.

However, not one to give up easily, I believe I have found a solution:

I am using the EnsLib.REST.GenericServices business service class which uses the EnsLib.HTTP.InboundAdapter  adaptor class.

It appears that the EnsLib.HTTP.InboundAdapter class uses the second and remaining pieces, separated by " ", of the StatusLine header value for the returned status code.

Therefore, in my Business Process code, that returns  EnsLib.HTTP.GenericMessage back to the Business Service, I used the following lines, in the appropriate places of my code:

Set tHttpResponse = ##class(%Net.HttpResponse).%New()

Set tHttpResponse.StatusLine = "HTTP/1.1 404 Not Known"

Set response = ##class(EnsLib.HTTP.GenericMessage).%New(tResponseStream,,tHttpResponse)

Do response.HTTPHeaders.SetAt("HTTP/1.1 400 Bad Request","STATUSLINE")

Do response.HTTPHeaders.SetAt(tHttpResponse.StatusLine,"STATUSLINE")

Hope this helps.

Hi Neil,

My code was pretty much identical to what you shared above, except for the following:

Do response.HTTPHeaders.SetAt("HTTP/1.1 400 Bad Request","STATUSLINE")

I added that, but it didn't change anything.

The only other difference is that I am doing all of this in the Business Operation in that I only have and Business Service and Business Operation (no Business Process). Not sure if that would make a difference, but I'm going to put in a Business Operation and apply these changes and see if that works.

Thanks again for the investigation and idea - I'll let you know if inserting a Business Process and the related code works for me.

Hi Mike,

I am using my own custom Business Process which creates the HTTP Response.

I am also using a Business Services, rather than a Business Operation, like you, but I'm sure the principle will be much the same.

My Business Services uses the passthrough 'EnsLib.REST.GenericServices' business service class, which passes the HTTP Request to my custom process.

The Business Process then processes the request and creates the appropriate HTTP Response which is passed back to Business Service.

Just in case someone stumbles into this thread looking for an answer (as I did) ...

Assuming the vanilla, un-extended EnsLib.HTTP.GenericService is the service handling the request, any response it receives from a business process needs to be an EnsLib.HTTP.GenericMessage. %Net.HttpResponse is not needed, nor is a CSP layer required.

The service requires that a stream is attached to the message; the stream doesn't need to contain anything.

The response message is composed in the BP something like this:

Set rstream = ##class(%Stream.GlobalCharacter).%New()
// Optional body content
Do rstream.Write("<HTML><HEAD>Uh oh.</HEAD><BODY><BR><STRONG>Error: Invalid Patient ID</STRONG></BODY></HTML>")
// Provide a stream object, empty is fine
Set response = ##class(EnsLib.HTTP.GenericMessage).%New(rstream)
// This works as expected in I4H 2023.1
Do response.HTTPHeaders.SetAt("HTTP/1.1 400 Bad Request","StatusLine")
// if you're providing a payload ...
Do response.HTTPHeaders.SetAt("text/html; charset=utf-8","Content-Type")

I've verified that it works as coded above, using curl:

< HTTP/1.1 400 Bad Request
< Content-Type: text/html; charset=utf-8
< Content-Length: 99
<
* Connection #0 to host iristest.local left intact
<HTML><HEAD>Uh oh.</HEAD><BODY><BR><STRONG>Error: Invalid Patient ID</STRONG></BODY></HTML>

The reason this 2-year-old thread floated to the top is because I found it researching an issue I had encountered with EnsLib.HTTP.GenericService.. I wanted to "pass through" a status code I had set as a property of a response message in a business process. While a solution was buried in the thread, the OP claimed it did not work in his case. I'm not sure why; I used a slight variation of that solution with success and simply felt the variation was worth sharing.