Question Yone Moreno Jiménez · May 25

Add HTTP Headers when sending a SOAP Message through a SOAP Bussines Operation

Good afternoon,

I have received a WSDL.

I have imported it successfully in HealthShare.

The external is requesting me to send messages with the following structure (using the auto-generated SOAP Bussiness Operation from the WSDL), as you see they need a custom http header titled "Appian-API-Key", as the following:

            curl --request POST \
              --url [ endpoint ] \
              --header 'Appian-API-Key:  << API KEY >> \
              --header 'Content-Type: application/xml' \
              --data '<?xml version='\''1.0'\'' encoding='\''utf-8'\''?>
            <soapenv:Envelope xmlns:soapenv='\''http://schemas.xmlsoap.org/soap/envelope/'\''>
              <soapenv:Body>
                <tns:acceptMessage xmlns:tns='\''http://ws.connectors.connect.mirth.com/'\''>
                <![CDATA[  Message  ]]>
                </tns:acceptMessage>
              </soapenv:Body>
            </soapenv:Envelope>'


I have looked for it, reading various threads:

https://community.intersystems.com/post/sending-soap-header-object-request-object

https://community.intersystems.com/post/theres-any-way-edit-soap-header

https://community.intersystems.com/post/add-header-soap-request

https://docs.intersystems.com/irislatest/csp/docbook/DocBook.UI.Page.cls?KEY=GSOAPSEC_manual

https://docs.intersystems.com/irislatest/csp/docbook/DocBook.UI.Page.cls?KEY=ESOAP_settings_outbound

I have tried:

Class Operation.SOAPSend Extends Ens.BusinessOperation [ ProcedureBlock ]
{

Property AppianApiKey As %String(MAXLEN = "");

Parameter SETTINGS = "AppianApiKey";

Parameter ADAPTER = "EnsLib.SOAP.OutboundAdapter";

Method acceptMessage(pRequest As Mensajes.Request.GestionPacientes.TSI.NotificacionesToPAM.acceptMessageRequest, Output pResponse As Mensajes.Response.GestionPacientes.TSI.NotificacionesToPAM.acceptMessageResponse) As %Status
{
    Set ..Adapter.WebServiceClientClass = "WSCLIENTE.GestionPacientes.TSI.NotificacionesToPAM.ExitusPort"
    Set client = ..Adapter.GetWebClient()

    Do client.HttpRequest.SetHeader("Appian-API-Key", ..AppianApiKey)
    Do client.HttpRequest.SetHeader("Content-Type", "application/xml")
    Set tSC = client.InvokeMethod("acceptMessage", .status, pRequest.message, .description)
    Quit:$$$ISERR(tSC) tSC

    Set tSC = pRequest.NewResponse(.pResponse)
    Quit:$$$ISERR(tSC) tSC

    Set pResponse.status = $Get(status)
    Set pResponse.description = $Get(description)

    Quit $$$OK
}

XData MessageMap
{
<MapItems>
<MapItem MessageType="Mensajes.Request.GestionPacientes.TSI.NotificacionesToPAM.acceptMessageRequest">
<Method>acceptMessage</Method>
</MapItem>
</MapItems>
}

}

It shows, after trying it:

  ERROR <Ens>ErrException: <METHOD DOES NOT EXIST>acceptMessage+2^Operaciones.SOAP.GestionPacientes.TSI.NotificacionesToPAM.ExitusPort.1 *GetWebClient,EnsLib.SOAP.OutboundAdapter -- - registrado como '-' número - @' Set client = ..Adapter.GetWebClient()'

I have also tried:

Class Operation.SOAPSend Extends Ens.BusinessOperation [ ProcedureBlock ]
{

Property AppianApiKey As %String(MAXLEN = "");

Parameter SETTINGS = "AppianApiKey";

Parameter ADAPTER = "EnsLib.SOAP.OutboundAdapter";

Method OnBeforeCall() As %Status
{
    Do ..Adapter.HttpRequest.SetHeader("Appian-API-Key", ..AppianApiKey)
    Do ..Adapter.HttpRequest.SetHeader("Content-Type", "application/xml")
    Quit $$$OK
}

Method acceptMessage(pRequest As Mensajes.Request.GestionPacientes.TSI.NotificacionesToPAM.acceptMessageRequest, Output pResponse As Mensajes.Response.GestionPacientes.TSI.NotificacionesToPAM.acceptMessageResponse) As %Status
{
    Set ..Adapter.WebServiceClientClass = "WSCLIENTE.GestionPacientes.TSI.NotificacionesToPAM.ExitusPort"

    Set tSC = ..Adapter.InvokeMethod("acceptMessage", .status, pRequest.message, .description)
    Quit:$$$ISERR(tSC) tSC

    Set tSC = pRequest.NewResponse(.pResponse)
    Quit:$$$ISERR(tSC) tSC

    Set pResponse.status = $Get(status)
    Set pResponse.description = $Get(description)

    Quit $$$OK
}

XData MessageMap
{
<MapItems>
<MapItem MessageType="Mensajes.Request.GestionPacientes.TSI.NotificacionesToPAM.acceptMessageRequest">
<Method>acceptMessage</Method>
</MapItem>
</MapItems>
}

}

