NodeJS GET request not working with AngularJS - javascript

I have this web app that is for sharing photos.
Now I have this route that is supposed to return the photos of all the users from the following array.
Route:
router.get('/getphotos',function(req, res){
var reqPhotos = [];
console.log( "\n" + req.body.username + "\n");
try{
for(x =0; x < req.body.following.length; x++){
reqPhotos.push({username: req.body.following[x].username});
}
}
catch(err){
console.log(err);
}
Photo.find({username: reqPhotos}).exec(function(err, allPhotos){
if(err){console.log(err);}
else{
res.json(allPhotos);
}
});
});
I have found out that the req.body.following was undefined. This is how I was calling it using angular:
$scope.getPhotos = function(){
if($scope.identification){
flng = angular.copy($scope.identification.following);
flng.push($scope.identification.username);
var data = {username: $scope.identification.username, token: $scope.identification.token, following: flng}
//IDENTIFICATION HAS ALL THE INFO.
$http.get('/users/getphotos', data).success(function(response){
$scope.photos = response;
});
}
}
Why does this happen and how to fix it?
Thanks!

Not sure about the server side, but I see two problems in the angular code. You cannot pass a body when doing an HTTP GET request. Try to pass any necessary data through the url.
Also, the actual data that is returned, will be in response.data. Do something like this:
var urlData = ""; //add any url data here, by converting 'data' into url params
$http.get('/users/getphotos/' + urlData).then(function(response){
$scope.photos = response.data;
});
For constructing the urlData, have a look at this question.
Of course, you will have to adjust the server so it reads the data from the url, rather than from the body.

I don't know what the Content-Type in request request header, is that application/json or application/x-www-form-urlencoded or other. Every content type have to be treated differently. If you use expressjs, try using multer to handle request with multipart-form content type, I usually use it in my application.

$http doesn't take a 2nd parameter for a data object in GET method. However, $http does accept a data object as the 2nd parameter in POST method.
You'll need pass it as the params property of the config object and access it in your req.query in node:
$http.get('enter/your/url/', { params: data})

Related

POST to a REST service using Ajax is failing

I am working with a javascript client that I am trying to use to communicate with a server. I have a Javascript function that is POSTing to a Spring Boot REST service. The service is a simple test service that doesn't do much...
#RequestMapping(method = RequestMethod.POST,value="/testservice")
#ResponseBody
public String testPostRequest(#RequestParam String someText)
{
System.out.println("Reached the counting service! Param value: " + someText);
if(someText != null)
{
...
perform some actions
...
}
return("Success");
}
The Javascript I am using to send POST requests to the server is below:
var sendWords = function(toSend) {
var data = { DataList : [toSend] };
var param = { someText: data };
$.post("http://localhost:8080/testservice",param,
function(status,ret) {
alert("We're back "+status);
});
};
The toSend parameter is just a string containing some text that will be posted to the service. Note that the port for the service was set to 8080 in the server's application.properties file.
When I call the Javascript function and post the string to the service, I get the following log message from the server:
2019-07-28 20:00:06.292 WARN 80844 --- [nio-8080-exec-8] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.bind.MissingServletRequestParameterException: Required String parameter 'someText' is not present]
I am doing something wrong, but cannot figure out what it is. I am sending an object that is tagged as the someText string, but it is not being recognized by the server for some reason.
Can someone tell me what I am missing? How do I get this to work?
var data = { DataList : [toSend] };
var param = { someText: data };
Here data is not string.
You may need to stringify it.
var param = { someText: JSON.stringify(data) };
You are missing the value in the #RequestParam(), such as #RequestParam(value="someText", required=true).
You could use #PathVariable too.
This could be helpful:
#RequestParam vs #PathVariable

Get intents, entities, contexts and all data

