RE: How to interact with discourse platform using REST API's

I am able to get the data from by using the API with a status code 200 but while parsing it, the local server crashes with an error: [Uncaught SyntaxError: Unexpected end of JSON input at JSON.parse].

It is happening while trying to get users, posts, or even categories.

const fetch = require('node-fetch');
let url = 'https://metastudio.org/groups.json';

let settings = { method: "Get" };

fetch(url, settings)
    .then(res => res.json())
    .then((json) => {
        console.log(json.groups);
        console.log(json.groups[0]);
    });

===========================================================

const fetch = require('node-fetch');
let url = 'https://metastudio.org/categories.json';

let settings = { method: "Get" };

fetch(url, settings)
    .then(res => res.json())
    .then((json) => {
        console.log(json);
        //console.log(json);
    });

Hi Bir,

I am able to fetch the groups and categories data successfully using node-fetch library. can you try to replace your code with this ? and try once again.
i hope this answer helps you.

1 Like

Problem:

I am able to get the data from by using the API with a status code 200 but while parsing it, the local server crashes with an error: [Uncaught SyntaxError: Unexpected end of JSON input at JSON.parse].

It is happening while trying to get users, posts, or even categories.

Solution:

const fetch = require('node-fetch');
let url = 'https://metastudio.org/groups.json';

let settings = { method: "Get" };

fetch(url, settings)
    .then(res => res.json())
    .then((json) => {
        console.log(json.groups);
        console.log(json.groups[0]);
    });

===========================================================

const fetch = require('node-fetch');
let url = 'https://metastudio.org/categories.json';

let settings = { method: "Get" };

fetch(url, settings)
    .then(res => res.json())
    .then((json) => {
        console.log(json);
        //console.log(json);
    });

Hi Bir,

I am able to fetch the groups and categories data successfully using node-fetch library. can you try to replace your code with this ? and try once again.
i hope this answer helps you.

1 Like

Thank You, the above mentioned code which you suggested works.
I was trying:-
var url=secret.url;
var options={
method:‘GET’
};
https.get(url,options,function(response){
console.log(response.statusCode);
response.on(‘data’,function(data){
console.log(JSON.parse(data));
});
});

This was giving error ‘Unexpected end of JSON input at JSON.parse’.

var https = require("https");

var url="https://metastudio.org/groups.json";
//var options={method:"GET"};

https.get(url, function(res){
    var body = '';
    res.on('data', function(chunk){
        body += chunk;
    });
    res.on('end', function(){
        var Response = JSON.parse(body);
        //console.log("Got a response: ", Response);
        console.log("Got a response: ", Response.groups);
        //console.log("Got a response:", Response.groups[0]);
    });
}).on('error', function(e){
      console.log("Got an error: ", e);
});

I modified your code a little bit. after modification it is working properly. if you want you can try this code also.

1 Like
  function addNewUser(name,email,password,userName){
    const url=secret.url+'users';
    const options={
    method:'POST',
    headers:{"Content-Type": "application/json",'Api-Key': secret.key ,'Api-Username': 'system'}
  };
  var data={
  "name": name,
  "email": email,
  "password": password,
  "username": userName,
  "active": true,
  "approved": true,
  "user_fields[1]": "string"
};
  data=JSON.stringify(data);
  console.log(data);
  const request=https.request(url,options,function(response){
	console.log(response.statusCode);
    if(response.statusCode===200){
      var body='';
      response.on('data',function(chunk){
        body+=chunk;
      });
      response.on('end',function(){
        var result=JSON.parse(body);
        console.log(result);
        if(result.success===true && result.active === true){
          console.log('yes');
        }else{
	      console.log('no');
         }
       });
     }else{
     	console.log('no');   
       }
  });
  request.write(data);
  request.end();
  return true;
}

I am trying to add a new User using this code, I get a statusCode of 200 but
{
success: false,
message: ‘You have not completed all the user fields’
} objects comes as a response.
I am unable to understand which user field I am missing. Kindly help.

var https = require("http");
var querystring = require('querystring');

secret= {"url": "http://localhost:9292/","key": "1605437245731e6a74797ba82e34f37ed21038b3b2102dd6c929fd6c437b92bd"}

 function addNewUser(name,email,password,userName){
    const url=secret.url+'users';

  var data={
  "name": name,
  "email": email,
  "password": password,
  "username": userName,
  "active": true,
  "approved": true,
  "user_fields[1]": "Student"
};

// values of user_fields[1] are Curious Member, Student, Teacher,Researcher,Teacher Educator,Citizen Scientist,STEM Activist,Administrator,Social Worker,Home Schooling Parent


data=querystring.stringify(data);

  const options={
    method:'POST',
    headers:{'Api-Key': secret.key ,'Api-Username': 'siddhudhangar'}
  };

  
  console.log(data);
  console.log(url);

  var request=https.request(url,options,function(response){
	console.log(response.statusCode);
    if(response.statusCode===200){
      var body='';
      response.on('data',function(chunk){
        body+=chunk;
      });
      response.on('end',function(){
        var result=JSON.parse(body);
        console.log(result);
        if(result.success===true && result.active === true){
          console.log('yes');
        }else{
	      console.log('no');
         }
       });
     }else{
     	console.log('no');   
       }
  });
  request.write(data);
  request.end();
  return true;
}

addNewUser("siddhu_dhangar","siddhu123@gmail.com","root12345678","siddhudhangar123");

I modified your code a little bit. Can you try this code once and let me know whether it is working or not in your end.

Below links for your reference:

1 Like

No it isn’t working, without Content-Type in headers, it gives status code 400 or a bad request.
With Content-Type in headers, it still gives the same response:-
{
success: false,
message: ‘You have not completed all the user fields’
}
I tried this with endpoint URL: https://t2.metastudio.org/ and path users with my API key. Should I try with your API key?

I am unable to understand why do we need to send all the 7 fields in data since the discourse API documentation states that only first 4 are mandatory.

No. API key which is written in above code will not work.
I ran above code in my local system. there it is working fine.
now what i will do, i will try to replace my local API endpoint i.e http://localhost:9292/ with https://t2.metastudio.org/ and check whether it is working or not. if it is working then i will let you know.

1 Like

you are right only first four fields are mandatory but while registering the users using api call, we wil have to pass all the seven fields.
I will tell you why we need to pass all the seven fields.
when users register on discourse platform through User Interface, they have to fill some mandatory fields there as you said four fields. after filling all the mandatory details, one activation email is sent to registered user’s email id to activate the account. once the user clicks on that activation link, the account gets activated. and email also gets verified. right.
After account is activated, then user can easily login on to discourse platform.

but in API call we have to pass these three fields such as active, approved and user_fields[1].
Even if we dont pass these three fields, user will get created but problem here is everytime user gets created on discourse platform we (admin users) have to manually activate and approve the user. instead of manually changing these settings , we directly activate and approve the registered users which is registered by api.

user_fields[1] is also mandatory. we made that field mandatory and values of user_fields[1] are Curious Member, Student, Teacher,Researcher,Teacher Educator,Citizen Scientist,STEM Activist,Administrator,Social Worker,Home Schooling Parent

so that’s why these seven fields need to be passed in api call.

Hopefully. now you are doubt is clear. if not then let me know.

1 Like

Thanks, now I understand the need of these fields. The documentation alone was not making things clear.

var https = require("https");
var querystring = require('querystring');

secret= {"url": "https://t2.metastudio.org/","key": "XXXXXXXXXXXXXXXXXXXXXXXX"}

 function addNewUser(name,email,password,userName){
   const url=secret.url+'u';

  var data={
  "name": name,
  "email": email,
  "password": password,
  "username": userName,
  "active": true,
  "approved": true,
  "user_fields[1]": "Student"
};

// values of user_fields[1] are Curious Member, Student, Teacher,Researcher,Teacher Educator,Citizen Scientist,STEM Activist,Administrator,Social Worker,Home Schooling Parent


data=querystring.stringify(data);

  const options={
    method:'POST',
    headers:{'Api-Key': secret.key ,'Api-Username': 'Siddhu_Dhangar'}
  };

  
  console.log(data);
  console.log(url);

  var request=https.request(url,options,function(response){
	console.log(response.statusCode);
    if(response.statusCode===200){
      var body='';
      response.on('data',function(chunk){
        body+=chunk;
      });
      response.on('end',function(){
        var result=JSON.parse(body);
        console.log(result);
        if(result.success===true && result.active === true){
          console.log('yes');
        }else{
	      console.log('no');
         }
       });
     }else{
     	console.log('no');   
       }
  });
  request.write(data);
  request.end();
  return true;
}

