User Macro fails with Ajax call to JIRA
Asked by zaphnet:

Prototyping a plugin using User macros.

As a newbie in js I'm struggling with understanding the escaping of URL:s.

From the following post I get that the Ajax call expects "No quotes": <https://community.atlassian.com/t5/Answers-Developer-Questions/AJAX-call-to-external-API-in-user-macro/qaq-p/494128>

```
AJS.$.ajax({  url: URL_WITH_NO_QUOTES,type: "GET",contentType: "application/json",  success: function(msg){    alert(msg);  }});
```

When experimenting with a call with a JQL with example below:

It works as long as I have an JQL that does nott contain any space or quotes.

For generic JQL:s I've attempted using "encodeURIComponent" or "encodeURI" - the REST call fails in the Ajax call, but works fine in a browser. I don't understand why?

Also tried with hardcoded "paths" with %20, %22 and so on, they alos work OK in broowser or command line, but fails in the USer Macro.

From: <https://community.atlassian.com/t5/Jira-questions/How-to-perform-calculations-in-confluence-using-Jira-issues/qaq-p/1162542>

```
jQuery.ajax({  type: "GET",  url: "<Confluence URL>/plugins/servlet/applinks/proxy?appId=<UUID>&path=<JIRA URL>/rest/api/latest/search/jql=<YOUR_JQL>",  dataType: "json",  async: false,  success: function( data ) {      //process data and render it in html tags  }});
```

Another example attempting to get the Sum Story points printed from a JQL.

The path looks OK in console in browser, but fails in Ajax call! And Ok in browser

```
<script>

    theurl = "/rest/scriptrunner-jira/latest/jqlfunctions/aggregateResult?jql=" + "$paramJql" + " AND issueFunction in aggregateExpression(\"Totalpoints\", \"storyPoints.sum()\")"
    // theurl = "/rest/scriptrunner-jira/latest/jqlfunctions/aggregateResult?jql=" + "$paramJql" + " AND issueFunction in aggregateExpression(\"Totalpoints\", \"storyPoints.sum()\")"
    // theurl = '/rest/scriptrunner-jira/latest/jqlfunctions/aggregateResult?jql=' + encodeURIComponent("$paramJql" + ' AND issueFunction in aggregateExpression("Totalpoints", "storyPoints.sum()")') 
    //encodeURIComponent
    //encodeURI
    console.log( "theurl: " + theurl);

AJS.toInit(function(){
    jQuery.ajax({
        type: "GET",
        url: "https://confluence.assaabloy.net/plugins/servlet/applinks/proxy?appId=<UUID>&path=" + theurl,
        dataType: "json",
        async: false}).done(function (response) {

        var txt3 = document.createElement("p");  // Create with DOM
        var divContainer = document.getElementById("showJira");

        one = response.Totalpoints;
        txt3.innerHTML = txt3.innerHTML +  "Total StoryPoints: " + one;
        divContainer.innerHTML = "";
        console.log( "Total StoryPoints: " + one);
        console.log( "response: " + response);

        divContainer.appendChild(txt3);
        divContainer.innerHTML = "";
        divContainer.appendChild(txt3);
    });
});
</script>
```

The Ajax call returns with null.


Answers:
author: Rafael Pinto Sperafico
body: Hi [@zaphnet](/t5/user/viewprofilepage/user-id/224141) ,

Sorry for delay on getting back to you.

After running some tests, please find below an example on how to build the AJAX request. For this to work you must have an Application Link between Jira and Confluence working.

If the Application Link is configured with OAuth only, you must Allow the user in Confluence performing the action to perform Actions with Jira, the famous "Login \& Approve".

