Send HTTP.call Json - javascript

I have problems sending a json that will be verified by another server, where then I will get a response from that process has been exist. I'm using HTTP.call, but I have not gotten so far any results in when to functionality.
Already do the tests with postman and everything works me correctly.
Here is a copy of code:
// client side event click button
var jsonStr = JSON.stringify(jsonOBJ);
Meteor.call("Json", jsonStr, function(error, result){
if(error){
console.log("error", error);
}
if(result){
console.log(resul);
}
});
///server side
Json(JsonStr) {
var options = {
data: JsonStr,
headers: {
'content-type': 'application/json'
}
}
try {
var url = "https://api.xxxxxxxxx.com/xxxxxxx-api/4.0/xxxxxx.cgi";
var result = HTTP.call('POST', url, options )
return result;
} catch (err) {
console.log(err)
}
}
//I must receive something like
{
"code": "SUCCESS",
"error": null,
"transactionResponse": {
....
....
....
}
}
That's the answer I'm getting from the server
"{"code":"ERROR","error":"Invalid request format","result":null}"

Fixed problem is when using var str = JSON.stringify (jsonOBJ); From the client and it passes through Meteor.call() when it receives the meteor methods on the server does not arrive with the correct format so the solution is to pass the jsonObj from the client without giving the format and to be received on the server if apply The JSON.stringify (jsonOBJ)

Related

Meteorjs handle scraped data from server to client returns undefined

I am trying to achieve a url preview for my Meteor + React app, where when users paste in a url in a textarea, they'll get a preview of the url. I plan to achieve this by using several npm modules i.e.:
url-regex, and
open-graph-scraper
I understand that in order to avoid any CORS issue, the request should be done server side.
So I have this currently set up:
//on client
import urlRegex from 'url-regex';
const onTextareaChange = e => {
let value = e.target.value;
let testURL = urlRegex().test(value) //returns true if url exists in textarea
console.log(testURL);
if(testURL){
let extractURL = value.match(urlRegex()) //extract the url
extractURL.map(url =>{
console.log(url)
Meteor.call('scrapeURL',{url}, function (result){
console.log(result)
})
})
}
/* console.log(e.target.value) */
setTextarea(e.target.value)
}
//on server
import ogs from 'open-graph-scraper';
/* 24. scrapeURL */
'scrapeURL' ({url}){
new SimpleSchema({
url : { type : String }
}).validate({url})
if(!Meteor.userId){
throw new Meteor.Error('not-authorised!')
} else {
let options = { 'url': url };
ogs(options)
.then(function (result) {
console.log('result:', result);
return result;
})
.catch(function (error) {
console.log('error:', error);
});
}
}
The problem here is, when i tried to console.log the results on the server, the scraped data shows up in the server console. but when i tried to return the results from the server to client, console.log on the client shows undefined.
I haven't got a clue what's wrong with the code.
Your scrapeUrl function doesn't return any data (you only described what the .then() function will return), you should try this way :
import ogs from 'open-graph-scraper';
/* 24. scrapeURL */
'scrapeURL' ({url}){
new SimpleSchema({
url : { type : String }
}).validate({url})
if(!Meteor.userId){
throw new Meteor.Error('not-authorised!')
} else {
let options = { 'url': url };
// here return the full promise :
return ogs(options)
.then(function (result) {
console.log('result:', result);
return result;
})
.catch(function (error) {
console.log('error:', error);
// probably here a need to tell the client that there was an error
//throw new Meteor.Error(error);
});
}
}
Here is a good reading on medium about the use of promises in Meteor :
https://blog.meteor.com/using-promises-and-async-await-in-meteor-8f6f4a04f998

Reading response from Node JS Server

