I'm currently developing game app. I have started with authorization via FB and now i got stuck on connecting front-end angular with back-end node.
My folder contains 2 subfolders without any connections or dependencies between them: client and server.
Client contains scaffolded yeoman application based on angular generator so that my front end is fired with grunt serve. I'm using here angular-socket-io by btford.
Server contains nothing but basic server allowing to connect and loggs to console when someone will connect via socket.io.
My problem lies on client folder, front-end part, where:
angular.module('battleshipsApp')
.factory('socket', function (socketFactory) {
var myIoSocket = io.connect('http://localhost:5432');
var mySocket = socketFactory({
ioSocket: myIoSocket
});
return mySocket;
});
doesn't work.
I think i linked everything i needed:
src="bower_components/angular-socket-io/socket.js"
<!-- endbower -->
<!-- endbuild -->
src="bower_components/angular-socket-io/mock/socket-io.js"
Here my simple server:
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
app.get('/', function(req, res){
res.sendFile(__dirname + '/index.html');
});
io.sockets.on('connection', function(socket){
var logIn = new Date();
console.log(logIn + ' user connected')
socket.on('disconnect', function() {
var logOut = new Date();
console.log(logOut + ' bye bye')
})
});
http.listen(5432, function(){
console.log('listening on localhost:5432');
});
And I can't figure out why these two cannot connect.
I couldn't find any answers which could fit my problem in google.
I'm looking right now on both terminals, one with grunt serve in action and one with nodemon server.js and no errors, no connections.
Also there are no errors on dev tools console in chrome on front-end side.
Any help? Or maybe approach for this app with my structure is bad?
I guess you need to add to your server :
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
Related
I am trying to setup a base for a MEAN application. I created the new project using Angular CLI, added Express.js, MongoDB modules to the application. In the app.js file I have the following configuration:
var express = require('express');
var bodyParser = require('body-parser');
var session = require('express-session');
var path = require("path")
var app = express();
var conf = require('./config/conf');
var server = require('http').Server(app);
var mongoDB = require('./adapters/mongodb')
var mongoClient = new mongoDB(conf);
app.use(bodyParser());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, 'dist/index.html'));
});
app.use(function (req, res, next) {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type,__setXHR_');
res.setHeader('Access-Control-Allow-Credentials', true);
next();
});
mongoClient.connect(function (dbconn) {
app.dbconn = dbconn;
app.conf = conf;
console.log("************************************************************");
console.log(new Date() + ' | CRUD Server Listening on ' + conf['web']['port']);
console.log("************************************************************");
server.listen(conf['web']['port']);
var Routes = require('./routes/http-routes');
new Routes(app);
});
I setup a hello world route for now and no changes done to the angular sources, which means I would land at the Angular default starting page. But I cant land at the page but instead a white screen page. However, I can access the routes using Postman. I do ng build and then node app.js to run the application. What am I doing wrong?
You should use the Express way to handle routes
First
const router=express.Router();
Then let's suppose you have a file using only authentication routes
const authentication = require('./routes/authentication')(router);
To conclude, you only have to do :
app.use('/authentication', authentication);
This allows a better divison of your routes
You 'll use your routes this way
module.exports= (router)=>{
router.get('/',(req,res)=>{
res.json(message:'Hello World');
});
return router;
To set angular routes you need the router module, for more details read the documentation
You serve only index.html from your Angular App. But you need also serve assets, css and javascript. Easiest would be something like this (but you need to adjust directory names:
app.use('/js', express.static(path.resolve(__dirname, 'dist/js')));
app.use('/css', express.static(path.resolve(__dirname, 'dist/css')));
app.use('/assets', express.static(path.resolve(__dirname, 'dist/assets')));
I'm having a difficult time posting data retrieved from a server using mysql with node. I have connected to my db successfully, and I can return the data I want by console logging it to the CLI when running "node server.js". However, I'm not sure how to post this data to my Angular view. No problem console logging, but this doesn't help me get data to the application.
For the moment, I'm just trying to get the data to index.html, which is my primary view and holds my ng-view portion for Angular routing. I'm probably missing something obvious bc I'm new to NodeJS.
// MODULES
var express = require('express');
var app = express();
var port = process.env.PORT || 3000;
var mysql = require('mysql');
var serveStatic = require('serve-static');
var bodyParser = require('body-parser');
var source = __dirname + '/public/views/index.html';
app.use(serveStatic(__dirname, {'index': ['index.html']}));
app.route('/*')
.get(function(req, res) {
res.sendFile(source);
});
var data;
var connection = mysql.createConnection({
host : 'thehostdb',
user : 'username', // credentials correct, connection works
password : 'pw',
database : 'db',
port: '3306'
});
connection.query('SELECT * from poemTable', function(err, rows, fields) {
if (!err) {
data = JSON.stringify(rows);
setDataValue(data);
}
else {
console.log('Error while performing Query:', err);
}
});
function setDataValue(value) {
data = value;
console.log(data); //Where the data logs
}
app.listen(port, function () {
console.log('Example app listening on port' + port + '!')
})
You have to understand what this code does, and how nodejs and angular are supposed to work together. Angular is served to the client and then rendered by the clients browser. So if you want to inject data you have to fetch it. So in your angular app when the controller starts make an api call, and in your server create a new route:
app.get('/data', function(req, res, next) {
connection.query(..., function(err, rows, fields) {
res.json(rows);
});
});
Make sure you understand node and it's async nature, what is event loop and how it works and what is callback hell, also I would check out promises and other tutorials on nodeschool.io, it's a great place to start with node :)
I am very new to express (and backend), and I am learning. So I mounted an express server on my machine by running express and npm install, and then overwriting the app.js with a simple code that serves something on /test
var express = require('express')
var app = express()
app.all('/*', function(req, res, next) {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Headers', 'Content-Type,X-Requested-With');
next();
});
app.get('/test', function (req, res) {
res.send('hi???');
});
app.listen(3100);
On my frontend, I am working with angular, it is running on localhost:3000, but when I run
function TestController ($http) {
var vm = this;
$http.get('http://localhost:3100/test')
.then(function (response) {
console.log(response);
});
}
It throws the following error:
XMLHttpRequest cannot load http://localhost:3100/test. Request header field Pragma is not allowed by Access-Control-Allow-Headers in preflight response.
I thought it could be a problem on the backend, but when I run
function TestController ($http) {
var vm = this;
var httpRequest = new XMLHttpRequest();
httpRequest.open('GET', 'http://localhost:3100/test', true);
httpRequest.send(null);
}
It won't throw any error, so I guess it is a problem with my angular configuration, but I cannot figure out where or what the problem is... how can I fix this? any help tweaking the backend or the frontend to fix this will be really helpful!
I already tried this, but it won't work, AngularJS POST Fails: Response for preflight has invalid HTTP status code 404 it doesn't makes any difference :(
Given the description of the problem, it was not about CORS, it had to do with headers not being handled correctly by the backend. Running the app on firefox, firebug suggests to add the token pragma to Access-Control-Allow-Headers... and then, another unkown header would jump up, now called cache-control so I only had to modify the app.js.
For anyone having this same problem, you just need to add the problematic headers to the string on 'Access-Control-Allow-Headers' :)
app.all('/*', function(req, res, next) {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Headers',
'Content-Type,X-Requested-With,cache-control,pragma'
+ otherHeadersSeparatedByComma);
next();
});
im having a little problem with my M.E.A.N(mongo, express, angular, node) application, when i do a GET request from my node server, it displays on 10 items instead of all 21 that are in the mongo db. i did some search on google and i read stuff saying it had to do with my CORS set up on my servers side, but i still cant seem to figure it out... here's my code:
index.js
var express = require('express');
var mongoose = require('mongoose');
var bodyParser = require('body-parser');
var methodOverride = require('method-override');
var _ = require('lodash');
var cors = require('cors');
// Create the application.
var app = express();
//enable the use of cors
app.use(cors());
// Add Middleware necessary for REST API's
app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.json());
app.use(methodOverride('X-HTTP-Method-Override'));
// CORS Support
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
res.header('Access-Control-Allow-Headers', 'Content-Type');
next();
});
app.models = require('./models/index');
// Load the routes.
var routes = require('./routes');
_.each(routes, function(controller, route) {
app.use(route, controller(app, route));
});
// Connect to MongoDB
var db = mongoose.connect('mongodb://localhost/isdbmeanapp');
mongoose.connection.on('error', console.error.bind(console, 'connection error:'));
mongoose.connection.once('open', function() {
// Load the models.
app.models = require('./models/index');
app.listen(3000);
console.log('Server running on localhost port 3000...');
});
i currently have 21 users(dummy data) in my database(mongodb) but when i run the above restangular query, it displays only 10 users. i also tried making requests with postman and thesame thing happens (with a 206 server status code).
im using restangular to make my requests:
Restangular.all('user').getList().then(function(user){
$scope.users = user;
});
please i need help in solving this problem... thanks in advance...
I have written webservice using NodeJS and Express. Service is running on port 8090. Also I wrote frontend in AngularJS and running on port 8080.
Mongo has username and password stored of all users
When I login via HTML5/AngularJS frontend, the AngularJS app in turn calls the http post request of express. User is authenticated. And I set req.session.email = the email address of the user.
I even am able to return and check in console log of AngularJS that req.session.email was set correct in express
The problem is that I created an authentication function called "restrict" in Express to act as middleware function to give access to other get/post requests only if req.session.email is not undefined.
But even after session has been set, when this other get/post request of Express are calling by AngularJS app, this "restrict" function blocks the calls because it receives req.session.email as undefined
Both AngularJS and Express are on the same machine. But I don't think this is the problem.
Express Code Snippet
var url = 'mongodb://127.0.0.1:5555/contacts?maxPoolSize=2';
var mongojs = require('mongojs');
var db = mongojs(url,['data']);
var dbauth = mongojs(url,['users']);
// var request = require('request');
var http = require('http');
var express = require('express');
var cookieparser = require('cookie-parser');
var app = express();
var bodyParser = require('body-parser');
var session = require('express-session');
app.use(cookieparser());
app.use(session({secret:'v3ryc0mpl!c#t3dk3y', resave: false, saveUninitialized: true}));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
var user_session;
app.all('*',function(req, res, next){
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'PUT, GET, POST, DELETE, OPTIONS');
res.header('Access-Control-Allow-Headers', 'Content-Type');
next();
});
function restrict(req,res,next){
try{
if(req.session.email){
next();
}
else{
res.send('failed');
res.end();
}
}
catch(err){
res.send('failed');
res.end();
}
};
app.post('/login',function(req,res){
//removed DB function from here to make the code look simple
req.session.email = req.body.email;
req.session.password = req.body.password;
});
app.get('/loggedin',restrict,function(req,res){
res.send(true);
});
AngularJS Function that calls the Express function to check session status
var resolveFactory = function ($q, $http, $location,LoginDetails) {
var deferred = $q.defer();
$http.get("http://127.0.0.1:8090/loggedin")
.success(function (response) {
if(response == true){
deferred.resolve(true);
}
else
{
deferred.reject();
LoginDetails.setemail('');
LoginDetails.setpassword('');
$location.path("/");
}
})
.error(function (err) {
deferred.reject();
$location.path("/");
});
return deferred.promise;
};
Fundamentally the AngularJS Resolve Function that I created should be successful but it is not. It is failing. Am using live-server to run HTML/AngularJS on my laptop and nodemon to run Express app
Ok! So the reason is that AngularJS is running on a different port 8080
Express was running on port 8090. This means that if AngularJS calls an API of Express, the session of Express would be lost unless Express allows session to be passed on to AngularJS and AngularJS calls the API of Express with {withCredentials: true} parameter set. Below are the changes that I had to make to get the session maintained when AngularJS and ExpressJS were running on different ports
In AngularJS makes sure any API you call of Express, it should have
{withCredentials: true} like this
$http.get('http://expressdomainname:expressport/api',{withCredentials: true})
like wise in case you use $http.post
the parameter {withCredentials: true} is important
Now on the Express side
make sure you have app setting like this
app.all('*',function(req, res, next){
//Origin is the HTML/AngularJS domain from where the ExpressJS API would be called
res.header('Access-Control-Allow-Origin', 'http://localhost:8080');
res.header('Access-Control-Allow-Methods', 'PUT, GET, POST, DELETE, OPTIONS');
res.header('Access-Control-Allow-Headers', 'Content-Type');
//make sure you set this parameter and make it true so that AngularJS and Express are able to exchange session values between each other
res.header("Access-Control-Allow-Credentials", "true");
next();
});
Please feel free to ask me question in case you have about this topic. I spent days to resolve this.