```
## Macro title: My Jira Search Macro
## Macro has a body: Y
## Body processing: Rendered
## Output: No Output
##
## Developed by: Rafael Pinto Sperafico
## Date created: 04/09/2019
## Installed by: Rafael Pinto Sperafico

## User Macro to search in Jira
## @noparams

<script type="text/javascript">
AJS.toInit(function() {

// JQL: jql=project=QWERTY
// url: AJS.Confluence.getBaseUrl() + '/plugins/servlet/applinks/proxy?appId=' + applicationLink.id + '&path=' + applicationLink.rpcUrl + encodeURI('/rest/api/2/search?jql=project=QWERTY'),

// JQL: jql=project="Basic Software Development"
// url: AJS.Confluence.getBaseUrl() + '/plugins/servlet/applinks/proxy?appId=' + applicationLink.id + '&path=' + applicationLink.rpcUrl + encodeURI('/rest/api/2/search?jql=project%3D%22Basic%20Software%20Development%22'),

// JQL: jql=issueFunction in aggregateExpression(total,"originalEstimate.sum()")
// url: AJS.Confluence.getBaseUrl() + '/plugins/servlet/applinks/proxy?appId=' + applicationLink.id + '&path=' + applicationLink.rpcUrl + encodeURI('/rest/scriptrunner-jira/latest/jqlfunctions/aggregateResult?jql=issueFunction%20in%20aggregateExpression(total%2C%22originalEstimate.sum()%22)'),

  var search = function(applicationLink) {
    jQuery.ajax({
      url: AJS.Confluence.getBaseUrl() + '/plugins/servlet/applinks/proxy?appId=' + applicationLink.id + '&path=' + applicationLink.rpcUrl + encodeURI('/rest/api/2/search?jql=project%3D%22Basic%20Software%20Development%22'),
      type: "GET",
      contentType: "application/json",
      success: function(data) {
        console.log(data);
      }
    })
    .done(function(data) {
      console.log(data);
    })
  }

//
// Get a list of all application link configured in Confluence
//
  jQuery.ajax({
    url: AJS.Confluence.getBaseUrl() + '/rest/applinks/1.0/listApplicationlinks.json',
    type: "GET",
    dataType: "json",
    success: function(data) {
      console.log(data);
    }
  })
  .done(function(data) {
//
// Iterate over a list of application links 
// search for Jira application link
// search in Jira application link found
//
  jQuery.each(data.list, function(i, v) {
    if (v.application.typeId == 'jira') {
      AJS.log(v.application);
        search(v.application);
      }
    })
  });
});
</script>
```

Tested on Confluence 6.6.7 and 6.15.2

Kind regards,  
Rafael

comments: author: zaphnet
body: Thanks for your help!

Finally got some time to review all my posts/attempts.

The call to get proxy and jira server failed due to websudo, but those were never the problem.

I must have made some other typo in combination with the final working url:

```
var theurl = encodeURI(confbase + "/plugins/servlet/applinks/proxy?appId=" + confproxy +"&path=" + jirabase + "/rest/scriptrunner-jira/latest/jqlfunctions/aggregateResult?jql=" + encodeURIComponent('fixversion="$paramProjectIssue" AND issueFunction in aggregateExpression("Totalpoints", "storyPoints.sum()")'));
```

{"Totalpoints":"235"}

Finally got all the "" and '' to work with $paramProjectIssue parameter from Built In Macro.


author: sviengkhou
body: Hello,

I'm trying to do something similar to Zaphnet and currently am running into error 500.

I'm using HTML macro from Confluence and trying to do some JQL query to JIRA.

I've followed the steps where you get the Jira UUID and the do the JQL query but in vain.

My query looks something like this

```
https://<ConfluenceURL>/plugins/servlet/applinks/proxy?appId=<UUDI>&path=https://<JIRAURL>/rest/api/2/search?jql=project=<MYPROJECT>
```

And if I try this directly from a web page I still get 500 error.

Any thought?

Thanks


author: Rafael Pinto Sperafico
body: Hi [@zaphnet](/t5/user/viewprofilepage/user-id/224141) ,

I usually perform the JQL search in Jira first, e.g:

```
text ~ "sample feature" and project = "Basic Software Development"
```

This is result in the following encoding in my web browser address bar:

```
jql=text%20~%20"sample%20feature"%20and%20project%20%3D%20"Basic%20Software%20Development"%20
```

Then, I copy the JQL above and paste it into the AJAX call surrounding it with single-quotes ('):

```
AJS.$.ajax({
  url: 'http://localhost:8080/jira/rest/api/2/search?jql=text%20~%20"sample%20feature"%20and%20project%20%3D%20"Basic%20Software%20Development"',
  type: "GET",
  dataType: "json",
  success: function(data) {
    AJS.log(data);
  }
});
```

Hope the above helps.

Kind regards,  
Rafael

comments: author: zaphnet
body: I've tried a number of different hard-coded strings as:

```
aurl = 'https://localhost/plugins/servlet/applinks/proxy?appId=<UID>&path=/rest/scriptrunner-jira/latest/jqlfunctions/aggregateResult?jql=issuekey=STP-207%20AND%20issueFunction%20in%20aggregateExpression(%22Totalpoints%22%2C%20%22storyPoints.sum()%22)';
```

or:

```
aurl = 'https://localhost/plugins/servlet/applinks/proxy?appId=<UID>&path=/rest/scriptrunner-jira/latest/jqlfunctions/aggregateResult?jql=issuekey=STP-207%20AND%20issueFunction%20in%20aggregateExpression("Totalpoints"%2C%20"storyPoints.sum()")';
```

They all fail without a json object returned, but work OK if I paste them on commandline.

"Failed to run init function: TypeError: Cannot read property 'Totalpoints' of null"

In my example direct from rest API:

```
{"Totalpoints":"8"}
```


author: Rafael Pinto Sperafico
body: Hi [@zaphnet](/t5/user/viewprofilepage/user-id/224141) ,

Sorry, it took me some time to understand from your description that you are actually attempting on calling ScriptRunner REST API endpoint (from Adaptavist) to get the Sum Story points.

When running *aggregateExpression* from Adaptavist, the search request to be used is as you have mentioned:

```
# Adaptavist REST API
/rest/scriptrunner-jira/latest/jqlfunctions/aggregateResult?jql=
```

and not:

```
# Jira REST API
/rest/api/2/search?jql=
```

Just to be sure we are on the same page ;)

