7 Replies Latest reply on Jun 5, 2016 2:33 AM by Liran Tevet

    REST Client Recording

    Liran Tevet

      Hi everyone,

      I"ve been asked to monitor a REST Client user experience using BMC TMART (we're running version 4.2).

      The REST request need to be verified using a certificate I've been given.

      Does anyone knows if is even possible to record REST Client with certificate authentication using TMART?
      If so any advice will be highly appreciated.

      Thanks,
      Liran.

        • 1. Re: REST Client Recording
          Hal DeVore

          I'm not an expert in this area but I do recall a couple of BMC customers who very successfully used the SoapUI tool to record transactions for TM ART.

           

          As I recall, you just create an Application Profile for the SoapUI program.  Select that instead of the Internet Explorer or Firefox profiles when you record.  From there it just all worked.  As with the browser, the SoapUI tool was not needed at playback time.

           

          --Hal

          • 2. Re: REST Client Recording
            Liran Tevet

            Thanks Hal I'll sure check you solution and update once I'll reach a conclusion

            • 3. Re: REST Client Recording
              Liran Tevet

              Hi,

              I've tried what you've suggested. Download Soap UI client, installed it, configured it under Application Profile with Protocol Profile defined as Web but when I tried to record a simple GET function, the functions counter was 0 all the time.

              Is there any kind of special configuration I should do in order for Workbench to successfully record the Soap UI client?

              Thanks

              Liran.

              • 4. Re: REST Client Recording
                Sachin Tewari

                Hi Liran Tevet,

                 

                When the application type is unsupported & not defined explicitly in Workbench, I normally look into options such as interacting with API's using command line interface. Then, use ProcessInitialize() to write to a log file and read it.

                 

                I have used this to monitor Active MQ(another unsupported type) using JMX Command Line Client or monitor XML pages(XML is more accurate then verifying HTML contents due to shifts in position(Row/Column/Occurences)

                 

                Hope this helps!

                Sash

                • 5. Re: REST Client Recording
                  Liran Tevet

                  Hi Sachin,

                  I'm not really sure what you mean by "I normally look into option such as interacting with API's using command line interface".

                  Do you mean you are not using TMART in such cases and uses CMD\Powershell command lines instead?

                  Thanks for the assistance
                  Liran.

                  • 6. Re: REST Client Recording
                    Todd Fendt

                    Hi all,

                     

                    [Please note: My answer is based on me using TMART 4.2 sp2]

                     

                    If I understand correctly (and I have been mistaken before), if you can use the SoapUI app to actually interact with your target web service, then you may be able to write the same exchange using the bdf language.

                     

                    I was also challenged with testing a web service, actually many web services.

                     

                    I may have recorded the base of this from soapui, I don't recall.

                     

                    I came up with the following:  ( example code to follow after explanation)

                     

                    My customer (responsible for the web service(s)) provided me with xml files to post to the service for each appropriate method or action.

                     

                    I developed a way to handle session after login, by keeping the provided session string from the first response after the login interaction for future interactions. And also was able to develop a way to substitute values within the xml files with output from previous responses. This allowed a multiple step interaction with the web service. Such as: Post a login action, get the response (and memorize the session string), Post another method to process something, injecting the previously saved session string into this steps xml file In the appropriate place.

                     

                    Code to setup the interaction:

                            // If the XML file exists then run this web service check

                            if FExists(lsFilename) then

                            

                            

                              lsPostURL := lsServer + lsURL;

                              lsTimerName := lsWebServiceName + " " + getServer(lsServer);

                             

                              lsTimerMessage := "Web Service: " + lsWebServiceName + MESSAGE_SEPARATOR +

                                          "URL: " + lsPostURL + MESSAGE_SEPARATOR + "User: " + lsUser;

                             

                              TimerStart(lsTimerName,lsTimerMessage);

                           

                              SetEncoding("ISO-8859-1");

                              WebHeaderAdd("SOAPAction", "\"\"");

                               

                              // Authenticate if provided

                              if ( (StrLen(lsUser) > 0) and ( Strlen(lsPWD) > 0 ) ) then

                                authenticate(lsUser, Decrypt3DES(lsPWD));

                              end;

                             

                              // Capture the Response XML

                              WebParseDataBound(lsResponse);

                     

                    The above code processes a datapool file ( a file containing a set of records that have fields that describe each step in this interaction. If a password field is specified or other values needed in the interaction then they are handled.The datapool fields specify the URL to post to. This example uses a password. The above code also sets up capturing the response into a variable:

                              WebParseDataBound(lsResponse);

                     

                    and it also sets the header and encoding:

                              SetEncoding("ISO-8859-1");

                              WebHeaderAdd("SOAPAction", "\"\"");

                     

                    Code to read an xml file (provided by the owner of the service):

                    [I keep these xml files within the project and they are then included in the package when uploading to central]

                                 // Read XML File contents and store in var

                                  if FOpen(lnFileHandle, lsFilename, OPT_FILE_ACCESS_READWRITE ) then

                       

                                        FSizeGet(lnFileHandle, lnFileSize);

                                        FRead(lnFileHandle, lsXMLFileContents, lnFileSize);

                                        FClose(lnFileHandle);

                                  else

                                    // trouble opening the File

                                    RepMessage("WSCheck: Could not open file: " + lsFilename,SEVERITY_ERROR );

                                    // Quit because of the dependencies of each step.

                                    exit;

                                  end;

                    So after this the variable lsXMLFileContents contains the xml contents.

                     

                    Then replace any needed values in the xml file with programmable values:( in this case a password that is stored encrypted: variable: lsPWD):

                                  //**************************************************************

                                  // Replace Password Token inside current Request XML content with

                                  // real password decrypted from datapool

                                  //                               

                                  //  Token format '#$TokenName$#' used inside XML request files

                                  //**************************************************************

                           

                                  lsXMLFileContents := strReplace(lsXMLFileContents, lsPWDReplaceToken, Decrypt3DES(lsPWD));

                     

                    Then post the file to the service:

                                  //post the file from a variable
                                  WebUrlPostBin(lsPostURL, lsXMLFileContents, STRING_COMPLETE, "text/xml;charset=UTF-8"); 
                             
                              else  
                                 // Post file from physical file
                                 WebUrlPostFile(lsPostURL,lsFilename,"text/xml;charset=UTF-8");
                              end;

                     

                    Either posting using the variable containing the xml contents or using WebUrlPostFIle to utilize the actual file.

                    The above code used the physical file if a password wasn't needed.

                    In case it is not obvious, the above comment in the code describes my method to replace values within the xml file using 'tokens' and the strreplace () function makes that happen. The password isn't seen unencrypted as the only place it is used is in the variable containing the xml.

                     

                    Now we have the response from the service:

                                     
                              // Create the XMl Document in memory   
                              lnXMLDoc := XmlCreateDocumentFromXml(lsResponse);
                             
                              //Print(lsResponse);

                     

                    The tricky part is actually driving through the response and getting any values you need to validate, usually errors are included in responses.

                     

                    The response uses namespaces to advertise the format of the XML nodes and such.

                    The code below uses any namespaces specified in my datapool fields and adds them:

                     

                              // Set the namespaces for the XML document
                              // The namSpaces specified apply to the XML being sent and received
                              // truelog will display any other namespaces needed
                              // You will get an error if a needed namespace is not specified
                              if Strlen(lsNameSpaces) > 0 then
                                //XmlSetNamespaces(lnXMLDoc, "xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/' xmlns:ns1='urn:horde'");
                                XmlSetNamespaces(lnXMLDoc, lsNameSpaces);
                              end;

                    You can gather the namespaces from the actual responses as they are specified in the response in the beginning of the file/response. If this is not done then commands like this XmlSelectSingleNode won't work.

                     

                    Here is a sample node locating string: used in the sample code from variable 'lsResponseNode'

                    /soapenv:Envelope[1]/soapenv:Body[1]/p:invokeResponse[1]/retrieveCustomerServiceConfigurationOutput[1]/Header[1]/io3:HeaderExtension[1]/ExecutionStatusMessage[1]/ExecutionStatusDescription[1]

                     

                    Code here to locate a specified node then get it's value for validation:

                     

                              // Capture the Node Value from the Response XML
                              //lnHExecutionContext := XmlSelectSingleNode(lnXMLDoc,"//ExecutionStatusMessage/ExecutionStatusDescription");
                              lnHExecutionContext := XmlSelectSingleNode(lnXMLDoc,lsResponseNode);

                              // test if the XmlSelectSingleNode returned a handle or a zero( Zero is failure)
                              if lnHExecutionContext = 0 then
                                Print("Error: Context was 0");
                                RepMessage("Web Service: " + lsWebServiceName + " Web Service response Node was not found Node:" + lsResponseNode,SEVERITY_ERROR );
                              else
                                // Test the Response against the verifications in the data pool
                                XmlGetNodeValue(lnHExecutionContext,lnsValue);
                               
                                // Verify Strings 
                                while dpValueElement(gsWSdpName, "VerifyStrings",lsVerifyString) do
                                         
                                   if (Strlen(lsVerifyString) > 0) then
                                     Print("Verify String: '" + lsVerifyString +"'");
                                     Print("Actual String: '" + lnsValue +"'");
                                     if trimString(lsVerifyString) <> trimString(lnsValue) then
                                    
                                       // Issue repmessage
                                       lsMessage := "Verify string '" + lsVerifyString + "' was not found. ERROR";
                                       Print(lsMessage);
                                       RaiseError(RAISE_ERROR_EVENT_CODE,lsMessage);
                                     end;
                                   end;         
                                end;

                     

                    A fair part of the code is to manage values from my datapool fields for this step and can be ignored and done manually. I am willing to share the datapool inventions for those interested.

                     

                    There is also code to look for error strings in node values and also regex expressions in node values.

                    These matches are coded to create failure messages.

                     

                    I can post the entire bdf file if you are interested. It requires some additional include files to power the datapool and other custom stuff. But the above example shows how to post and get responses and interrogate them.

                     

                    Have fun!

                     

                    Todd Fendt

                    2 of 2 people found this helpful
                    • 7. Re: REST Client Recording
                      Liran Tevet

                      Todd let me start with WOW!

                      Your answer is one of the most detailed answer I've ever came across with.

                      I've used some of your code in order to Post a REST query and it worked great ! without any recording just some plain bdl code lines.

                      Thanks a lot everyone for the assistance and the very quick responses

                      Cheer,

                      Liran.