Javascript: REST API Mongodb not connecting on Postman - javascript

I'm new to JavaScript and I'm trying to learn how to build REST API's from a local server on my computer. When I test the GET request on Postman, however, it always comes back with an error: Could Not Get Any Response.
The purpose of the REST API is to (a) Store basic information about the planets in the solar system, (b) allow GET requests and (c) allow me to use POST to add more entries in the database.
When I go to postman I use the following URL: localhost:8000/planets
I'm using mongodb and mongoose. I assume the problem is somewhere in my code because I'm not getting a response from the Server but I can't pinpoint where the problem is. Thanks.
var express = require('express');
var bodyParser = require('body-parser');
var _ = require('lodash');
var mongoose = require('mongoose');
var app = express();
app.use(express.static('planet_pages'));
app.use(bodyParser.urlencoded({extended: false}));
app.use(bodyParser.json);
mongoose.Promise = global.Promise;
var promise = mongoose.connect('mongodb://localhost/planet_server', {
useMongoClient: true,
});
promise.then(function(db){
console.log('DATABASE CONNECTED!!');
}).catch(function(err){
console.log('CONNECTION ERROR', err);
});
var Schema = mongoose.Schema;
var planetSchema = new Schema({
name: String,
position: String,
moons: String,
diameterInKm: String,
daysInYear: String,
temperature: String
})
var Planet = mongoose.model('Planet', planetSchema);
Planet.collection.drop();
//*****RAW DATA*****
var planets = [{
name: "Mercury",
position: "Mercury is the first planet from the Sun",
moons: "Mercury has no moons",
diameterInKm: "Mercury's diameter is 4,879km",
daysInYear: "A year on Mercury lasts just 88 days!",
temperature: "The temperature on Mercury is a scorching 427C"},
{ name: "Venus",
position: "Venus is the second planet from the Sun",
moons: "Venus has no moons",
diameterInKm: "Venus's diameter is 12,104km",
daysInYear: "A year on Mercury lasts 225 days!",
temperature: "The temperature on Mercury is 467C. Hot enough to melt lead!"
}];
//*****END OF RAW DATA*****
app.get('/planets', function(req, res){
Planet.find({}).exec(function(err, planets){
if(err) {
return res.status(500).send(err);
}
return res.json(planets);
});
});
app.listen(8000, function(){
console.log('I am listening');
});
EDIT: in the line app.use(express.static('planet_pages'), planet_pages is a folder inside my project folder which contains a couple of HTML pages that I hope to use to make AJAX queries.
Also, supplementary question, in the line app.get('/planets', function(req, res) I'm using /planets as the extension because that's the name of the URL that holds my data in the //*****RAW DATA section. I got this from following a tutorial but I'm not sure why I'm supposed to do it. If anyone could explain this I'd MASSIVELY appreciate it. Thanks.
Also I was advised to use the Planet.collection.drop() to ensure the database refreshes properly when I re-load or make a change to the database. Since I can't even make the GET request work, I'm not sure if I need this line.
Also, I've not put the POST request code in yet because I don't see the point until I can get the GET request function working.

Try commenting out app.use(bodyParser.json)

Related

Evaporate.js upload file with x-amz-security-token: SignatureDoesNotMatch

I want upload a file with evaporate.js and crypto-js using x-amz-security-token:
import * as Evaporate from 'evaporate';
import * as crypto from "crypto-js";
Evaporate.create({
aws_key: <ACCESS_KEY>,
bucket: 'my-bucket',
awsRegion: 'eu-west',
computeContentMd5: true,
cryptoMd5Method: data => crypto.algo.MD5.create().update(String.fromCharCode.apply(null, new Uint32Array(data))).finalize().toString(crypto.enc.Base64),
cryptoHexEncodedHash256: (data) => crypto.algo.SHA256.create().update(data as string).finalize().toString(crypto.enc.Hex),
logging: true,
maxConcurrentParts: 5,
customAuthMethod: (signParams: object, signHeaders: object, stringToSign: string, signatureDateTime: string, canonicalRequest: string): Promise<string> => {
const stringToSignDecoded = decodeURIComponent(stringToSign)
const requestScope = stringToSignDecoded.split("\n")[2];
const [date, region, service, signatureType] = requestScope.split("/");
const round1 = crypto.HmacSHA256(`AWS4${signParams['secret_key']}`, date);
const round2 = crypto.HmacSHA256(round1, region);
const round3 = crypto.HmacSHA256(round2, service);
const round4 = crypto.HmacSHA256(round3, signatureType);
const final = crypto.HmacSHA256(round4, stringToSignDecoded);
return Promise.resolve(final.toString(crypto.enc.Hex));
},
signParams: { secretKey: <SECRET_KEY> },
partSize: 1024 * 1024 * 6
}).then((evaporate) => {
evaporate.add({
name: 'my-key',
file: file, // file from <input type="file" />
xAmzHeadersCommon: { 'x-amz-security-token': <SECURITY_TOKEN> },
xAmzHeadersAtInitiate: { 'x-amz-security-token': <SECURITY_TOKEN> },
}).then(() => console.log('complete'));
},
(error) => console.error(error)
);
but it produce this output
AWS Code: SignatureDoesNotMatch, Message:The request signature we calculated does not match the signature you provided. Check your key and signing method.status:403
What I'm doing wrong
SIDE NOTE
This is the versione I'm using on browser side:
{
"crypto-js": "^4.1.1",
"evaporate": "^2.1.4"
}
You have your crypto.HmacSHA256 parameters reversed. They should all be the other way around. I've been bashing my head against a wall trying to get evaporate 2.x to work for the last week, it's been very frustrating.
I tried your code above and looked over all the docs and forum posts related to this, and I think using Cognito for this auth just doesn't work or isn't obvious how it's supposed to work, even though the AWS docs suggest it's possible.
In the end I went with using Lambda authentication and finally got it working after seeing much misinformation about how to use various crypto libraries to sign this stuff. I got it working last night after rigorously examining every bit of what was going on. Reading the docs also helped get me on the right path as to how the crypto needs to work, it gives example inputs and outputs so you can test for sure that your crypto methods are working as AWS expects them to work:
https://docs.aws.amazon.com/general/latest/gr/sigv4_signing.html
Tasks 1, 2 and 3 are especially important to read and understand.

Node.Js using tmi.js and cleverbot.io trouble

I am currently having trouble with a twitch bot that I am trying to make. I decided to try out Node.js, but I am having a couple of errors. I am using the tmi.js and cleverbot.io libraries, installed via npm. My code so far is as shown below:
var tmi = require('tmi.js');
var cleverbot = require('cleverbot.io');
var options = {
options: {
debug: true
},
connections: {
cluster: "aws",
reconnect: true
},
identity: {
username: "TwitchCleverBot",
password: "APIKEY"
},
channels: ["klausmana"]
};
var client = new tmi.client(options);
var smartbot = new
cleverbot('APIUSERNAME','APIKEY');
client.connect();
client.on("chat", function(channel, userstate, message, self){
if(self){
return;
}
if(message.toLowerCase().includes("cleverbot")){
var lowmessage = message.toLowerCase();
var newmessage = lowmessage.replace("cleverbot", " ");
smartbot.create(function(err, session){
smartbot.ask(newmessage, function(err, response){
client.action(channel, response);
});
});
}
});
This is all the code I have in my app.js so far. The error occurs when I try to make a request to the cleverbot.io, so the tmi.js part works (with as much as I know). It gives me the following error:
Apparently, I am trying to make a JSON parse to a html file, but I really do not understand where and how that happens if anyone is able to help, I would really appreciate it.
P.S : The project is indeed a twitch bot, but my problem was in Node.js and Javascript, so that is why I decided to turn to StackOverflow

How can I access my req.body data/json in Express?

I am new to node.js and I am trying to access json on my node.js server from a post request so I can send it to an API and feed it back to my front-end js file. I can see the json object, but I can't seem to access it(ex: req.body.name) after reading some documentation/stackoverflow posts.
Here is my post route from my server.js file, and packages:
var prettyjson = require('prettyjson');
var express = require('express');
var http = require('http');
var cors = require('cors');
var bodyParser = require('body-parser');
var app = express();
// create application/json parser
app.use(bodyParser.json());
// create application/x-www-form-urlencoded parser
app.use(bodyParser.urlencoded({
extended: true
}));
app.post('/', function(req, res) {
var test = req.body; //If I req.body.name here, it will return undefined
console.log(test);
});
Here is my front end map.js file post function and data:
var locations = [
{name:'Le Thai', coords:{lat:36.168743, lng:-115.139866}},
{name:'Atomic Liquors', coords:{lat:36.166782, lng:-115.13551}},
{name:'The Griffin', coords:{lat:36.168785, lng:-115.140329}},
{name:'Pizza Rock', coords:{lat:36.17182, lng:-115.142304}},
{name:'Mob Museum', coords:{lat:36.172815,lng:-115.141242}},
{name:'Joe Vicari’s Andiamo Italian Steakhouse', coords:{lat:36.169437, lng:-115.142903}},
{name:'eat', coords:{lat:36.166535, lng:-115.139067}},
{name:'Hugo’s Cellar', coords:{lat:36.169915, lng:-115.143861}},
{name:'Therapy', coords:{lat:36.169041, lng:-115.139829}},
{name:'Vegenation', coords:{lat:36.167401, lng:-115.139453}}
];
//convert array to JSON
var jsonStr = JSON.stringify(locations);
$.post('http://localhost:3000/', jsonStr, function(data){
//empty for now
},'json');
End goal: I want to be able to access my data like req.body.name. I tried using typeof on req.body, and it returns an object, however I can't seem to access this object. And I tried using JSON.parse, but realized req.body is already an object. I would like to serve this data to the Yelp API eventually.
Current output(per request) from console.log(req.body):
{ '{"name":"Le Thai","coords":{"lat":36.168743,"lng":-115.139866}},
{"name":"Atomic Liquors","coords":{"lat":36.166782,"lng":-115.13551}},
{"name":"The Griffin","coords":{"lat":36.168785,"lng":-115.140329}},
{"name":"Pizza Rock","coords":{"lat":36.17182,"lng":-115.142304}},
{"name":"Mob Museum","coords":{"lat":36.172815,"lng":-115.141242}},
{"name":"Joe Vicari’s Andiamo Italian Steakhouse","coords":
{"lat":36.169437,"lng":-115.142903}},{"name":"eat","coords":
{"lat":36.166535,"lng":-115.139067}},{"name":"Hugo’s Cellar","coords":
{"lat":36.169915,"lng":-115.143861}},{"name":"Therapy","coords":
{"lat":36.169041,"lng":-115.139829}},{"name":"Vegenation","coords":
{"lat":36.167401,"lng":-115.139453}}': '' }
You're using an array, so it will not be:
req.body.name
but e.g.
req.body[0].name
You probably want to iterate over the array that you get with .forEach or a for loop etc.
The problem is you're not telling the server you're sending it JSON, so it's not getting parsed. Also, as rsp pointed out, to access the first name, you'd want req.body[0].name, not req.body.name.
The dataType parameter on $.post isn't to tell the server what you're sending it, it's to tell jQuery what you're expecting back from the server. To tell the server what you're sending it, use $.ajax and the contentType option:
$.ajax({
url: 'http://localhost:3000/',
type: "POST",
contentType: "application/json", // <====
data: jsonStr,
success: function(data){
//empty for now
}
});
Now, the body-parser module sees the content type on the request, and parses it for you. So for instance, if I change your server file to do this:
app.post('/', function(req, res) {
req.body.forEach(function(entry, index) {
console.log(index, entry.name)
});
});
...then with the change above to the client code, I get this on the server console:
0 'Le Thai'
1 'Atomic Liquors'
2 'The Griffin'
3 'Pizza Rock'
4 'Mob Museum'
5 'Joe Vicari’s Andiamo Italian Steakhouse'
6 'eat'
7 'Hugo’s Cellar'
8 'Therapy'
9 'Vegenation'
For those getting an empty object in req.body
I had forgotten to set headers: {"Content-Type": "application/json"} in the request. Changing it solved the problem

How to access Angular Js data from nodejs

Hi in my angular js file, I have patient objects which contain name, number and appointment date. In my node js file, I use twilio to send a text a patient. What I want to know is how to get the number from the angular js file in order to use it in my node Js file so I can send the patient a text. Thanks.
here is the part of server.js where I send the text message
app.post('/testtwilio', function(req,res){
var cheerio = require('cheerio'),
$ = cheerio.load('file.html'),
fs = require('fs');
fs.readFile('./views/index.html', function (err, html) {
if (err) {
throw err;
} else {
$ = cheerio.load(html.toString());
console.log($scope.patients)//$('.reminder').attr('text'));
}
});
client.sendMessage({
to: '{{patient.number}}',
from: '+16173935460',
body: 'Text sent using NodeJS'
}, function(err, data){
if(err)
console.log(err);
});
})
Here is the patient object in the MainController.js
$scope.patients = [
{
name: 'John Smith',
date: "12/22/2016",
number: 1829191844
},
{
name: 'Matt',
date: "09/15/2016",
number: 1829198344
},
{
name: 'John',
date: "08/25/2016",
number: 1829198844
},
];
Pass the data from the front end to the backend? Have angular call a route on your backend with the data you need and access it with the req.params object.
Is your server.js a node.js controller?
In the angular controller you could import $http and just do a $http.post({myparams}, /myRoute, function(results){console.log(results)})
Like Mike says. The only way to really share files between the front end and the backend is if the files are JSON as that can be read by Angular and Node. However, I usually just use this for static configuration files.

Parsing JSON array nodejs

so I'm learning NodeJS and javascript in general, and playing around with it and I have some problems parsing a JSON. I receive the following from the "user":
{
"sync_contact_list": [
{
"name": "c",
"number": "789",
"email": ""
},
{
"name": "b",
"number": "123",
"email": "a#a.com"
},
{
"name": "a",
"number": "416",
"email": ""
}
]
}
My question is how can i properly parse this to get the individual bits:
{
"name": "a",
"number": "416",
"email": ""
}
I've been trying to do it by doing var jsonObject = JSON.parse(req.body); ,but I keep getting parsing errors, no matter how I vary the JSON that I do receive (individual components, all of it, etc).
Could anyone one point out what I'm doing wrong?
EDIT:
So i use express to deal with the different paths. So i have app.js:
var express = require('express')
, routes = require('./routes')
//var mysql = require('mysql');
var app = module.exports = express.createServer();
// Configuration
app.configure(function(){
app.set('views', __dirname + '/views');
//app.set('view engine', 'jade');
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(__dirname + '/public'));
});
app.configure('development', function(){
app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});
app.configure('production', function(){
app.use(express.errorHandler());
});
// Routes
//app.post('/', routes.syncServiceIndex);
app.post('/syncService', routes.synchServicePost);
app.get('/syncService/:syncServiceUser/sync', routes.synchServiceSync);
app.post('/syncService/:syncServiceUser/push', routes.synchServicePush);
app.del('/syncService/:syncServiceUser', routes.synchServiceDel);
app.post('/syncService/:syncServiceUser/contacts/push', routes.synchServiceContactsPush);
app.get('/syncService/:syncServiceUser/contacts/sync', routes.synchServiceContactsSync);
app.post('/syncService/:syncServiceUser/contacts/', routes.synchServiceContactsPost);
app.get('/syncService/:syncServiceUser/contacts/:contactId', routes.synchServiceContactsGet);
app.put('/syncService/:syncServiceUser/contacts/:contactId', routes.synchServiceContactsPut);
app.del('/syncService/:syncServiceUser/contacts/:contactId', routes.synchServiceContactsDel);
app.listen(3000);
console.log("Express server listening on port %d in %s mode", app.address().port, app.settings.env);
And then I have index.js, where I basically have the following for each route.
exports.synchServicePost = function(req, res) {
console.log('synchServicePost');
console.log("BODY:"+JSON.stringify(req.body));
var jsonObject = JSON.parse(req.body);
res.statusCode = 200;
res.send("OK\n");
}
The request is made with a line free JSON:
curl -i -d "{'sync_contact_list':[{'name':'c','number':'789','email':''},{'name':'b','number':'123','email':'a#a.com'},{'name':'a','number':'416','email':''}]}" http://localhost:3000/syncService
EDIT: I realized I should probably change the Content Type to application/json. in this case, for JSON.stringify I get the following:
SyntaxError: Unexpected token ILLEGAL
at parse (native)
at IncomingMessage.<anonymous> (/home/alex/peekcode/quipmail/synch/node_modules/express/node_modules/connect/lib/middleware/bodyParser.js:71:15)
at IncomingMessage.emit (events.js:61:17)
at HTTPParser.onMessageComplete (http.js:133:23)
at Socket.ondata (http.js:1029:22)
at Socket._onReadable (net.js:677:27)
at IOWatcher.onReadable [as callback] (net.js:177:10)
Maybe it is already parsed? I do not know (I did not see your whole code).
If it is (or you will parse it the way you need), then specific "bits" will be available like that (see this jsfiddle for a proof):
for (var i=0; i<jsonObject['sync_contact_list'].length; i++){
// here jsonObject['sync_contact_list'][i] is your current "bit"
}
Within the loop, between iterations, jsonObject['sync_contact_list'][i] changes between the "bits", because i changes and points to the first element, then to the second, and so on, until the last element.
So it turns out my JSON was badly formatted. Bad habit I got from working on a Java project. Once that part was fixed, my request was getting parsed by default, which caused some other headache until I found out about node-inspector.
As a result, I'm selecting Tadeck as having the right answer.
for(count in sync_contact_list) {
console.log('individual json objects list', JSON.stringify(sync_contact_list[count]));
}

Categories

Resources