I am working on a program where a specific Java file will be compiled at the Server side and if there is any error in compiling, I will capture the error information and send it back to the client side. However, I have tried many ways to read the JSON Object but to no avail.
So my question is why was I not able to read the error string sent by the server at the client side? I am current using res.data.err to read my error response.
Server Side Code
var cmd=require('node-cmd');
exports.compileTest = function(req,res){
console.log(req.body.data.fileName);
var file = req.body.data.fileName;
var output = "";
output = cmd.get(
'javac solutionTest/'+file,
function(err, data, stderr){
if (err) {
console.log(err);
res.json({ state : 0 ,err});
}
else
res.json({ state : 1});
}
);
}
Client Side Code
$scope.compileSol = function(){
$http.post('/testRun', { data : { fileName : $scope.solutionFileName.name}
}).then(function(res){
if(res.data.state==0){
alert(res.data.err);
}
}).catch(function(error){
});
}
Below is the error I wanted to send over to the web browser
I suppose your err variable that you are sending from your server is a JSON object that has for key: err. If not, you can consider modifying it, the way I do below.
if (err) {
console.log(err);
res.json({ state : 0 ,err: err});
}
else
res.json({ state : 1});
}
The object response on your client side should have the same form as how you sent it. In the way you are sending it from your server, it should be this way you can access it client side:
if(res.state==0){
alert(res.err);
}
}).catch(function(error){
});
My mistake lies in assume err is the exact error output by the server.
Solution is to convert it to String and then send it over.
var cmd=require('node-cmd');
exports.compileTest = function(req,res){
console.log(req.body.data.fileName);
var file = req.body.data.fileName;
var output = "";
output = cmd.get(
'javac solutionTest/'+file,
function(err, data, stderr){
if (err) {
console.log(err);
//added this line
err = err.toString();
res.json({ state : 0 ,err:err});
}
else
res.json({ state : 1});
}
);
}

How to properly return a response and a error from a meteor method

