Apr. 25, 2019

Bruce Clayton


3 min. read

SearchStax recently released a REST API for managing Zookeeper Solr Cloud configurations. A set of five API methods lets authorized users create, list, read, download, and delete Solr Cloud configurations remotely. This is part of a larger API that lets SearchStax clients create and configure Solr Cloud deployments procedurally if so desired.

In my role for SearchStax Support, I was asked to work up examples of these methods. You can exercise a REST API using any tool that lets you issue HTTP requests to the web. For my testing, I use cURL from a Bash shell script on a Linux platform.

The SearchStax API is trivial to use in that environment, barring the usual challenges of picking apart the returned JSON objects and extracting the desired values from them. For instance, the Bash command to retrieve a list of Solr configs from a Zookeeper ensemble is this simple:

RESULTS=$(curl -s -X GET -H "Authorization: APIkey $APIKEY" \

The $APIKEY is a nice innovation. It is a security code that gives one user access to the Solr configs on one deployment. It doesn’t expire, but it can be revoked. This lets the deployment’s admin delegate Solr configuration to an external user without granting general access to the deployment.

I had all of the API methods working under Bash when a client asked for API examples in Windows PowerShell. “Sure,” I thought. “How hard can it be?”

PowerShell syntax is deceptively similar to Bash syntax, except when it isn’t, which is most of the time. To paraphrase author Douglas Adams in The Hitchhikers Guide to the Galaxy, “PowerShell is almost, but not quite, precisely unlike Bash.” The tasks and goals of the script, however, are the same in both environments so I settled down to learn new idioms, new objects, and new methods.

The learning curve took about a day. My script to retrieve Solr configs from Zookeeper transformed into three lines of PowerShell script:

$headers = New‑Object "System.Collections.Generic.Dictionary[[String],[String]]"
$headers.Add("Authorization", "APIkey $APIKEY")

$RESULTS = Invoke-RestMethod -Method Get -Headers $headers /
‑uri "https://app.searchstax.com/api/rest/v2/account/$ACCOUNT/deployment/$uid/zookeeper-config/"

The code was fundamentally the same as well as being completely different, but that’s coding. I rapidly churned out the other examples—and then I hit a problem.

One of the SearchStax API methods uses multipart/form-data to mimic the body of a POST request from a multi-field form. This is the zookeeper-config-create method, which uses a form field to upload a configuration directory in ZIP format. It converts the ZIP file into a binary stream and sends it to the SearchStax servers, and from there to Zookeeper. In Bash, the code was perfectly simple:

DETAILS=$(curl -s -H -X POST "Authorization: APIkey $APIKEY" \
-F "name=test_config" -F "files=@conf.zip" 

The –F parameters are the fields of the multipart form. When I tried this in PowerShell, however, I hit a stone wall.

The problem, as I quickly discovered, is that PowerShell is notorious for not supporting multipart/form-data! There are many blogs, accumulated over years, lamenting this hole in PowerShell. Some other blogs explain how to manually assemble the form data using PowerShell objects, but most people don’t succeed at that. I certainly did not.

I spent hours digging through blog posts before discovering PowerShell Core, a cross-platform open-source version of PowerShell based on .NET Core. The first release of PowerShell Core, version 6.0, came out in January of 2018. Release 6.1 was released that March. It included limited support for multipart/form-data supplied by Mark Kraus. See Example 4 here.

I installed PowerShell Core 6.2 and tried the new feature. After setting up the same header for the APIKEY, the rest of the code was trivial:

$form = @{
name = 'test_config'
files = Get-Item -Path 'conf.zip'

$RESULTS = Invoke-RestMethod -Method Post -Headers $headers -Form $form \
‑uri "https://app.searchstax.com/api/rest/v2/account/$ACCOUNT/deployment/$uid/zookeeper-config/"

I ran the script. The ZIP file was transmitted, unpacked, and installed as expected.

The PowerShell examples are now complete, and I can go back to reading The Hitchhiker’s Guide to the Galaxy. Where’s my towel?

By Bruce Clayton

“…search should not only be for those organizations with massive search budgets.”

Get the Latest Content First