Request header handler for reusing and modifying a header
This is the SOAP request header handler (ReqHandler) that reuses the initial SOAP response header and adds a Password value to the existing AuthHead header entry to pass along with the AccessID value between the client and Web service:
Request header handler modifying a saved SOAP response header
PROCEDURE ReqHandler: /*1*/ DEFINE OUTPUT PARAMETER hHeader AS HANDLE.
DEFINE INPUT PARAMETER cNamespace AS CHARACTER.
DEFINE INPUT PARAMETER cLocalNS AS CHARACTER.
DEFINE OUTPUT PARAMETER lDeleteOnDone AS LOGICAL.
/* The IF test determines if this is the first call through this code. If
it is, then g_header is not set and hHeader is set to ? to ensure that no
header is sent. g_header gets set when the response header is returned,
so a subsequent pass through this code takes the previous response header
and sends it as the current request header, possibly modified to
authenticate a secure request. */
IF NOT VALID-HANDLE (g_header) THEN DO: /*2a*/ /* first request */
hHeader = ?. lDeleteOnDone = TRUE. END.
ELSE DO: /*2b*/ /* all subsequent requests */
hHeader = g_header. lDeleteOnDone = FALSE. /* Password node data are added to the existing SOAP header if a secure
operation is being executed */
IF cPassword <> ? THEN DO: /*3*/ /*3a*/ /* Build a new x-doc to contain the Password data */
CREATE X-DOCUMENT hXdoc. CREATE X-NODEREF hXnoderef1. CREATE X-NODEREF hXnoderef2. CREATE X-NODEREF hXtext.
/* Add the Password data as a child of the existing header entry */
DEFINE VARIABLE hHeaderEntryref AS HANDLE. /*3b*/ DEFINE VARIABLE ClientNS AS CHARACTER
INIT "http://ServiceHost/SOAPHeader".
CREATE SOAP-HEADER-ENTRYREF hHeaderEntryref.
hXdoc:IMPORT-NODE(hXnoderef2, hXnoderef1, TRUE). /*3d*/ IF hXnoderef2:NUM-CHILDREN > 1 THEN DO: /* Get rid of previous */
hXnoderef2:GET-CHILD(hXnoderef1,2). /* Password data */
hXnoderef1:DELETE-NODE().
END.
/* Replace the existing header entry using a deep copy of the new version
from the x-doc that has the Password node added */
hHeaderEntryref:SET-NODE(hXnoderef2). /*3g*/
/* Procedure/header cleanup */
cPassword = ?. /*3h*/ /* Use current password until replaced */ DELETE OBJECT hHeaderEntryref. DELETE OBJECT hXdoc. DELETE OBJECT hXnoderef1. DELETE OBJECT hXnoderef2. DELETE OBJECT hXtext. END.
END. /* all subsequent requests */
END PROCEDURE.
The code in the preceding example:
1. Sends the SOAP request header for the HelloWorld and HelloSecureWorld requests (and any request run after running OpenAccess).
2. Tests if the global header handle (g_header) references a valid object, and:
a. If it does not reference an object, the request handler must be running as part of the initial call to OpenAccess and sets the output parameters to ensure that no initial SOAP request header is sent
b. If it does reference an object, the handler passes the global header object as output using the request header parameter (hHeader) and ensures that the object is not deleted (saving it for use in any further request)
3. Tests if a password has been specified for the current Web service request, indicated by any cPassword value that is not the Unknown value (?). If the current Web service request is nonsecure (as with the HelloWorld operation), all work has been done and the request handler can end. If the current Web service request is secure (as with the HelloSecureWorld operation), the request handler adds the password information to the SOAP request header, as follows:
Note: After the first secure request, all future requests (secure or nonsecure) send a request header that includes password information because the password information is never deleted until replaced by a newly-specified password.
a. Creates the XML x-document and x-noderef objects to manipulate the SOAP header
b. Creates the SOAP header entryref object (hHeaderEntryref) to access SOAP header entries and defines the namespace (ClientNS) used for defining the SOAP header entry for this request
c. Returns the existing header entry from the saved global SOAP header object using the GET-HEADER-ENTRY( ) method on the SOAP header object and accesses the XML root node of the entry using the GET-NODE( ) method on the SOAP header entryref object
The handler is adding the password information to an existing SOAP header entry. If it was adding a new header entry to hold the information, it would invoke the ADD-HEADER-ENTRY( ) method to add the header entry to contain the new XML for it.
d. Imports the header entry root node into an x-document object in order to access and modify the XML for the header entry, and also deletes any password data from a previous secure request before adding the currently-specified password data
e. Adds the <Password> element as a sibling of the <AccessID> element
f. Adds the <Password> element value
g. Replaces the entire existing header entry in the global SOAP header object with the header entry updated in the x-document object
h. Sets the password value (cPassword) to unknown (?), which retains the current password in the header entry until it is explicitly changed in cPassword, then deletes all of the helper XML and SOAP header entryref objects created in the header handler