I am trying to return a response or a error on the client side from a meteor method that exists on the server side. The method itself is for submitting a post request to a API when a form is submitted, I would like to on the client side be able to return the API's response so I can send info to the user like, this email address already exists. Here is what I have so far.
I receive a 201 response on the client side in the console.log(result); when I call the method when it is successful but I would like to also console log the error when the POST submissions gives a 400 or any error.
server/main.js
Meteor.methods({
addSub(email) {
var emailAddress = {
"lists": [
{
"id": "1395617465"
}
],
"email_addresses": [
{
"email_address": email
}
]
}
HTTP.post('https://api.constantcontact.com/v2/contacts?api_key=<api-key>', {
headers: {
'Authorization': 'Bearer <token>',
'Content-Type': 'application/json'
},
data: emailAddress
}, function (error, response) {
if ( error ) {
console.log( error );
throwError = error;
} else {
console.log(response);
returnResponse = response;
}
});
return returnResponse;
}
});
client/main.js
Template.info.events({
'submit #cm-subscribe'(event){
event.preventDefault();
var form = event.target;
var email = form.email.value;
Meteor.call('addSub', email, (error, result) => {
console.log(result);
});
}
});
client/main.html
<template name="info">
<h2>Signup For Our Newsletter</h2>
<form id="cm-subscribe">
<input field name="email" type="email" value="email">
<input type="submit">
</form>
</template>
1) Your code currently contains a race condition. The value of returnResponse may or may not be set depending on the order of execution between the callback and the return statement. Instead, you should use Promises, which allow you to wrap asynchronous code in a synchronous way. There is a good post on the Meteor blog about how to do this. Note that this does not affect the client behavior- it would still use callbacks like you have.
2) The reason that you do not see errors on the client is that Meteor intentionally converts all normal Javascript errors (like those returned by HTTP.post) into internal server errors to protect data and source code. What you should do is handle all of the errors on the server side, and return new Meteor.Error objects for expected invalid responses. These can then be handled by the client. A thorough explanation of this can be found in the Meteor Guide.
Something like this:
Meteor.methods({
addSub(email) {
return new Promise((resolve, reject) => {
HTTP.post('<URL>', ..., function(error, response){
if(!error){
resolve(response);
} else if (error == <Some Error Comparison>){
reject(new Meteor.Error("Email.subscription.invalidEmail", "You put in an invalid email"));
}
});
});
}
}

Parsing JSON response body in Express.js

A Node.js/Express.js app makes a RESTful call to another app and receives JSON in response. But the JSON response is not being parsed into new variables. What specific changes need to be made to the code below, so that the JSON body can be successfully parsed into new variables that the receiving Node.js/Express.js app can use for further processing?
Here is the Node.js/Express.js code which is currently receiving the JSON body response:
var url = require('url');
var request = require('request');
app.get('/user**', function(req, res) {
console.log("You Hit The User Route TOP");
request.get(authServer + '/uaa/user', function (error, response, body) {
if(error){console.log('ERROR with user request.')}
if (!error){// && response.statusCode == 200) {
console.log(response.statusCode); console.log(body);
response.on('data', function(chunk){
console.log('inside response.on(data...)');
body += chunk;
});
response.on('end', function(){
console.log('inside response.on(end...)');
body = JSON.parse(body);
var text = '';
for (var key in body){
text += 'Index is: ' + key +
'\nDescription is: ' + body[key]
}
// The Description is: "descriptive string"
console.log("Got a response: ", text);
res.send(text);
});
res.send(body);
};
}).auth(null, null, true, bearerToken);//this inserts bearer token in the GET request
console.log("You Hit The User Route BOTTOM");
});
Here are the nodemon logs for the GET shown in the code. Note that the response.on() blocks are never called because their SYSO never prints:
You Hit The User Route TOP
You Hit The User Route BOTTOM
200
{ long JSON string, which is formatted and truncated below for easier reading }
GET /user 200 182.862 ms - 1296
And here is the formatted and truncated JSON body, which illustrates the format of the data that needs to be parsed into Node.js/Express.js JavaScript variables:
{
"details":
{
"remoteAddress":"127.0.0.1",
"sessionId":null,
"tokenValue":"SomeLongTokenString",
"tokenType":"Bearer",
"decodedDetails":null
},
"authenticated":true,
"userAuthentication":
{
"details":null,
"authorities":
[
{
"authority":"ROLE_ADMIN"
},
{
"authority":"ROLE_USER"
}
],
"authenticated":true,
"principal":"user",
"credentials":"N/A",
"name":"user"
},
"name":"user"
}
The problem is you're acting as though response is a stream that's incrementally giving you the JSON but you've already proven to yourself that's not true with your first console.log(body) statement. Instead, you can parse body immediately and begin working on it. You can also simplify your request handler.
if (error) {
console.log('ERROR with user request.')
return res.sendStatus(500);
}
body = JSON.parse(body);
var text = '';
for (var key in body) {
text += 'Index is: ' + key + '\nDescription is: ' + body[key]
}
// The Description is: "descriptive string"
console.log("Got a response: ", text);
res.send(text);
The following line doesn't wait for your response to be parsed.
res.send(body);
Remove it and wait to respond from your response.on('end') event.
Edit to include restructured request
I'd structure your request differently. You're not streaming your response so there shouldn't be much reason to listen for response events. Also you can get rid of your need for JSON.parse() by letting request handle that for you by indicating that the returning body is JSON.
request({
method: 'GET',
url: authServer + '/uaa/user',
json: true, // indicates the returning data is JSON, no need for JSON.parse()
auth: {
user: null,
password: null,
sendImmediately: true,
bearer: bearerToken
}
}, function (error, response, body) {
if(error){
console.log('ERROR with user request.');
return res.sendStatus(500); // Return back that an error occurred
}
else {
console.log(response.statusCode);
console.log(body);
var text = '';
for (var key in body) {
text += 'Index is: ' + key + '\nDescription is: ' + body[key];
}
return res.status(200).send(text);
}
});

Firebase REST API - how to set character encoding?

I'm calling the Firebase REST API from a Node.js process. The problem I'm seeing is that POSTS fail when the post body contains non-ASCII characters. This is despite the request returning a "200" status, and the name of a node (which doesn't actually get created).
I'm currently trying something like this:
function push(path, object, callback) {
console.log("Pushing to "+path+" on: "+firebase.host);
var fullPath=firebase.basePath+path;
console.log("fullPath="+fullPath);
var body = JSON.stringify(object);
var options = {
host: firebase.host,
port: 80,
method: "POST",
path: fullPath, //gamma.firebase.com/...
agent: false,
headers: {
'content-type': 'application/json',
'Content-Length': body.length,
}
};
var req = http.request(options, function(response) {
var result = "";
console.dir(response.headers);
response.on('data', function(chunk) {
result+=chunk;
});
response.on('end', function() {
console.error("POST response result: "+result);
try {
callback(JSON.parse(result));
} catch(e) {
callback({ error: e });
}
});
response.on('error', function(e) {
console.error("POST response error: "+error);
callback({error: e});
});
});
req.on('error', function(error) {
console.error("POST request error: "+error);
});
req.write(body);
req.end();
}
The contents of "object" can be as simple as:
{"text": "test\u00a0text"}
The result I get back is status 200, and an reasonable-looking child name, which doesn't actually get created.
I've tried setting content-type to a bunch of different things (adding ; charset="UTF-8", for example), and it doesn't seem to affect the results at all.
There is an error in the way we are handling certain types of input which is yielding the erroneous 200 status. We will roll out a fix shortly. To work around the problem in the meantime you can omit sending the Content-Length header. This will allow you to post ASCII and non-ASCII data.

Categories

Resources