How to fetch JSON using an object with request-promises


#1

I have a simple skill which does the following. When LAUNCH-ed, it reroutes to another intent where I am trying to connect a database which is on subratasarkar.com and fetch some user information form there. My code in app.js is like this:

app.setHandler({
  LAUNCH() {
    return this.toIntent("LinkAccountIntent");
  },

  async LinkAccountIntent() {
    var request = require("request-promise");
    await request({
      method: "POST",
      uri: "https://subratasarkar.com/actions.php",
      json: true,
      data: {
        action: "json_data"
      }
    }).then(body => {
      //const data = JSON.parse(body);
      //this.ask(data.user.name);
      console.log(body);
    });
  }
});

But I always get body as undefined.

But when I am making the same request using jQuery in a simple html file, it works. I get the data back from the server and could PARSE is fine. The JSON structure coming from the server is like the following:

{
   user: {
       email: "[email protected]"
       id: "amzn1.account.XXXXXXXXXXXXXXXXXXXXX"
       name: "Jenny Morrison"
   }
}

I added webhook.jovo.cloud in my MySql access list already to make sure it can connect the database remotely. No luck!

What is the right way to call a third party API url using request and then collect it inside promise? Please suggest.


#2

Take a look here:


#3

Thank you @jan !

What if I need to send a POST request like in my example? The ultimate objective is to send Amazon user’s data after account linking to my server and save those in a table. The structure of the object I need to could be like this:

const options = {
   uri: 'https://subratasarkar.com/page.php',
   json: true,
   data: {
      email: user_email_address,
      profile_id: user_profile_id
      action: "save_user"
   }
}

const data = await requestPromise(options);

user_email_address and user_profile_id I will be collecting from Amazon response.
Because in the PHP file I am use $_POST to retrieve the values like $_POST['email'].

Will this work? How will I tell request-promise-native that this is a post request? Can I add a property in my object like method: 'POST' ?

Sorry for shooting so many question lately!

The thing I cannot figure out is when I am sending the same request using jQuery, I get my desired value but always getting undefined with request and promise. I in fact tried the above approach of adding method and data properties in options object, but it did not work. Please let me know where I am doing wrong! :frowning:


#4

Hi, sorry for getting back for one more time.

The following code block always logging undefined

async function getRandomQuote() {
  const options = {
    method: "POST",
    uri: "https://subratasarkar.com/process_login.php",
    body: {
      action: "json_data"
    },
    json: true
  };
  const data = await requestPromise(options);
  console.log(data);
  return "";
}

Whereas this logs the correct data

async function getRandomQuote() {
  const options = {
    method: "POST",
    uri: "https://subratasarkar.com/process_login.php?action=json_data",
    json: true
  };
  const data = await requestPromise(options);
  console.log(data);
  return "";
}

I must be doing something wrong. Isn’t there a way to pass raw JavaScript object with promises? I am looking into a number of threads and trying this for last 2 hours with no luck! Please help.


#5

Hi there. I think the best resource to consult is the request-promise docs: https://github.com/request/request-promise#post-data-to-a-json-rest-api


#6

Thank you! I will try that and let you know the result.


#7

You could use axios too. It is a much lighter library and for lambdas is much better than request-promise.

Regards


#8

@jan @Nic Thank you so much for your helping me to get this work. Unfortunately I tried both approaches. Here is what I get.

With request-promise I always get undefined. Here is the code.

const rp = require('request-promise');
...
const options = {
    method: "POST",
    uri: "https://subratasarkar.com/process_login.php",
    body: {
      action: "json_data"
    },
    json: true
  };

  await rp(options)
    .then(function(parseBody) {
      console.log(parseBody);
    })
    .catch(function(err) {
      console.log(err);
    });

With request-promise-native I always get undefined as well.

With axios I am getting TypeError: Converting circular structure to JSON. If you go to https://subratasarkar.com/process_login.php?action=json_data you should see the JSON output, which I want to parse in my skill. Here is my code:

var axios = require("axios");
axios
    .get(url, { params: { action: "get_test" } })
    .then(response => {
      console.log(response);
      // If I apply JSON.parse on response, it is saying
      // SyntaxError: Unexpected token o in JSON at position 1
    })
    .catch(error => {
      console.log(error);
    });

The only thing working is this:

const options = {
    method: "POST",
    uri: "https://subratasarkar.com/process_login.php?action=json_data",
    json: true
  };

  const data = await requestPromise(options);