In the case, the actually conversation-simple have one function with all the values, but the function update every time if flows conversation.
I want create one function or other form to be able to capture all that data that is currently on the data.
In the case have Intents, context, entities, etc.
conversation.message(payload, function(err, data) {
if (err) {
return res.status(err.code || 500).json(err);
}
return res.json(updateMessage(payload, data));
});
});
The data inside updateMessage parameter have all I need, but if I create other function and try get this values, does not work.
In the case I use the values and get with app.js for open some REST webservice.
I try it:
function login (req, res) {
numberOrigin = null;
sessionid = null;
var dataLogin = {
data: { "userName":"xxxxx","password":"xxxxx","platform":"MyPlatform" },
headers: { "Content-Type": "application/json" }
};
client.registerMethod("postMethod", "xxxxxxxxxxxxxxx/services/login", "POST");
client.methods.postMethod(dataLogin, function (data, response) {
if(Buffer.isBuffer(data)){
data = data.toString('utf8');
console.log(data);
var re = /(sessionID: )([^,}]*)/g;
var match = re.exec(data);
var sessionid = match[2]
console.log(sessionid);
}
});
}
function openRequest(data, sessionid, numberOrigin ){
//console.log(data); dont show the values.. show the data response of login
var dataRequest = {
data: {"sessionID": sessionid,
"synchronize":false,
"sourceRequest":{
"numberOrigin":numberOrigin,
"description": JSON.stringify(data.context.email) } },
headers: { "Content-Type": "application/json" }
};
numberOrigin +=1;
client.post("xxxxxxxxxxxxxxxxxx/services/request/create", dataRequest, function (data, response) {
if(Buffer.isBuffer(data)){
data = data.toString('utf8');
console.log(data);
}
});
}
function updateMessage(res, input, data, numberOrigin) {
var email = data.context.email; // this recognize but this function is responsible for other thing
if (email === 'xxxxxxxxxxxx#test.com') {
console.log(data);
login(data);
openRequest(data, sessionid, numberOrigin)
}
}
In case, I just want get the values with my app.js for use inside REST. I got it with ajax but everything on the client side (index.html), and that made me show my credentials, so I decided to do it in REST for security my code..
If have some form to solved this, please let me know.
If have other form to do it, I'll be happy to know.
Thanks advance.
The issue is likely that you need to write to the response object res.. In the updateMessage function the response is passed in. In order for data to be sent back to the browser you need to write to the response. I have a demo app which calls the weather channel to get the weather based on an intent, similar to what you are trying to do with your login function. Please take a look at this code
https://github.com/doconnor78/conversation-simple-weather/blob/master/app.js#L130
You will need to pass the original res (response) object into the appropriate function and then write data to the response (res) once you get it from the third party service.

Angular with hapi js server jsonp

I have an endpoint defined at /api/profile which accepts post parameters.
var http = require('http');
var serverConfig = require('../server.config.js');
var request = require('request');
module.exports = function(server){
server.route({
method: 'POST',
path: '/api/profile',
handler: getProfileData
});
function getProfileData(request, reply){
var battleTag = request.payload.battleTag;
getProfileDataHttp(battleTag, function(err, data){
if(err){
reply(new Error(err));
}
reply(data);
});
}
function getProfileDataHttp(battleTag, callback){
var key = serverConfig.battleNet.apiKey;
var tag = encodeURIComponent(battleTag);
var url = 'https://eu.api.battle.net/d3/profile/'+ tag + '/?locale=en_GB&callback=JSON_CALLBACK&apikey=' + key;
console.log(url);
request(url,function(error, response, body){
if(error){
callback(err);
}
if(!error && response.statusCode ==200){
callback(null, body);
}
});
}
};
it is calling an api with a json callback, when I am receiving the data it is in format:
JSON_CALLBACK({ json data here})
how can I get this endpoint to return just the json data, I have tried JSON.parse() but it causes errors in the server.
the angular service that calls this endpoint is like below:
function getProfileData(battleTag){
var defer = $q.defer();
var tag = validTag(battleTag);
if(!tag){
defer.reject('Invalid Tag please use format 1[a-z]11[a-z0-9]#4[0-9]');
return defer.promise;
}
$http.post('/api/profile', {
battleTag: battleTag
})
.success(function(data){
if(data.reason){
defer.resolve(data.reason);
}
defer.resolve(data);
})
.error(function(err){
defer.reject(err);
});
return defer.promise;
}
the call would work when using $http.jsonp in angular however I had to create the server to hide the secret key from the client
Your question is a bit confusing. You are talking about JSONP, but you want to fetch the data directly.
The whole point of JSONP is to return the data encapsulated inside a function that you choose. You then simply have to execute it.
If you want the data in a direct way, don't use JSONP. Simply do a "normal" call.
After having a quick look at the Battle.net API, it seems that to get the data directly, you should simply omit the 'callback' parameter in the URL of your request.
Thus, your request URL would looks like that:
var url = 'https://eu.api.battle.net/d3/profile/'+ tag + '/?locale=en_GB&apikey=' + key;

making ajax request in meteor helpers

