Recently I was working on getting data from IBM Connections in and out of an XPages application using the IBM Connections API. The API was great to work with: it is pretty good documented and easy to understand. It uses Atom feeds and RESTful calls to communicate.
I needed to implement the data read/write ‘barebones style’. No HTTPClient and no Abdera. Don’t ask me why. but it’s not because I like to torture myself. In the beginning that actually worked quite well: I was able to implement and parse the GET, PUT and DELETE calls without any big problems.
Until… I tried to create a File in Connection. According to the API this can be done in two ways: either by sending multipart form-data (including the encoded file) or just the file using a POST request. Since the multipart form-data option returns a JSON object (and everywhere else I worked with XML/ Atom), I went with the option to just post the file.
To test my calls and the API I was using the Dev HTTP Client Chrome plugin (which I can highly recommend!). Using that I could simulate the request: make a POST to the correct Files URL, select a file and of we go. Response code: 201. All fine.
I then tried the same in SSJS: create a HTTPUrlConnection, set the method to POST and write the file to an output stream. Response code: 503 (“service unavailable”). No matter what I did.
So I searched. And searched. And tested. And couldn’t figure out why it failed. Until I had a bright moment: check what actually’s being sent (headers and body) and compare it with the output of the Dev HTTP Client. For the plugin that was easy: F12 in Chrome and you’ll have all the information you need. For the server-to-server call it was more difficult. I ended up installing Wireshark to inspect the network traffic.
After I found the POST request (in the enermous amount of data Wireshark generates) I noticed something strange and was sure I didn’t add: a Content-Type header with the value application/x-www-form-urlencoded. That is obviously wrong: I’m sending a binary file. It shouldn’t add that header. There was a bug in Java that describes the same behaviour, but that was supposed to be fixed in a later 1.5 version. I (now) know that the Java 1.6 version in Domino is not Oracle’s one so might that explain why this issue (or is it a feature?) still exists.
The solution was easy: override that header with the correct one. I used the URLConnection.guessContentTypeFromName() function (yes, that really exist) and added the header. Response: 201. Every time. Happy Mark and client.