The above code is returning the object I want (Please see the above screenshot).
This amazon user is created by me for testing purpose only hence no harm sharing it.

But this won’t work since I have to sent data as object because there will be a set of key/value pairs I need to send to my API and I cannot send those as query string parameters.

I am totally screwed up!! Please help…


#9

I am getting the data with a post? And when you say you cannot send data in that way because you have to send an object is not what a post is there for? I will share with you a couple of get and posts that works. Are your API public? Can u share the URL?


#10

Hi @Nic yes, the API is public. You are free to use the following endpoint:
https://subratasarkar.com/proess_login.php?action=json_data

The objective is to POST an object from my skill to the API, which will then get saved in the database. After successful save the API will create a JSON and return it back to the skill. Sine I need to send the data as POST, I am using it in this endpoint because the ultimate goal is to POST and then get something back from the API.

In the above endpoint I am using an echo to send the JSON back.

Like this (sorry for adding a PHP code here):

$objJson = json_encode(array(
     "user" => array(
         "id"  => last_intersted_id,
         "name => user_primary_email,
          "email" => user_email_last_inserted,
      ),
));

echo $objJson;

What it does it simple. It gets one record from the database and return it as JSON.

Here is another:
https://subratasarkar.com/process_login.php?action=save

It takes the following parameters:

action, name, email and clientId (string)
Stores the data in database and echo-es Id, Name and Email of the user just in JSON format.

$objJson = json_encode(array(
        "user" => array(
                "id"    => $row["id"],
                 "name"  => $row["user_name"],
                 "email" => $row["primary_email"],
         ),
));

echo $objJson;

PS: Accessing https://subratasarkar.com/process_login.php?action=json_data or https://subratasarkar.com/process_login.php?action=save will throw error in JSON format since I am checking with $_POST.

The output JSON is logged in console.

This is how I am calling it from jQuery:

$("#btnJson").bind("click", function() {
        $.ajax({
          method: "POST",
          async: false,
          url: "process_login.php",
          data: {
            action: "json_data"
          },
          success: function(response) {
            const data = JSON.parse(response);
            console.log(data);
          },
          failure: function() {
            alert("Failed");
          }
        });
      });

EDIT: Just found this thread and going through it gives me an idea that Axios has major issues with PHP as far as POST is concerned.


#11

Hey sorry for the late response, do you still need help with this?


#12

@Nic as far as posting data as object, yes, I am still facing the same issue. When I am sending as Query strings I am getting that work but ideally I always prefer to use JS objects for POST-ing data to server. Please let me know if that could be achieved anyway.


#13

@emfluenceindia it is possible indeed (and also very normal) to send data with a post!

Here an example of a post that is working for me:

const res = await axios({
url: "https://myApiUrlFoPost",
method: "post",
responseType: "json",
headers: { Authorization: "Basic xqwertasdfgyzcvf" },
data: {
  source: {
    folder: "myfolder",
    fileName: "myfile",
    fileFormat:"mp4",
    authorization: {
      sessionToken: "xxxxxxxxx"
    }
  }
  }
});

please not that you should set response type to json and you MUST NOT stringify the data json


#14

Thank you so much for your quick reply. I will try again and get back to you asap. :slight_smile:


#15

Is source{...} a required node? I formatted my object without it and it didn’t work. And what should I put for headers {}?


#16

This all depends on what the API you are using specifies. That is like asking what parameters would I pass to call any function–there is no catch all it is whatever the spec is.

These are very general REST API questions that would be answered in things like the Axios docs/the docs for the API you are using.


#17

Come on, source Is part of my example… The data object is the one that contains your object data. Same for headers, it was in my example in case you had to send headers too… Have you read the documentation related to axios? I think will give you all the answers you need.


#18

Sorry for some questions that might look stupid.


#19

Hi @emfluenceindia, no worries, the Jovo community is open for everyone :slight_smile: However, please keep in mind that for some not Jovo-specific things (like making API calls), other resources might help you better and faster, like the Axios Docs. Always happy to help with Jovo-related issues!


#20

@emfluenceindia Really sorry if My message sounded wrong I wrote it on the way home on the tube…

Not meant to imply your questions are stupid I was suggesting you to read the Axios docs because will save time for you to achieve what you really need.

Apology for my reply yesterday I thought was clear I did not meant anything else but helping :slight_smile: