CloudFlare as Axios Response in Network Tab Missing?

Hey Guys,

@Apple

I am trying to get a response from this CloudFlare Axios Call in the “Network Tab on Chrome” for example.

What seems to happen is it populates with “no data” and then 500-1500ms later, the actual data is logged in the console on Wappler (see below).

Am I missing something with the return / response in the Code?

Image posts to CloudFlare just fine with a 304 Response

WAPPLER CONSOLE

App listening at http://localhost:3000
server-connect:router Serving serverConnect /api/TEST_cf_upload_img +0ms
server-connect:app Executing action step cfUpload +0ms
server-connect:app options: { path: '/uploads/test8.jpg', img_name: 'test8.jpg' } +0ms
{"result":{"id":"0a734adf-81d8-4ec0-9679-c1b466da0d00","filename":"test8.jpg","uploaded":"2022-02-21T19:46:45.442Z","requireSignedURLs":false,"variants":["https://imagedelivery.net/ZFpmFfUMgrq3swZTSeGQxA/0a734adf-81d8-4ec0-9679-c1b466da0d00/original","https://imagedelivery.net/ZFpmFfUMgrq3swZTSeGQxA/0a734adf-81d8-4ec0-9679-c1b466da0d00/designer"]},"result_info":null,"success":true,"errors":[],"messages":[]}

JS MODULE

const axios = require('axios'); // you will need to install this
const { toSystemPath } = require('../../../lib/core/path');
const fs = require('fs')
const FormData = require('form-data');

exports.cfUpload = async function (options) {

const srcImgPath = options.path;  //image path on the server
let path = toSystemPath(this.parseRequired(this.parse(options.path), 'string', 'fs.exists: path is required.'))
let srcPath = fs.createReadStream(path);

var data = new FormData();

const contents = fs.readFileSync(path, { encoding: 'utf-8' });
data.append('file', fs.createReadStream(path));

var config = {
    method: 'post',
    url: 'https://api.cloudflare.com/client/v4/accounts/45cea078ebef87fccfbc40e7e0d86331/images/v1',
    headers: {
        'X-Auth-Key': 'f566c4e2cb169ebe13f0041aa0c4439d712eb',
        'X-Auth-Email': 'robbyd@kodiak-coolers.com',
        ...data.getHeaders()
    },
    data: data
};

axios(config)
    .then(function (response) {
        console.log(JSON.stringify(response.data));
        return (response.data.result.id);
    })
    .catch(function (error) {
        responseError = true;
        console.log(error);
    });

// if (responseError) {
//     throw response;
// }
// else {
//     // console.log('RESPONSE: ', response);
//     return response;
// }

}

HJSON MODULE

{
type: 'cfUpload_cfUpload',
module : 'cfUpload',
action : 'cfUpload',
groupTitle : 'My Modules',
groupIcon : 'fas fa-lg fa-project-diagram comp-images',
title : 'cfUpload Image',
icon : 'fas fa-lg fa-file-alt comp-images',
dataPickObject: true,
    dataScheme: [
    {name: 'response', type: 'text'}
    ],
properties : [
    {
    group: 'Image Path',
    variables: [
        { name: 'actionName', optionName: 'name', title: 'Name', type: 'text', required: true, defaultValue: ''},
        { name: 'path', optionName: 'path', title: 'Path', type: 'text', required: true, defaultValue: '', serverDataBindings: true}
        { name: 'name', optionName: 'img_name', title: 'File Name', type: 'text', required: true, defaultValue: '', serverDataBindings: true, allowPaste: true}
        { name: 'output', optionName: 'output', title: 'Output', type: 'boolean', defaultValue: false }
    ]
    }
]
}

I think I’m getting famous now

I believe the problem here is a race condition, your module is returning something (spoiler: nothing) instead of return (response.data.result.id);

This might be hard to understand at first. You have to understand this:

axios(config)
    .then(function (response) {
        console.log("I got Axios response!");
        console.log(JSON.stringify(response.data));
        return (response.data.result.id);
    })
    .catch(function (error) {
        responseError = true;
        console.log(error);
    });
console.log("I run after Axios!")
// implicit return; at the end of the script

The problem is, if you run the script, your module is going to say “I run after Axios” and return; before Axios actually finishes and says “I got Axios response!”

As I’m not experienced enough dealing with these kind of issues, I’m going to kindly ask you to run the code with the changes above and say if I predicted the outputs correctly

This happens because you’re running an asynchronous function:

exports.cfUpload = async function (options) {

You can’t expect the code to act like synchronous. In other words, you can’t expect the script to hang at:

axios(config).then(...)

It will call that and immediately move to the next line, it won’t wait till the HTTP request completes

The .then().catch() syntax is slightly old-school, we now use async/await:

const resp = await axios.get('https://jsonplaceholder.typicode.com/posts');
console.log(resp.data);

So, to solve this problem, maybe you can use async/await syntax to prevent mixing behaviours. Async/await allows you to write asynchronous code in a synchronous manner

Ok Cool! let me take a look into this…

This was my response from the code you sent over (which pretty much shows what you explain) that it is not waiting it simply moves to next line of code.

  server-connect:router Serving serverConnect /api/TEST_cf_upload_img +8s
  server-connect:app Executing action step cfUpload +8s
  server-connect:app options: { path: '/uploads/test8.jpg', img_name: 'test8.jpg' } +0ms
I run after Axios!
I got Axios response!
{"result":{"id":"500011fd-11d1-400c-cf14-775611958b00","filename":"test8.jpg","uploaded":"2022-02-21T20:21:53.590Z","requireSignedURLs":false,"variants":["https://imagedelivery.net/ZFpmFfUMgrq3swZTSeGQxA/500011fd-11d1-400c-cf14-775611958b00/original","https://imagedelivery.net/ZFpmFfUMgrq3swZTSeGQxA/500011fd-11d1-400c-cf14-775611958b00/designer"]},"result_info":null,"success":true,"errors":[],"messages":[]}

SOLVED WITH THIS FOR ANYONE WONDERING

    const axios = require('axios'); // you will need to install this
const { toSystemPath } = require('../../../lib/core/path');
const fs = require('fs')
const FormData = require('form-data');

exports.cfUpload = async function (options) {

    const srcImgPath = options.path;  //image path on the server
    let path = toSystemPath(this.parseRequired(this.parse(options.path), 'string', 'fs.exists: path is required.'))
    let srcPath = fs.createReadStream(path);

    var data = new FormData();

    const contents = fs.readFileSync(path, { encoding: 'utf-8' });
    data.append('file', fs.createReadStream(path));

    const response = await axios({
        method: 'post',
        url: 'https://api.cloudflare.com/client/v4/accounts/IMAGE ACCOUNT/images/v1',
        headers: {
            'X-Auth-Key': 'API KEY,
            'X-Auth-Email': 'EMAIL,
            ...data.getHeaders()
        },
        data: data
    });

    return (response.data.result.variants[0]); // Return the URL For the Designer

}