Powershell, Windows, and the Cherwell SOAP API (cherwellservice) - empty response or not found error

I wanted to share something interesting I encountered when using PowerShell’s Web-ServiceProxy to interact with the Cherwell SOAP API or Cherwell Service.

This approach is well documented in the Cherwell Community but the example needed a minor adjustment because of the way Cherwell was deployed in the environment I was working with (hint: behind a load balancer).

The error / issue

Following the Builder’s Network example, I received a strange blank response error that tripped up the WebServiceProxy:

# Define URL, and create proxy for web service
$URI = "https://mycherwellserver.net/CherwellService/?WSDL"
$cherwellService = New-WebServiceProxy -Uri $URI

# Create container for storing session cookie
$cherwellService.CookieContainer = New-Object system.net.CookieContainer

# Test API connectivity
$cherwellService.GetServiceInfo()

The result was the following error:

Exception calling "GetServiceInfo" with "0" argument(s): "The request failed with an empty response."
At line:1 char:1
+ $cherwellService.GetServiceInfo()
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : WebException

A generic “The request failed with an empty response” message. Capturing this with Fiddler, I discovered the response was an unexpected 302 redirect from an http version of the URL to the https version (which is indeed an empty response).

The fix

This is the result of reverse proxying requests to the Cherwell Service in some way or another. In my case, it was SSL offloading via a network appliance. I suspect any form of proxying to the SOAP API could result in the same behavior though.

To identify and address the issue, create a proxy for the CherwellService, exactly as shown in the Cherwell Community example:

# Define URL, and create proxy for web service
$URI = "https://mycherwellserver.net/CherwellService/?WSDL"
$cherwellService = New-WebServiceProxy -Uri $URI

# Create container for storing session cookie
$cherwellService.CookieContainer = New-Object system.net.CookieContainer

Then, examine the WebServiceProxy object and take note of the Url property:

$cherwellService
SoapVersion                          : Default
AllowAutoRedirect                    : False
CookieContainer                      : System.Net.CookieContainer
ClientCertificates                   : {}
EnableDecompression                  : False
UserAgent                            : Mozilla/4.0 (compatible; MSIE 6.0; MS Web Services Client Protocol
                                       4.0.30319.42000)
Proxy                                :
UnsafeAuthenticatedConnectionSharing : False
Credentials                          :
UseDefaultCredentials                : False
ConnectionGroupName                  :
PreAuthenticate                      : False
Url                                  : http://mycherwellserver.net/CherwellService/api.asmx
RequestEncoding                      :
Timeout                              : 100000
Site                                 :
Container                            :

In my case, the property was incorrect. The Url was set to the http equivalent API URL (not the SSL offloaded https version). The Cherwell SOAP API was not aware it was behind a load balancer (likely a configuration issue but outside the scope of this post)!

Manually fixing the URL on the WebServiceProxy object (setting it to https instead of http) fixed the issue for me and eliminated the errant 302 response when calling API methods:

# Fix the URL in the object to be the load balancer front end URL
$cherwellService.Url = "https://mycherwellserver.net/CherwellService/api.asmx"

# Test API connectivity
$cherwellService.GetServiceInfo()

After fixing the Url, the correct response was returned from the API:

<ServiceInfo><ApiVersion>8.0.1</ApiVersion><CredentialsMode>0</CredentialsMode><LoginOptions /></ServiceInfo>

As noted, I suspect this could also manifest with the following error if there is a more serious configuration error (i.e. hostname or URI mismatch between the Cherwell Service and the front end appliance):

Exception calling "GetServiceInfo" with "0" argument(s): "The request failed with HTTP status 404: Not Found."
At line:1 char:1
+ $cherwellService.GetServiceInfo()
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : WebException

I hope this helps someone with a similar issue.