But, when I open a LogSoap, it does not show the Appian-API-Key Header. It just shows the SOAP Body:

05/25/2026 13:37:57 *********************
Output from Web client with SOAP action = acceptMessage
<?xml version="1.0" encoding="UTF-8" ?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:s='http://www.w3.org/2001/XMLSchema'&gt;
 <SOAP-ENV:Body><acceptMessageRequest xmlns="http://ws.connectors.connect.mirth.com/"><message xsi:type="s:string"><![CDATA[[  Message  ]]></message></acceptMessageRequest></SOAP-ENV:Body>
</SOAP-ENV:Envelope>
 

Is there a way to add custom HTTP Headers when sending a SOAP communication through a Business Operation?

How?

In the previous forum topics I quoted, it looks like only SOAP Headers can be altered, but not HTTP headers. Is it false or true? 🤔

How could the requested custom http header be added?

Thank you so much for your time reading this doubt. Thanks. 🙂

Product version: IRIS 2023.1
$ZV: IRIS for UNIX (Red Hat Enterprise Linux 8 for x86-64) 2023.1 (Build 235_1U) Fri Jun 2 2023 13:23:04

Comments

DC AI Bot · May 25 Bot

Yes — custom HTTP headers can be added for a SOAP client. It is not limited to SOAP <Header> elements. InterSystems provides SetHttpHeader() on %SOAP.WebClient for this purpose. [1][2]

EnsLib.SOAP.OutboundAdapter itself does not expose GetWebClient() in the material you found here, which matches the <METHOD DOES NOT EXIST> ... GetWebClient,EnsLib.SOAP.OutboundAdapter error you received. The available guidance here is to set the HTTP header on the SOAP client object, using the adapter’s client instance: ..Adapter.%Client.SetHttpHeader(name,value). [3]

So the supported approach for your case is to set the generated web service client class on the adapter, then set the HTTP header on ..Adapter.%Client, and then invoke the SOAP method. [3][1]

Example pattern: [3][1]

Method acceptMessage(
  pRequest As Mensajes.Request.GestionPacientes.TSI.NotificacionesToPAM.acceptMessageRequest,
  Output pResponse As Mensajes.Response.GestionPacientes.TSI.NotificacionesToPAM.acceptMessageResponse
) As %Status
{
    Set ..Adapter.WebServiceClientClass = "WSCLIENTE.GestionPacientes.TSI.NotificacionesToPAM.ExitusPort"

    Do ..Adapter.%Client.SetHttpHeader("Appian-API-Key", ..AppianApiKey)

    Set tSC = ..Adapter.InvokeMethod("acceptMessage", .status, pRequest.message, .description)
    Quit:$$$ISERR(tSC) tSC

    Set tSC = pRequest.NewResponse(.pResponse)
    Quit:$$$ISERR(tSC) tSC

    Set pResponse.status = $Get(status)
    Set pResponse.description = $Get(description)

    Quit $$$OK
}

For your Content-Type line, be careful: the InterSystems SOAP client documentation says: [1]

Note: Content-Type, Content-Encoding, and Content-Length headers are part of the entity body rather than the HTTP main headers. You cannot set the Content-Length header, which is read-only. Nor can you set the Connection header, because this class does not support persistent connections.

So the key part for your requirement is the custom header:

Do ..Adapter.%Client.SetHttpHeader("Appian-API-Key", ..AppianApiKey)

[3][1]

About your LogSoap output: the material here only documents SOAP header elements in the SOAP envelope separately from HTTP headers, and explains that SOAP headers are inside the SOAP <Header> element, while HTTP headers are set through SetHttpHeader(). So not seeing Appian-API-Key in the SOAP envelope log is consistent with it being an HTTP header, not a SOAP header. [4][1]

Note: If you perform these steps in a utility method, note that the method must be an instance method and must be a member of an instantiable class (not an abstract class, for example). [4]

Also, the documentation you cited about HeadersOut applies to SOAP header elements inside the SOAP envelope, not HTTP transport headers. HeadersOut is for custom SOAP headers, while SetHttpHeader() is for HTTP headers. [4][1]

So, in short: your statement is false — it is possible to alter/add HTTP headers for SOAP calls, and the documented way in the retrieved material is to call ..Adapter.%Client.SetHttpHeader("Appian-API-Key", ..AppianApiKey) before InvokeMethod(). [3][1]


Sources:

Tell us more:
Don't like the style
Not factually correct
Didn't fully follow instructions
Refused when it shouldn't have
Being lazy
More...
Submit
0 0