How can I attach a file to a Jira Insight object using SIL?

Alex VanderWoude June 15, 2021

I am attempting to add a file as an Attachment to an object in our Jira Insight system.  To do this I am using an SIL script to Post a call to the REST API method "/attachments/object/".  The problem is that I cannot figure out how to set up the request correctly.  Every method I have tried results in an HTTP 400 error, which I take to mean that my request is malformed.  There aren't even any error messages returned, alas.

Method 1 puts the file information into the request as a struct:

string baseInsightUrl = getJIRABaseUrl() + "/rest/insight/latest";
number objectKey = 12345; // This is a known object I can see
string command = "/attachments/object/" + objectKey;
string insightUrl = baseInsightUrl + command;

HttpRequest request;
request.headers += httpBasicAuthHeader("user.name", getPersistentVar("password"));
request.headers += httpCreateHeader("Content-Type", "multipart/form-data");
request.headers += httpCreateHeader("X-Atlassian-Token", "no-check"); // Bypass XSRF checks
request.headers += httpCreateHeader("Cache-Control", "no-cache");
//request.headers += httpCreateHeader("Accept", "application/json"); // Is this needed?

struct FileForPostRequest {
string filename;
string file;
string comment;
string encodedComment;
}
FileForPostRequest body;
body.filename = "LoremIpsum.txt";
body.file = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. In ac "
+ "finibus ante. Suspendisse eu laoreet dui. Nam suscipit leo et "
+ "viverra maximus. Mauris aliquet tempus est, at porta odio eleifend "
+ "et. Curabitur sed velit dapibus, porta dolor elementum, rutrum "
+ "mauris. Pellentesque velit ex, imperdiet vel ornare id, aliquet eu "
+ "enim. Fusce enim nisl, scelerisque sit amet malesuada lobortis, "
+ "vehicula eu justo.";
body.comment = "This is a comment.";
body.encodedComment = "This is a comment.";

string result = httpPost(insightUrl, request, body);

string statusCode = httpGetStatusCode();
if (statusCode != 200) {
runnerLog("HTTP error code: " + statusCode);
runnerLog("HTTP reason: " + httpGetReasonPhrase());
runnerLog("HTTP error message: " + httpGetErrorMessage());
}

Method 2 manually builds the body as a string:

string baseInsightUrl = getJIRABaseUrl() + "/rest/insight/latest";
number objectKey = 12345; // This is a known object I can see
string command = "/attachments/object/" + objectKey;
string insightUrl = baseInsightUrl + command;

HttpRequest request;
request.headers += httpBasicAuthHeader("user.name", getPersistentVar("password"));
string boundary = "----MultipartFormDataBoundary" + formatDate(currentDate(), "ssSSS");
request.headers += httpCreateHeader("Content-Type", "multipart/form-data; boundary=" + boundary);
request.headers += httpCreateHeader("X-Atlassian-Token", "no-check"); // Bypass XSRF checks
request.headers += httpCreateHeader("Cache-Control", "no-cache");
//request.headers += httpCreateHeader("Accept", "application/json"); // Is this needed?

string[] bodyLines;
bodyLines += "--" + boundary;
bodyLines += "Content-Disposition: form-data; name=\"file\"; filename=\"LoremIpsum.txt\"";
bodyLines += "Content-Type: text/plain";
bodyLines += "Lorem ipsum dolor sit amet, consectetur adipiscing elit. ";
bodyLines += "In ac finibus ante. Suspendisse eu laoreet dui. Nam " ;
bodyLines += "suscipit leo et viverra maximus. Mauris aliquet tempus est, ";
bodyLines += "at porta odio eleifend et. Curabitur sed velit dapibus, ";
bodyLines += "porta dolor elementum, rutrum mauris. Pellentesque velit ";
bodyLines += "ex, imperdiet vel ornare id, aliquet eu enim. Fusce enim ";
bodyLines += "nisl, scelerisque sit amet malesuada lobortis, vehicula eu ";
bodyLines += "justo.";
bodyLines += "";
bodyLines += "--" + boundary;
bodyLines += "Content-Disposition: form-data; name=\"comment\"";
bodyLines += "This is a comment.";
bodyLines += "";
bodyLines += "--" + boundary;
bodyLines += "Content-Disposition: form-data; name=\"encodedComment\"";
bodyLines += "This is a comment.";
bodyLines += "";
bodyLines += "--" + boundary + "--";
string body = join(bodyLines, "\n");

string result = httpPost(insightUrl, request, body);

string statusCode = httpGetStatusCode();
if (statusCode != 200) {
runnerLog("HTTP error code: " + statusCode);
runnerLog("HTTP reason: " + httpGetReasonPhrase());
runnerLog("HTTP error message: " + httpGetErrorMessage());
}

But as noted above, both of these methods fail with a 400 error.

What am I doing wrong?  I have not been able to find any examples of this sort of thing being done using SIL, and the documentation is sparse to say the least (see https://insight-javadoc.riada.io/insight-javadoc-8.6/insight-rest/#attachments_object__objectid__post and https://anovaapps.atlassian.net/wiki/spaces/SIL/pages/1828153/httpPost for example).  The only working examples I could find seemed to be in Java or Python, but I am trying to use SIL here.

I have used SIL to successfully issue httpGet() calls, and even httpPost() with a simple struct (i.e. not multipart form data) with the "/comment/create" command.  So it seems like it ought to work if I can just get the syntax right.

By the way, if there's a way to do this without using the REST API then please let me know.  But even if there is such a way it would still be nice to know how to properly build a Post request that uses multipart form data.

 

0 answers

Suggest an answer

Log in or Sign up to answer