Question
· Mar 10

Can %Net.HttpRequest objects get reused (behind our back)?

We are calling a REST web-service from Ensemble using EnsLib.HTTP.OutboundAdapter and redefining the adapter class to set custom headers as described by @Eduard Lebedyuk here: How to set Content-Type

During development we accidentally stumbled across puzzling behaviour - we now suspect that the %Net.HttpRequest object created in the linked example is being reused in the following scenario:

  1. request is created as described and sent to web-service, so an instance of a %Net.HttpRequest object exists and is known to the EnsLib.HTTP.OutboundAdapter
  2. we modify our code to test what happens if headers are not set - eg changing the "GetRequest()" method in the above example to return "" rather than a new %Net.HttpRequest object
  3. but in a subsequent call the headers set in step 1 above arrive in the web-service, even though they were not set (unset?) at step 2...

After really scratching our heads our suspicion is that the %Net.HttpRequest object created in step 1 is not thrown away after use, but "remembered"/re-used by the OutboundAdapter. Are we correct?

Is this what stands behind the "In normal use you create a single %Net.HttpRequest object and use it to issue as many requests as you need to the web server, each %Net.HttpRequest object can be thought of as a single instance of an internet browser" and "Reset the %Net.HttpRequest class so that it can issue another request. This is much faster than closing this object and creating a new %Net.HttpRequest object" in the class documentation? And if we are correct, is there documentation or good practice guidelines on how long it is wise to keep reusing such a request object? Or is it so situation dependent its impossible to say?

(Our situation is a passing a feed of healthcare data to a downstream system within our internal network; headers to contain content type and Basic Authentication headers - will only change a couple of times a year if the password is changed - and sent over the wire using SSL. We'll process several hundred, perhaps a few thousand, messages per day, mostly during working hours, with significant spikes of activity at certain points in the day.)

Product version: Ensemble 2018.1
$ZV: Cache for Windows (x86-64) 2018.1 (Build 184U) Wed Sep 19 2018 09:09:22 EDT
Discussion (1)1
Log in or sign up to continue

In the main method of EnsLib.HTTP.OutboundAdapter - SendFormDataArray line 5 you can see the following code:

#; Create an Http Request Object
Set tHttpRequest=$S($$$IsdefObject(pHttpRequestIn):pHttpRequestIn,1:##class(%Net.HttpRequest).%New())  $$$ASSERT($IsObject(tHttpRequest)&&tHttpRequest.%IsA("%Net.HttpRequest"))

Which creates a new empty %Net.HttpRequest object, unless pHttpRequestIn (3rd arg) has been passed with a custom request object. Most wrapper methods (VERB, VERBURL and VERBFormDataArray) do not pass pHttpRequestIn so you should get a fresh request object every time, but SendFormData and SendFormDataURL would pass pHttpRequestIn  from caller, if given.

Another place to look into is a Send call:

Set tSC=tHttpRequest.Send($ZCVT(pOp,"U"),$G(pURL,..URL),..#DEBUG)

It has the following signature:

Method Send(type As %String, location As %String, test As %Integer = 0, reset As %Boolean = 1) As %Status

reset arg defaults to 1, and when it's true the Reset method of %Net.HttpRequest is called after every request. Reset method removes headers (among other things). As you can see in the implementation:

Kill i%Headers,i%FormData,i%Params

EnsLib.HTTP.OutboundAdapter never calls Send with reset=0, so the request should be reset every time.

That said, how do you call SendFormDataArray?

I took a look at the article you linked to. Can you add logging to GetRequest method? It should be called on every business operation message.