needle : node.js returning 500 on POST - javascript

I have my own rest API, that internally calls an NLP API, for which I have to post some data on their URL.
I am using needle to achieve this, but there's some error that I cannot catch, and my own api is returning 500 to the frontend.
Here is that part of my server.js code:
app.post('/api/get',function(req,res) {
//console.log(req);
console.log("here in post ");
if(!req.body){
return res.send(400);
}
//console.log(req.body.msg);
var searchQuery = req.body.msg;
var options = { 'api-key' : '3080a0e0-1111-11e5-a409-7159d0ac8188' };
needle.post('http://api.cortical.io:80/rest/text/keywords?retina_name=en_associative',searchQuery,options,function(err, resp){
if(err){
console.log('something went wrong :' + err);
}
console.log('Got :'+resp );
});
I reach here in post every time, but nothing after that. I am also curious that is this correct way to specify my api-key for the external API.
Thanks.

if you are using express 4.x, I am not sure whether you configured your express server but you need install body-parser and add the following lines in your express configuration:
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({extended: false}));
app.use(bodyParser.json());
If you are using express 3.x version, you don't need to install body-parser:
var express = require('express');
var app = express();
app.use(express.json());
app.use(express.urlencoded());
Now regarding your post route I edited it a little bit:
var config = require('./config');
app.post('/api/get', function (req, res) {
var searchQuery = {
q: req.body.msg
};
var NEEDLE_API_KEY = config.needle.API_KEY;
var NEEDLE_URL = config.needle.URL;
var options = {
'api-key': NEEDLE_API_KEY
};
needle.post(NEEDLE_URL, searchQuery, options, function (err, needleResponse) {
console.log(err || needleResponse.body);
res.json(err || needleResponse.body);
});
});
So I added a new file called config.js for purposes of having a reference for all your api keys, urls of your third party services.
module.exports = {
needle: {
API_KEY: process.env.NEEDLE_API_KEY,
URL: 'http://api.cortical.io:80/rest/text/keywords?retina_name=en_associative'
}
};
So when you run your server at the console, you should pass setting a value to your global environment variable called NEEDLE_API_KEY:
NEEDLE_API_KEY=666 node app.js
So in this way you are not saving any keys on your source code, you are saving keys in global environment variables that available only on the server machine.

Related

Node - Post request not really doing anything

I am writing a simple MEAN app, and I am currently working on the routes.
In my server.js, I have
var express = require('express');
var multer = require('multer');
var upload = multer({dest: 'uploads/'});
var sizeOf = require('image-size');
var app = express();
var mongoose = require('mongoose');
var bodyParser = require('body-parser');
var methodOverride = require('method-override');
// configuration ===========================================
require('./app/models/Purchase');
require('./app/models/Seller');
require('./app/models/User');
// config files
var db = require('./config/db');
var port = process.env.PORT || 8080; // set our port
// mongoose.connect(db.url); // connect to our mongoDB database
// get all data/stuff of the body (POST) parameters
app.use(bodyParser.json()); // parse application/json
app.use(bodyParser.json({ type: 'application/vnd.api+json' })); // parse application/vnd.api+json as json
app.use(bodyParser.urlencoded({ extended: true })); // parse application/x-www-form-urlencoded
app.use(methodOverride('X-HTTP-Method-Override')); // override with the X-HTTP-Method-Override header in the request. simulate DELETE/PUT
app.use(express.static(__dirname + '/public')); // set the static files location /public/img will be /img for users
// routes ==================================================
var routes = require('./app/routes/routes');//(app); // pass our application into our routes
var price = require('./app/routes/pricing');
var processing = require('./app/routes/processing');
var uploads = require('./app/routes/uploads');
var seller = require('./app/routes/seller');
app.use('/', routes);
app.use('/price', price);
app.use('/processing', processing);
app.use('/uploads', uploads);
app.use('/seller', seller);
// start app ===============================================
app.listen(port);
console.log('Magic happens on port ' + port);
exports = module.exports = app;
Then, in my route, I have
var express = require('express');
var mongoose = require('mongoose');
var Seller = mongoose.model('Seller');
var router = express.Router();
router.get('/', function(req,res){
res.json({message: 'youre in router.get'});
});
router.post('/registerSeller', function(req,res,next){
console.log('You made it all the way to seller route!');
res.json({message: "you did it"});
next();
});
module.exports = router;
When I start my node server, everything goes well. When I use Postman to POST to the above route, it just 'hangs' and eventually gives an error message that it cannot connect. In Postman, I select 'POST' to http://localhost:8080/seller/registerSeller.Clicking 'code', I get
POST /seller/registerSeller HTTP/1.1
Host: localhost:8080
Cache-Control: no-cache
Postman-Token: 070cb9b3-992a-ffd6-cede-c5b609bc9ce5
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW
Looking at the browser's developer tools, it shows a POST being made, and then after a while, it also reads that the POST failed.
Could anyone tell me what I'm doing wrong? Thank you.
The problem is that you are responding and then trying to call the next() function in the router stack.
router.post('/registerSeller', function(req,res,next){
console.log('You made it all the way to seller route!');
return res.send({message: "you did it"});
//next(); remove this shit.
});
This should work. Express middlewares go in order. So if you need to have a middleware to be called before this function, then you have to put it before in the stack. If you need to do something after this function, forget about the res.json... part.

can't find my json file in req.body when sending it through http post request

I have almost finished adding a new feature on my application trying to pass a json file from angular frontend to node backend via express. The original code come from How do I write a JSON object to file via Node server?. My controller part code look like:
var app = angular.module('myApp',[]);
app.controller('myCtrl',function ($scope, $http){
$scope.saveImage = function(){
var data = JSON.stringify(canvas);
debugger;
$http({
url: 'http://localhost:8080',
method: "POST",
data: data,
header: 'Content-Type: application/json'
});
}
});
I can see from developer tool that the json string "data" do have been created and has lots of things in it in my controller front end. But while I am passing it to node side, I can't get anything from req.body.
Here is my backend code:
// set up
var express = require('express');
var app = express();
var fs = require('fs');
var bodyParser = require("body-parser");
app.use(bodyParser.urlencoded({extended: false}));
var saveCount = 1;
//functions
// application -------------------------------------------------------------
app.use(express.static('./public'));
app.get('/', function (req, res) {
res.send('Hello World!');
});
app.post('/', function (req, res) {
fs.writeFile(__dirname+"/save/post"+saveCount.toString()+".json", req.body, function(err) {
if(err) {
return console.log(err);
}
res.send('The file was saved!');
});
saveCount++;
});
//listen
app.listen(8080, function () {
console.log('Example app listening on port 8080!');
});
Every time when I check my psot.json files, it only have [object Object]
I have exactly no idea what is happening here.
A few things:
You don't need to call JSON.stringify() on your data object. Just pass the object to $http as is.
You need to pass bodyParser.json() not bodyParser.urlencoded().
JSON.stringify() should be called before you try to write to your file.
Your code should look like:
var app = angular.module('myApp',[]);
app.controller('myCtrl',function ($scope, $http){
$scope.saveImage = function(){
debugger; // What does this do?
$http({
url: 'http://localhost:8080',
method: "POST",
data: canvas,
header: 'Content-Type: application/json'
});
}
});
And
// set up
var express = require('express');
var app = express();
var fs = require('fs');
var bodyParser = require("body-parser");
app.use(bodyParser.json());
var saveCount = 1;
//functions
// application -------------------------------------------------------------
app.use(express.static('./public'));
app.get('/', function (req, res) {
res.send('Hello World!');
});
app.post('/', function (req, res) {
fs.writeFile(__dirname+"/save/post"+saveCount.toString()+".json", JSON.stringify(req.body), function(err) {
if(err) {
return console.log(err);
}
res.send('The file was saved!');
});
saveCount++;
});
//listen
app.listen(8080, function () {
console.log('Example app listening on port 8080!');
});
That [object Object] means that your object is actually making it to the server and being parsed properly, that's just the representation of that object. You really don't need to stringify on the front end, however. $http will handle sending the object for you, you are just creating extra work for your application. And while bodyParser may be picking up the post data (possibly because of how you've handled it on the front end), what you really want is for bodyParser to parse it as a JSON object with the .json() method, because that's what it is.
If you don't want to go through all of that, you could keep things as you have it now and change your Content-Type to application/text or similar so that it's not parsed as an object when it gets to the server.

AngularJS SPA with Node.js and parse.com backend

I have this AngularJS SPA with ui-router which works perfectly. It uses parse.com as the backend, and I have it working on a regular Apache server.
Now I want to move it to a node.js server-app, and I want node.js to handle all the CRUDs for parse.com.
I set up a nice little node.js app to act as server, and it works.
My question is: How do I handle requests between my node.js server-app and my AngularJS SPA?
I've included my server.js file, in case anyone can use it.
// set up =====================================================================================================
var express = require('express'),
path = require('path'),
morgan = require('morgan'),
bodyParser = require('body-parser'),
methodOverride = require('method-override'),
routes = require('routes'),
keys = require('./config/keys'),
port = 80;
var app = express();
var Parse = require('parse/node').Parse;
// view engine setup ==========================================================================================
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
// configuration ==============================================================================================
app.use(require('prerender-node').set('prerenderToken', keys.prerender));
app.use(morgan('dev'));
app.use(bodyParser.urlencoded({'extended':'true'})); // parse application/x-www-form-urlencoded
app.use(bodyParser.json()); // parse application/json
app.use(bodyParser.json({ type: 'application/vnd.api+json' })); // parse application/vnd.api+json as json
app.use(methodOverride());
app.use(express.static(path.join(__dirname, 'public_html')));
Parse.initialize(keys.app, keys.js);
// routing ====================================================================================================
app.use(function(req, res) {
"use strict";
// use res.sendfile, as it streams instead of reading the file into memory. ===============================
res.sendfile(__dirname + '/public_html/index.html');
});
app.use('/', routes);
// catch 404 and forward to error handler =====================================================================
app.use(function(req, res, next) {
"use strict";
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// listen (start app with node server.js) =====================================================================
app.listen(port);
console.log("App listening on port %d", port);
File structure:
- public_html/ <-- the angularjs app -->
- node_modules/ <-- installed modules for node -->
- config/
- keys.js
- server.js
- package.json
The current setup
So, currently, I would deal with parse.com data in my (angularjs) app controller - and some of it in parse's cloud-code.
Now, I want to move all parse.com dealings to my node.js server-app, so that my angularjs "calls" the node.js server-app, which in turn "calls" parse.com for the data I need, and then return it to the angularjs app so I can update my views (with the new data from parse.com).
Example of what I want
parse.com <--> node.js server-app <--> angularjs SPA (views)
A simple thing I do in my controller is something like
var Profile = Parse.Object.extend('Profile');
var query = new Parse.Query(Profile);
query.equalTo('objectId', $stateParams.authorPermaLink);
query.find().then(function(results){
var object = results[0];
$scope.authorObj = results[0];
$scope.template.pageName = object.get('screenname');
$scope.template.pageAuthor = object.get('screenname');
$scope.template.pagePublished = object.createdAt;
$scope.template.pageLastEdit = object.updatedAt;
$scope.$apply();
}, function(error){
// error-handling
console.log("Error: " + error.code + " " + error.message);
});
Now, moving this snippet of code to node.js is simple because I can use the parse.com SDK in node.js directly. But how do I get the angularjs app to communicate with the node.js server-app?
Okay, so I managed to brain my way out of this.
The solution is to make routes that will handle http-requests from my angularjs app.
routes.js (node):
app.get('/api/article/:permalink', function(req, res) {
blog.getArticle(req.params.permalink, function(data) {
res.json(data);
});
});
// everything else
app.use(function(req, res) {
// use res.sendfile, as it streams instead of reading the file into memory.
res.sendfile('./public_html/index.html');
});
Then create a model with the blog object and methods, which are called above.
model.js (also node):
module.exports = {
getArticle : function(permalink, callback) {
"use strict";
var Article = Parse.Object.extend('Article');
var query = new Parse.Query(Article);
query.include('category');
query.include('profile');
query.equalTo('permalink', permalink);
query.find().then(function(results) {
var result = results[0];
var object = {
title: result.get('title'),
screenname: result.get('profile').get('screenname'),
profileID: result.get('profile').id,
content: result.get('content'),
publishedAt: result.get('publishedAt'),
updatedAt: result.updatedAt,
categoryName: result.get('category').get('categoryName'),
categoryPermaLink: result.get('category').get('categoryPermaLink'),
articleID: result.id
};
callback(object);
}, function(error) {
callback({error: error});
});
}
};
And then finally in mu angularjs app, simply make a http-request (get in this example but the other rest verbs all work as well).
controller.js (angularjs):
$http.get('/api/article/' + $stateParams.articlePermaLink
).then(function successCallback(response) {
response = response.data;
$scope.articleTitle = response.title;
$scope.template.pageName = response.title;
$scope.articleAuthor = response.screenname;
$scope.template.pageAuthor = response.screenname;
$scope.profilePermaLink = response.profileID;
$scope.articleContent = response.content;
$scope.publishDate = response.publishedAt;
$scope.template.pagePublished = response.publishedAt;
$scope.template.pageLastEdit = response.updatedAt;
$scope.category = response.categoryName;
$scope.categoryPermaLink = response.categoryPermaLink;
$scope.currentArticle = response.articleID;
console.log(response.commentObj);
}, function errorCallback(response) {
console.log("Error: " + response.code + " " + response.message);
});
The callbacks are the magic!

Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present in angular js

I have used nga admin using node js I'm new to angular js and node js. I have created rest api on localhost using mysql node js and i have check it by using postman and its working fine. But when I parse this api url it's gives me this below error. See I want to create admin panel for users to edit delete and update just need to implement basic thing.But its' showing me 404 error HEADERS ERROR.
XMLHttpRequest cannot load http://localhost:3000/api/user?_page=1&_perPage=30&_sortDir=DESC&_sortField=id. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost' is therefore not allowed access. Server.js file contain this below code.
server.js file
var express = require('express'),
path = require('path'),
bodyParser = require('body-parser'),
app = express(),
expressValidator = require('express-validator');
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json({ type: 'application/vnd.api+json' }));
app.use(bodyParser.json());
var connection = require('express-myconnection'),
mysql = require('mysql');
app.use(
connection(mysql,{
host : 'localhost',
user : 'root',
password : '',
database : 'gkv',
debug : true //set true if you wanna see debug logger
},'request')
);
app.get('/',function(req,res){
res.send('Welcome');
});
var router = express.Router();
router.use(function(req, res, next) {
console.log(req.method, req.url);
console.log(res.headers);
next();
});
var curut = router.route('/user');
curut.get(function(req,res,next){
res.header("Access-Control-Allow-Headers","Content-Type");
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Methods", "GET, PUT, POST,OPTIONS");
req.getConnection(function(err,conn){
if (err) return next("Cannot Connect");
var query = conn.query('SELECT * FROM users',function(err,rows){
if(err){
console.log(err);
return next("Mysql error, check your query");
}
res.json({message: 'All users!',data: rows });
//res.render('user',{title:"RESTful Crud Example",data:rows});
});
});
});
app.use('/api', router);
var server = app.listen(3000,function(){
console.log("Listening to port %s",server.address().port);
});
admin.js file
var myApp = angular.module('myApp', ['ng-admin']);
myApp.config(function($httpProvider) {
//Enable cross domain calls
$httpProvider.defaults.useXDomain = true;
//Remove the header containing XMLHttpRequest used to identify ajax call
//that would prevent CORS from working
delete $httpProvider.defaults.headers.common['X-Requested-With'];
$httpProvider.defaults.headers.common["Access-Control-Allow-Origin"] = "*";
$httpProvider.defaults.headers.common["Accept"] = "application/json";
$httpProvider.defaults.headers.common["content-type"] = "application/json";
});
myApp.config(['NgAdminConfigurationProvider', function (nga) {
// create an admin application
var admin = nga.application('My First Admin')
.baseApiUrl('http://localhost:3000/api/'); // main API endpoint
// create a user entity
// the API endpoint for this entity will be 'http://jsonplaceholder.typicode.com/users/:id
var user = nga.entity('user');
// set the fields of the user entity list view
user.listView().fields([
nga.field('Nachname').isDetailLink(true),
nga.field('Anrede'),
nga.field('Emailadresse'),
nga.field('Telefonummer'),
nga.field('Date&Time'),
nga.field('URL'),
nga.field('UserIP'),
]);
user.creationView().fields([
nga.field('Nachname'),
nga.field('Anrede'),
nga.field('Emailadresse'),
nga.field('Telefonummer'),
nga.field('Date'),
nga.field('URL'),
nga.field('UserIP')
]);
//user.editionView().fields(user.creationView().fields());
admin.addEntity(user);
/*var post=nga.entity('posts');
post.listView().fields([
nga.field('id'),
nga.field('title'),
nga.field('userId','reference').targetEntity(user).targetField(nga.field('username')).label('User'),
nga.field('comments','referenced_list').targetEntity(nga.entity('comments')).targetReferenceField('postId').targetFields([nga.field('email'),nga.field('name')]).sortField('id').sortDir('DESC')
]);*/
// add the user entity to the admin application
//admin.addEntity(post);
// attach the admin application to the DOM and execute it
nga.configure(admin);
}]);
I resolved my issue by adding the following to my "app.js" file, works like a charm.
var app = express()
, cors = require('cors')
, app = express();
app.use(cors());
This above query has been resolved as I have used core package npm and installed it using node js cmd and added below code in server.js file
cors = require('cors');
// use it before all route definitions
app.use(cors({origin: 'http://localhost'}));

Simple way of client-server communication in NodeJS

I found a very useful code snippet on GitHub that can provide simple server-client communication in NodeJS.
After some minor formatting, my code looks like this:
The client (Jade + Javascript)
head
title jsonp test
script(src='http://code.jquery.com/jquery-1.6.2.min.js')
script(type='text/javascript').
$(function () {
$('#select_link').click(function (e) {
e.preventDefault();
console.log('select_link clicked');
var data = {};
data.title = "title";
data.message = "message";
$.ajax({
type: 'POST',
data: JSON.stringify(data),
contentType: 'application/json',
url: 'http://localhost:7776/domaintest',
success: function (data) {
console.log('success');
console.log(JSON.stringify(data));
}
});
});
});
body
#select_div
a#select_link(href='#') Test
The server (Javascript)
var express = require('express');
var app = express.createServer();
app.use(express.bodyParser());
app.post('/domaintest', function(req, res){
var obj = {};
console.log('body: ' + JSON.stringify(req.body));
res.send(req.body);
});
app.listen(7776);
Route defined to the client (I was told it's unnecessary for the server as app.post serves the purpose)
var express = require('express');
var router = express.Router();
router.get('/', function(req, res, next) {
res.render('index');
});
module.exports = router;
The result is a simple text reading "Test" that can be clickable. When I click, the actual events should happen as far as I read it out from the code, but insted browser says POST http://localhost:7776/domaintest 404 (Not Found) in jquery-1.6.2.min.js:18. To be very precise, the error occures in $.ajax, according to the debugger.
Since the jQuery code is practically unreadable because of the formatting (not judging, it might have its reason), I need your help. What's the possible source of the error? Did I forget mentioning something?
Change your server.js file to this. I havent tested the code but this should work.
var express = require('express');
var app = express.createServer();
var router = express.Router();
app.use(express.bodyParser());
router.post('/domaintest', function(req, res, next) {
var obj = {};
console.log('body: ' + JSON.stringify(req.body));
res.send(req.body);
});
app.listen(7776);
You can read this for more information http://adrianmejia.com/blog/2014/10/01/creating-a-restful-api-tutorial-with-nodejs-and-mongodb/
I think this is because your calling body-parser incorrectly. Body parser isn't part of express so you can't do express.bodyParser.
You need to include it like so:
var bodyParser = require('body-parser);
app.use(bodyParser.urlencoded({ extended: false }))
After some research and outside help, I've found the solution.
For domaintest, there was a route defined, which is almost identical to the one I defined for the client. Well, to the domaintest route, I had to add the next function call, right after router.get:
router.post('/', function(req, res) {
res.setHeader('Content-Type', 'application/json');
res.send(JSON.stringify({data: 'asd'}));
});
The so-called server code above is practically unused and unnecessary; domaintest serves as a server.

Categories

Resources