Making multiple API calls in a single route

I’m trying to make 2 REST API calls in a single route

  1. Request WorkLog Ids since 1577836800000(GET)
  2. Base on the Id’s from #1, get the actual WorkLogs using (POST)

Is this even possible?

app.get('/hello-world', addon.authenticate(), (req, res) => {
        var httpClient = addon.httpClient(req);

        httpClient.get('/rest/api/latest/worklog/updated?since=1577836800000', (error, response, body) => {
            if (!error && +response.statusCode === 200) {
                var workLogs = JSON.parse(body);
                var workLogIds = workLogs.values.map(x => x.worklogId);
                var requestedWorkLogs = {ids: workLogIds};

                httpClient.post({headers: {Accept: 'application/json', 'Content-Type': 'application/json'}, url: '/rest/api/latest/worklog/list'}, requestedWorkLogs, (error, response, body) => {
                    console.log(error);
                    console.log(response);
                    console.log(body);

                    if (!error && +response.statusCode === 200) {
                        // Rendering a template is easy; the render method takes two params:
                        // name of template and a json object to pass the context in.
                        res.render('hello-world', {
                            title: 'Atlassian Connect',
                            body: body
                        });
                    } else {
                        res.render('hello-world', {
                            error: error
                        });
                    }
                });
            } else {
                res.render('hello-world', {
                    error: error
                });
            }
        });
    });

Hey,

I’m no expert, but the way I usually do this is by promisifying the httpClient request like:

const doRequest = (httpClient, url) => {
    return new Promise((resolve, reject) => {
        httpClient.get(url, (err, response, body) => {
            if (err || response.statusCode < 200 || response.statusCode >= 300) reject (err || body);
            resolve(JSON.parse(body));
        })
    })
}

Since you have a get and a post call, you might want to write it a bit differently to either accept a third argument with the request method (and any subsequent arguments you might need) or add another function that does a httpClient.post request.

Then you’re free to use await in your route and it would go something like:

app.get('/hello-world', addon.authenticate(), async (req, res) => {
    var httpClient = addon.httpClient(req);

    let workLogs = await doRequest(httpClient, '/rest/api/latest/worklog/updated?since=1577836800000');
    let workLogIds = workLogs.values.map(x => x.worklogId);
    let requestedWorkLogs = {
        ids: workLogIds
    };

    doPostRequest(httpClient, '/rest/api/latest/worklog/list')
        .then(body => {
            res.render('hello-world', {
                title: 'Atlassian Connect',
                body: body
            })
        })
        .catch(err => {
            res.render('hello-world', {
                error: error
            });
        });
});

As I said, I’m no expert and I didn’t try out the code so there might be errors, but I’ve used it this way and it worked.

Cheers

@ChupaCabra, I’ll give this a shot and let you know. Appreciate the response!

Thanks for this. Here’s how I’ve leveraged your idea and used async/await

utils.js:

exports.doGET = (httpClient, url) => {
    return new Promise((resolve, reject) => {
        httpClient.get(url, (error, response, body) => {
            if (error || response.statusCode < 200 || response.statusCode >= 300) reject (error || body);
            resolve({statusCode: response.statusCode, message: body});
        })
    })
}

exports.doPOST = (httpClient, options) => {
    return new Promise((resolve, reject) => {
        httpClient.post(options, (error, response, body) => {
            if (error || response.statusCode < 200 || response.statusCode >= 300) reject (error || body);
            resolve({statusCode: response.statusCode, message: body});
        })
    })
}

init.js

const utils = require('./utils.js')
exports.addIssueType = async function(httpClient) {
    let response = '';
    const issueTypeUrl = '/rest/api/2/issuetype';
    const options = {   
        url: issueTypeUrl, 
        json: true,
        body: { 
            name: "auto name", 
            description: "auto description"
        }
    };
    try {
        const result = await utils.doPOST(httpClient, options);
        response += ("Success creating issue types" + result.statusCode);
    }
    catch(error) {
        response += ("Error creating issue types:" + error.errors.name);
    }
    // NOTE: At this point `options` has been modified by httpClient

    try {
        const result= await utils.doGET(httpClient, issueTypeUrl);
        response += ("Issue types:" + result.message);
    }
    catch (error) {
        response += ("Error getting issue types:" + error.errors.name);
    }
    return response;
}

index.js:

const init = require('../src/init.js')
...
app.get('/hello-world/init', addon.authenticate(), safeHandler(initHandler));

    function safeHandler(handler) {
        return function(req, res) {
            handler(req, res).catch(error => res.status(500).send(error));
        };
    }

    async function initHandler(req, res) {
        const response = await init.addIssueType(addon.httpClient(req))
        res.send(response);
    }