For testing purposes, could you please replace the endpoint with:

```
aurl = 'CONFLUENCE_BASE_URL/plugins/servlet/applinks/proxy?appId=<JIRA_UID>&path=JIRA_BASE_URL/rest/api/2/issue/STP-207';
```

The testing purpose is to validate the request. You should get a STP-207 Jira Issue (<https://docs.atlassian.com/software/jira/docs/api/REST/7.6.1/#api/2/issue-getIssue>)

At the same time, would be possible to share your project somehow (e.g repository) so I could run some tests and get back to you with a resolution?

Kind regards,  
Rafael


author: zaphnet
body: Sorry for the confusion I've been having the same problem with both sql and script runner REST api:s.

The calls

```
aurl = 'CONFLUENCE_BASE_URL/plugins/servlet/applinks/proxy?appId=<JIRA_UID>&path=JIRA_BASE_URL/rest/api/2/issue/STP-207';
```

and

```
aurl = 'CONFLUENCE_BASE_URL/plugins/servlet/applinks/proxy?appId=<JIRA_UID>&path=/rest/api/2/issue/STP-207';
```

both work fine.

Still confusing to me how to write the url, some experiments in a browser (GurkaFilter a public example filter):

```
CCONFLUENCE_BASE_URL/plugins/servlet/applinks/proxy?appId=<JIRA_UID>&path=<JIRA_UID>/rest/api/2/search?jql=filter=GurkaFilter
```

Works fine, now attempting with another filter using the filter number.

```
CCONFLUENCE_BASE_URL/plugins/servlet/applinks/proxy?appId=<JIRA_UID>&path=<JIRA_UID>/rest/api/2/search?jql=filter=15593
```

Works fine, now attempting to use its name("Gurka Filter"):

None of below works

filter="Gurka Filter"

filter="Gurka%20Filter"

filter=\\"Gurka%20Filter\\"

filter=%27MY%20RFA%27

filter=%22Gurka%20Filter%22

Thanks for all the help, the problems that I encounter is in the combination of the application link/proxy and jira rest api.

Example above accessing jira rest api directly works fine

```
 <JIRA_UID>/rest/api/2/search?jql=filter="Gurka%20Filter"
```


author: Rafael Pinto Sperafico
body: Hi [@zaphnet](/t5/user/viewprofilepage/user-id/224141) ,

Thank you for your update and examples.

Could you please try removing the quotes from your JQL search, e.g:

```
'CONFLUENCE_BASE_URL/plugins/servlet/applinks/proxy?appId=<JIRA_UID>&path=<JIRA_BASE_URL>/rest/api/2/search?jql=filter=Gurka%20Filter'
```

Kind regards,  
Rafael


author: zaphnet
body: Still fails

```
'CONFLUENCE_BASE_URL/plugins/servlet/applinks/proxy?appId=<JIRA_UID>&path=<JIRA_BASE_URL>/rest/api/2/search?jql=filter=15593'
```

Works fine.

Attempted another workaround: Directly in jira rest api:

```

<JIRA_BASE_URL>/rest/scriptrunner-jira/latest/jqlfunctions/aggregateResult?jql=issuekey%20=%20STP-207%20AND%20issueFunction%20in%20aggregateExpression(Totalpoints,%20"storyPoints.sum()")
```

Works OK with output:

```
{"Totalpoints":"8"}
```

With a filter JQL: GurkaFilter
>
> ```
> GurkaFilter=issuekey = STP-207 AND issueFunction in aggregateExpression(Totalpoints, "storyPoints.sum()")?
>
> ```

```
<JIRA_BASE_URL>/rest/scriptrunner-jira/latest/jqlfunctions/aggregateResult?jql=filter=GurkaFilter
```

Fails with

```
{"message":"Negative array index [-1] too large for array size 0"}
```

...