This is my controller for the time being
.controller('HotelsController', ['$http', HotelsController]);
function HotelsController($http) {
var vm = this;
$http({
method: 'GET',
url: '/api/hotels'
}).then(function successCallback(response) {
console.log(response);
}, function errorCallback(response) {
console.log(response);
});
}
but I get an error message
CAN'T GET /api/hotels
and this is my api
module.exports.hotelsGetAll = function (req, res) {
Hotel
.find()
.skip(offset)
.limit(count)
.exec(function (err, hotels) {
if (err) {
res
.status(500)
.json(err);
} else {
console.log("Found Hotels ", hotels.length);
res
.json(hotels);
}
})
};
any suggestions please?
You should append your api host url before performing http request.
Edit your controller:
.controller('HotelsController', ['$http', HotelsController]);
function HotelsController($http) {
var vm = this;
$http({
method: 'GET',
url: 'http://yourhostapiurl/api/hotels' //Append the url of your api
}).then(function successCallback(response) {
console.log(response);
}, function errorCallback(response) {
console.log(response);
});
}
Thank you for helping me!
In addition I added these lines of codes in my server(app.js) file
app.all("/api/*", function (req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Cache-Control, Pragma, Origin, Authorization, Content-Type, X-Requested-With");
res.header("Access-Control-Allow-Methods", "GET, PUT, POST");
return next();
});
Related
I wrote backend API on Node.js and Express.js v4, this part (index.js):
app.use(function (req, res, next) {
res.setHeader('Access-Control-Allow-Origin', 'http://example.com');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
res.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
res.setHeader('Access-Control-Allow-Credentials', true);
next();
});
app.post('/add1', function (req, res) {
db.one("INSERT INTO table(value1) VALUES (${value1}) RETURNING ID", req.query).then(function (data) {
res.json(data);
}).catch(function (error) {
res.json(error);
});
});
app.put('/add2', function (req, res) {
db.one("INSERT INTO table(value1) VALUES (${value1}) RETURNING ID", req.query).then(function (data) {
res.json(data);
}).catch(function (error) {
res.json(error);
});
});
app.get('/add3', function (req, res) {
db.one("INSERT INTO table(value1) VALUES (${value1}) RETURNING ID", req.query).then(function (data) {
res.json(data);
}).catch(function (error) {
res.json(error);
});
});
And I have Angular JS or sample ajax like this
app.controller('globalController', function($scope, $http) {
var jsd = {};
jsd.value1=1;
$http.put(API_URL + 'add2', jsd).then(function(data) {
console.log(data);
}, function(data) {
console.log(data);
});
});
and
$.ajax({
url: API_URL + 'add1',
method: 'POST',
dataType: 'json',
data: jsond,
success: function(data) {
console.log(data);
},
error: function(data) {
console.log(data);
}
});
But I don't recive any data to my req.query and in generally in req object. When I make my AJAX request to add3 with get, then all works, req.query has my params.
I read about this solution:
app.config(function ($httpProvider) {
$httpProvider.defaults.transformRequest = function(data){
if (data === undefined) {
return data;
}
return $.param(data);
};
$httpProvider.defaults.headers.put['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8';
});
and solution here
var multer = require("multer");
//...
var upload = multer({ dest: "./upload/" });
app.post("/post", upload.array(), function(req, res) {
console.log(req.body);
res.send(null);
}
I tried first, not works, and second is too strange solution (I can't save data to files and etc.) I think problem was in fist OPTION request, but I googled it, not found solution. I need little example (working code) how I can send POST or PUT data from Angular $http or AJAX and use this data in req object in node.js. In GET requests all this works, but how I can make it work on others?
Which version of Express are you using? It's possible that you're writing the old way and using the new version.
You might wanna check this out -- How to retrieve POST query parameters?
Anyway, I'd suggest you use ngResource for making REST HTTP calls in Angular.
Instantiate the Factory
This will expose a few methods e.g query, save etc.
angular
.module('MyModule')
.factory('AddEndpoint', AddEndpoint);
AddEndpoint.$inject = ['$resource'];
function AddEndpoint($resource) {
return $resource(API_URL + '/:param', { param: '#param' });
}
Enjoy The Factory
angular
.module('MyModule')
.controller('MyController', MyCtrl)
MyCtrl.$inject = ['AddEndpoint'];
function MyCtrl(AddEndpoint) {
var scope = this;
scope.getFromApi = AddEndpoint.get({ params: 'add1' }); // GET 'API_URL/add1'
scope.postToApi = postToApi;
function postToApi(data) {
data.params: 'add2'
AddEndpoint.save(data); // POST to 'API_URL/add2'
}
}
I want to post data from Angular and save it in MongoDB through Express and Mongoose.
myConfig file
'use strict';
var express = require('express');
var parser = require('body-parser');
var router = require('./api');
var app = express();
require('./database');
app.use('/', express.static('public'));
app.use(parser.urlencoded({extended: true}));
app.use(parser.json());
app.use('/api', router);
app.listen(3000, function () {
console.log("Evalyst is running on port 3000");
});
myController
$scope.addNewEvaluation = function (newEvaluation) {
dataService.addNewEvaluation(newEvaluation);
$scope.closeModal();
};
MyService
$http({
method: 'POST',
url: 'http://localhost:3000/api/evaluations',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
data: {'evaluation': newEvaluation}
}).success(function (data) {
console.log(data);
}).error(function(data){
console.log(data);
});
};
My backend (node.js, express, mongoose)
router.post('/evaluations', function (req, res) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Cache-Control, Pragma, Origin, Authorization, Content-Type, X-Requested-With");
res.header("Access-Control-Allow-Methods", "GET, PUT, POST");
var evaluation = req.body;
console.log(evaluation);
Evaluation.create(evaluation, function (err, evaluation) {
if (err) {
return res.status(500).json({message: err.message});
}
res.json({evaluation, message: "Evaluation created"});
});
});
The problem is that an empty object is saved in my MongoDB.
In my req.body, I have the following line:
body: { '{"evaluation":{"title":"Sports","description":"Just do it","notifFreq":"daily"}}': '' },
I don't understand why I get the evaluation wrapped in {' }' : ''}.
Try to send it like this
$http({
method: 'POST',
url: 'http://localhost:3000/api/evaluations',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
data: newEvaluation
}).success(function (data) {
console.log(data);
}).error(function(data){
console.log(data);
});
because your newEvaluation is already an object.
Your newEvaluation data is a string.
'{"evaluation":{"title":"Sports","description":"Just do it","notifFreq":"daily"}}': ''
Please send javascript object to backend. Split your string first by ":" character and then parse json string to json object.
$scope.addNewEvaluation = function (newEvaluation) {
var splitStr = newEvaluation.split(":")[0],
newEvaluationObj = JSON.parse(splitStr);
dataService.addNewEvaluation(splitStr);
$scope.closeModal();
};
I am trying to use Angular's POST and PUT methods but I keep getting the error:
Response for preflight has invalid HTTP status code 404
My code:
$http({
method: "POST",
url: "http://localhost:4567/api/v1/project",
data: project_data
}).then(function successCallback(response) {
console.log(response);
}),
function errorCallback(response) {
console.log('error!');
console.log(response);
}
$http({
method: "PUT",
url: "http://localhost:4567/api/v1/project/1",
data: data
}).then(function successCallback(response) {
console.log(response);
}),
function errorCallback(response) {
console.log('error!');
console.log(response);
}
Does anyone know what might be going on or how to fix it? Other solutions I've found involve changes to the server side code (in this instance, I don't have access to the server). Thanks in advance!
If you use Node.js, just do this:
app.options('/api/v1/project/1', function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Content-Type, Content-Length, Authorization, Accept,X-Requested-With");
res.header("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS");
res.header("Content-Type", "application/json;charset=utf-8");
res.status(204);//important
res.end()
});
app.put('/api/v1/project/1', function(req, res, next) {
...your normal code here
})
I want to get access token for authentication. My post result like
POST https://staj-io-goldenilkay92-1.c9.io/api/v1/oauth/token 401 (Unauthorized)
but when I try to post with postman it works.
Server Side Headers
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'POST, GET, PUT, DELETE, OPTIONS');
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type, Authorization');
res.setHeader('Access-Control-Allow-Credentials', 'true');
res.header('Content-Type', 'application/json');
Angular Code
Service
function signIn(data) {
var deferred = $q.defer();
$http.post('https://staj-io-goldenilkay92-1.c9.io/api/v1/oauth/token', data,
{headers: {'Content-Type': 'application/x-www-form-urlencoded'}}
)
.success(function (response, status, headers, config) {
deferred.resolve(response);
}).error(function () {
deferred.reject("Failed to login");
});
return deferred.promise;
}
controller
vm.loginData = {
'client_id': 'client',
'client_secret': 'client',
'grant_type': 'password',
'username': '',
'password': ''
};
vm.login = function login() {
loginService.signIn(vm.loginData).then(function (result) {
vm.signInResult = result;
},
function (data) {
});
}
POST https://staj-io-goldenilkay92-1.c9.io/api/v1/oauth/token 401 (Unauthorized)
Here is suggestions to solve your problem;
Use cors module (not required);
Server Side
I assume that your passport code working properly.
var cors= require('cors');
//init first.
app.options(cors({origin'*'})); //Use your origins.
app.use(cors({origin'*'})); //Use your origins.
Client Side
Just delete headers options
//...
$http.post('https://staj-io-goldenilkay92-1.c9.io/api/v1/oauth/token', data)
.success(function (response, status, headers, config) {
deferred.resolve(response);
}).error(function () {
deferred.reject("Failed to login");
});
//...
If one POST works and the other doesn't, then your angularjs $http request is making the request with the wrong parameters.
I'd suggest you to get an http analyser (like Fiddler) and compare the actual request done by Postman vs the request done by you angular app.
I have the following code:
app.js:
var passport = require('passport')
, FacebookStrategy = require('passport-facebook').Strategy
, ...
passport.serializeUser(function(user, done) {
console.log('serializing user')
done(null, user);
})
passport.deserializeUser(function(obj, done) {
console.log('deserializeUser')
done(null, obj)
})
passport.use(new FacebookStrategy({
clientID: FBAPP.id,
clientSecret: FBAPP.secret,
callbackURL:
"http://www.mylocal.com:3000/auth/facebook/callback"
},
function(accessToken, refreshToken, profile, done) {
// asynchronous verification, for effect...
process.nextTick(function () {
return done(null, profile)
})
}
))
app.get('/auth/facebook', passport.authenticate('facebook',
{ scope: ['email, user_likes, user_photos, publish_actions'] }))
app.get('/auth/facebook/callback',
passport.authenticate('facebook', {
successRedirect: '/loginsuccess', failureRedirect : '/loginfail' }))
app.get('loginsuccess', function(req, res) {
console.log('Login success')
res.send(200, 'ok')
})
app.get('/loginfail', function(req, res) {
console.log('Login error')
res.send(401, 'error')
})
The angular part:
factory('FacebookFactory', ['$http', '$q', function($http, $q) {
var get = function() {
var deferred = $q.defer();
$http({method: 'GET', url: '/auth/facebook'}).
success(function(data, status, headers, config) {
deferred.resolve(data);
}).
error(function(data, status, headers, config) {
deferred.reject(data);
});
return deferred.promise;
};
return {
get: get
};
}])
I get always this error and did several attempts but no success.
XMLHttpRequest cannot load https://www.facebook.com/dialog/oauth?
response_type=code&redirect_uri=http%…
user_likes%2C%20user_photos%2C%20publish_actions&client_id=xxxxxxxxxxx.
No 'Access-Control-Allow-Origin' header
is present on the requested resource. Origin '[basic
links]http://www.mylocal.com:3000' is therefore
not allowed access.
Anyone any idea? I did try it solely in angular but then it does not work in Safari but in Chrome and FF it works perfectly.
www.mylocal.com:3000 = localhost:3000
You will not find a solution with client side languages as this constitutes a cross-origin request which could be used as a malicious attack. So basically the Facebook endpoint would need to have a Access-Control-Allow-Origin header block set and I don't think they will do that anytime soon. I use APIs alot and frequently have to have theses headers set in my endpoint so my clients can connect from localhost or dev urls:
if (isset($_SERVER['HTTP_ORIGIN'])):
header("Access-Control-Allow-Origin: {$_SERVER['HTTP_ORIGIN']}");
header('Access-Control-Allow-Credentials: true');
header('Access-Control-Max-Age: 86400');
endif;
if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS'):
if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD'])):
header('Access-Control-Allow-Methods: GET, POST, OPTIONS, DELETE, PUT');
endif;
if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS'])):
header("Access-Control-Allow-Headers: {$_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']}");
endif;
exit(0);
endif;
You could also try this in your $http broker:
var promise = $http({
method: 'POST',
url: 'url_to_api',
data: params,
headers: {
'Access-Control-Allow-Origin': true,
'Content-Type': 'application/json'
}
}).success(function (data, status, headers, config) {
return data;
});
I have an Angular app with express on the backend. When I clicked on a button with this HTML:
<input type="button" ng-click="socialLogIn('facebook')" class="modal-input" value="Sign in with Facebook">
It gave me a CORS error:
$scope.socialLogIn = function (social) {
return $http.get ('/auth/'+social).success (function (data) {
auth.saveToken (data.token); // write data to local storage
});
Problem is, I wanted to get the token back so I could save it in localStorage. I did solve it, but the solution is round-about. In the socialLogIn function, I opened a new window:
$scope.socialLogIn = function (social) {
var url = 'http://' + $window.location.host + '/auth/' + social;
$window.open(url);
};
In the express backend, after I got my 'stuff' from Facebook or Google and I created the token, I sent back some code that saved the token, reloaded the parent window and closed itself:
function loginReturn (res, token) {
var returnString = '' +
'<!DOCTYPE html>\n' +
'<html>\n' +
'<head>\n' +
'<meta charset="UTF-8">\n' +
'<title>Login</title>\n' +
'</head>\n' +
'<body>\n' +
'<script type="text/javascript">\n' +
'window.localStorage[\'token\'] = \''+token+'\';\n' +
'window.opener.location.reload(false);\n' +
'window.close();\n' +
'</script>\n' +
'</body>\n' +
'</html>';
res.send(returnString);
};