addNewUser("siddhu_dhangar","siddhu123@gmail.com","root12345678","siddhu123");

Hi bir, i just tried above code. and i used same api key which you are using for api calling. it is working fine in my end. Can you test the above code again???

Note: Password length should be at least 10 characters.

1 Like

Got it, I was doing JSON.stringify(data) while you did querystring.stringify(data) and now it works. What is the issue in using the former one? The code is working fine now, after the mentioned changes.

I have a query with the GET request. Can I return data from a function making GET request back to the calling function?

function getUser(userName) {
  var body = '';
  var url = secret.url + 'users/' + userName + '.json';
  var options = {
    method: 'GET',
    headers: {
      'Api-Key': secret.key,
      'Api-Username': 'system'
    }
  };

  https.get(url, options, function(response) {
    //console.log(response.statusCode);
    response.on('data', function(data) {
      body += data;
    });
    response.on('end', function() {
      body = JSON.parse(body);
      //console.log(body);
      var id= body.user.id;
      console.log(id);
      return id;
    }).on('error', function() {
      console.log('error');
    });
  });
  return -1;
}

This is returning -1 every time instead of the user id. Even if I try bringing out body by changing it, it returns an empty string only. Can you explain why this is happening and what can I do to rectify this?

Hi Bir,

This happened because of asynchronous call. https.get() function which you wrote above behaves like asynchronous function. because of this problem arises. actually i know how to deal with this kind of asynchronous calls in js frameworks but in node js. i am also first time facing this kind of issue. so if i find any solution on this problem, i will let you know.

Below links for your reference:

1 Like

var https = require(“http”);
var querystring = require(‘querystring’);

secret= {“url”: “http://localhost:9292/","key”: “1605437245731e6a74797ba82e34f37ed21038b3b2102dd6c929fd6c437b921ad”}

var json_data = null;

function addNewUser(name,email,password,userName){
const url=secret.url+‘users’;

var data={
“name”: name,
“email”: email,
“password”: password,
“username”: userName,
“active”: true,
“approved”: true,
“user_fields[1]”: “Student”
};

// values of user_fields[1] are Curious Member, Student, Teacher,Researcher,Teacher Educator,Citizen Scientist,STEM Activist,Administrator,Social Worker,Home Schooling Parent

data=querystring.stringify(data);

const options={
method:‘POST’,
headers:{‘Api-Key’: secret.key ,‘Api-Username’: ‘siddhudhangar’}
};

// console.log(data);
// console.log(url);

var request=https.request(url,options,function(response){
console.log(response.statusCode);
if(response.statusCode===200){
var body=’’;
var result=’’;
response.on(‘data’,function(chunk){
body+=chunk;
});
response.on(‘end’,function(){
result=JSON.parse(body);
if(result.success===true && result.active === true){
response_in_json_format(result);
console.log(‘yes’);
}
else
{
console.log(‘no’);
}
});
}else{
console.log(‘no’);
}
});
request.write(data);
request.end();
return true;
}

addNewUser(“siddhu_dhangar","siddhu123@gmail.com”,“root12345678”,“siddhudhangar123”);

function response_in_json_format(result)
{
	json_data=result
	
	var user_id = null
	user_id = json_data.user_id
	console.log(user_id);

}

What i did here i defined one function named response_in_json_format. once the response is returned from api, the result can be passed in the defined function named response_in_json_format function directly and in response_in_json_format function where you can access user id and whatever data you want to access from the result which i passed into response_in_json_format function. one more thing keep in mind result which i passed there has a local scope not global scope. you can pass the same result in some other functions as argument.

have you found any other solution on it ?
so if you have any other solution over this problem, you can try out that solution also.

i tried a lot solution from yesterday onwards but i have not got any solution. one solution over this problem is make synchronous requests instead of asynchronous requests then your problem will get resolved but generally it is not recommended to use synchronous requests for developing the progressive web application. below i attached few urls from there you will get an answer of why we dont use much synchronous calls.

Below articles for your reference:

https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Asynchronous/Async_await

1 Like

Thanks for the solution, I was thinking of storing the data on response end in a session and then using it through the website. On logout, I will be clearing this session data.

1 Like

i got it .you are storing response in a session that’s fine but for only this api request you are storing response in a session or are you thinking of storing all other api requests response also in a session ?

1 Like

Just the user information in session.

1 Like