How can i wait until the ajax request finishes when returning data to a meteor helpers method.
For example,
Template.item.helpers({
itemName:function () {
var user = Meteor.user();
$.when(reallyLongAjaxRequest()).done(function (a1) {
//tried using jquery when
return "Item Name should have this because it waited";
});
return " Doesnt wait at all";
}
});
I have a reallyLongAjaxRequest() running and i would like it to finish before continuing on with my itemName helper. The log statement to console always shows undefined but that's because the ajax request hasn't finished. I tried using the jquery when with no luck. Any ideas
Edit:
I should mention that i am inside the helper function for a reason. I need the item 'id' being rendered so that i can run the ajax request with that paramater. Using reactive sessions would be perfect but i don't know of a way to get currently rendering items outside of the helpers method definition?
An unnamed collection is one where null is passed for the name. It is an in-memory data structure, not saved to the database. (http://docs.meteor.com/#meteor_collection)
OK, given a Meteor collection called "items" and wanting to do an ajax request for each item based on the item _id, and then being able to reference the ajax result in a template, this is what I'd do:
(roughly)
var Items = new Meteor.Collection('items');
var Results = new Meteor.Collection(null);
Items.find().observeChanges({
added: function (id) {
$.get(url, {id: id}, function (data) {
if (Results.findOne(id))
Results.update(id, {$set: {result: data}});
else
Results.insert({_id: id, result: data});
});
}
});
Template.item.itemName = function (id) {
var doc = Results.findOne(id);
if (doc)
return doc.result;
else
return "";
};
inside your html you'll need to pass in the id to the helper:
{{itemName _id}}
Is there no way to just timeout for a few seconds when defining the helper so that my ajax request finishes without immediately returning.
No, with reactive programming things happen immediately, but you update when you have new stuff.
Make your ajax request separately, and when it completes, have it store the result in a Session variable. Then have your template helper return the value of the Session variable. Roughly...
$.get(url, function (data) {
Session.set('result', data);
});
Template.item.itemName = function () {
return Session.get('result');
};
Session is a reactive data source, so your template will automatically updated when the result of the ajax call comes in. (Naturally you can choose to call the Session variable anything you like, I just used "result" as an example).
This works and tested in MeteorJS > 1.3.x
Add the http package from the console meteor add http
Example POST call with data elements being sent to server and with custom headers.
HTTP.call('POST', tokenUri, {
data: {
"type": 'authorization_code',
//"client_id": clientId,
"code": code,
"redirect_uri" : redirectUri,
},
headers: {
"Access-Control-Allow-Origin" : "*",
"Access-Control-Allow-Credentials" : "true",
"Access-Control-Allow-Methods" : "GET,HEAD,OPTIONS,POST,PUT",
"Access-Control-Allow-Headers" : "Access-Control-Allow-Headers, Origin,Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers",
}
},function(error, response) {
if ( error ) {
console.log( error );
} else {
console.log( response );
}
});

Questions about the scopes, node.js, and express

I really suck at understanding scopes and other things of that nature in just about every language. Right now I am building an express application that takes user input and then queries an arbitrary api and then feeds it to the console. To handle the rest api, I am using shred. I know I can use nodes built in get request, but for some reason, I could never get it to work. The user makes the following get request to my app, /query?query=. This is what I have now. I can't really describe what I'm doing so pleas read the code comments.
var http = require('http');
var Shred = require("shred");
var assert = require("assert");
exports.query = function(req, res){
//thequery is the string that is requested
var thequery = req.query.query;
var shred = new Shred();
console.log("user searched" + " " + thequery);
console.log();
//The if statement detects if the user searched a url or something else
if (thequery.indexOf("somearbitratyrestapi.com") !== -1){
console.log("a url was searched");
//find info on the url
var thedata = shred.get({
url: "http://somearbitratyrestapi.com/bla/v2" + thequery,
headers: {
Accept: "application/json"
},
on: {
// You can use response codes as events
200: function(response) {
// Shred will automatically JSON-decode response bodies that have a
// JSON Content-Type
//This is the returned json
//I want to get this json Data outside the scope of this object
console(response.content.body);
},
// Any other response means something's wrong
response: function(response) {
console.log("ohknowz");
}
}
});
//I want to be able to see that json over here. How do?
}else{
console.log("another thing was searched");
}
/*
res.render('search-results', {
result: 'you gave me a url',
title: 'you gave me a url'
});
*/
};
I tried doing this
var http = require('http');
var Shred = require("shred");
var assert = require("assert");
exports.query = function(req, res){
//thequery is the string that is requested
var thequery = req.query.query;
var shred = new Shred();
//I created a variable outside of the object
var myjson;
console.log("user searched" + " " + thequery);
console.log();
//The if statement detects if the user searched a url or something else
if (thequery.indexOf("somearbitratyrestapi.com") !== -1){
console.log("a url was searched");
//find info on the url
var thedata = shred.get({
url: "http://somearbitratyrestapi.com/bla/v2" + thequery,
headers: {
Accept: "application/json"
},
on: {
// You can use response codes as events
200: function(response) {
// Shred will automatically JSON-decode response bodies that have a
// JSON Content-Type
//This is the returned json
//I set myjson to the returned json
myjson = response.content.body
},
// Any other response means something's wrong
response: function(response) {
console.log("ohknowz");
}
}
});
//Then I try to output the json and get nothing
console.log(myjson);
}else{
console.log("another thing was searched");
}
/*
res.render('search-results', {
result: 'you gave me a url',
title: 'you gave me a url'
});
*/
};
Sorry for the bad explanation of my problem. Can someone please help or explain what is going on.
So you think you need to move data out of your nested scope, but the opposite is true. Within the nested scope where you have access to your upstream JSON response, you need to access the res object and send it though:
myjson = response.content.body
res.send(myjson);
However, long term you'll need to do some more node tutorials and focus on how to use callbacks to avoid deeply nested function scopes.

Categories