0

With NodeJs I have set up an API which works (I can see the JSON result in my Browser). In Angular I have a socket.io chat which runs via http on port 3030. I am also running an apache server (with xampp) which serves the AngularJs frontend.

As soon as I want to make a request from Angularjs to the Nodejs API I get the following error in the browsers console

XMLHttpRequest cannot load localhost:3030/api/feed. Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https.

From what I understood after googling is that Angular can't communicate with the API as long as I dont have an HTTP server running in NodeJS. But can I run the socket.io server and the HTTP server for the api in the same process?

server.js

var express = require('express');
var app = express();
var http    = require('http').Server(app);
var io = require('socket.io')(http);

var routes  =   require('./app/api/routes');
app.use('/api', routes);

var chatMembers = {};


io.on('connection', function(socket){

	socket.on("new-message", function(msg){
		console.log(msg);
		var username = msg[username];
		var message = msg[message];
		io.emit("receive-message", msg);
	})

	socket.on("new-connection", function(username){
		chatMembers[socket.id] = username;
		console.log(chatMembers);

		io.emit("online-list", createOnlineList());
	})

	socket.on("disconnect", function(){
		if(chatMembers[socket.id] != undefined){
			console.log(" " + chatMembers[socket.id] + " hat die Verbindung getrennt.");
			delete chatMembers[socket.id];
			io.emit("online-list", createOnlineList());
		}
	})
});


function createOnlineList(){
	//returns list of every member connected to the socket (only name)
  	var onlinelist = [];
	for(var index in chatMembers){
		onlinelist.push(chatMembers[index]);
	}
	return onlinelist;
}


http.listen('3030', function(){
  console.log("Server online");
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

controller.js

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
angular.module('coursemate')
    .controller("chatCtrl", ['$rootScope','$scope', '$http', function($rootScope, $scope, $http){
		var vm = this;
		var socket = window.io('localhost:3030/');
		vm.newMessage = undefined;
		vm.username = undefined;
		vm.messages = [];
		vm.onlinelist = [];
		vm.sendBtnDisabled = true;
		vm.connected = false;


		//socket acions
		socket.on("receive-message", function(msg){
			//socket server send message to us
			$scope.$apply(function(){
			  vm.messages.push(msg);
			});
		});

		socket.on("online-list", function(list){
			//server sends us refreshed list of members
			$scope.$apply(function(){
			  vm.onlinelist = list;
			});
		});

		socket.on('disconnect', function(){
			//connection failed
			vm.connected = false;
			vm.keyEventSendMessage(null);
		});

		socket.on('connect', function(){
			//connection established
			vm.connected = true;
			vm.keyEventSendMessage(null);
		});
		vm.username = undefined;



		vm.sendMessage = function(){
			//we send messsage to socket server
			var newMessage = {
				username: vm.username,
				message: vm.newMessage
			};
			socket.emit("new-message", newMessage);

			var config = {
                headers : {
                    'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8;'
                }
            }
            var data = $.param({
                user: vm.username,
                content: vm.newMessage
            });
			$http.post('app/database/database.php?req=1', data, config).success(function(data) {
	       	});

	        vm.newMessage = undefined;
	        vm.keyEventSendMessage(null);
		};

		vm.createUser = function(username){
			// we "log in" as users
			vm.username = username;
			socket.emit("new-connection", username);
		}
 		vm.keyEventSendMessage = function(event){
 			//fired on keyhit at message input
 			if(typeof(vm.newMessage) != 'undefined' && vm.newMessage != null && vm.newMessage != '' && vm.connected){
 				vm.sendBtnDisabled = false;
 				if(event != null && event.keyCode == 13){
 					vm.sendMessage();
 				}
 			}else{
 				vm.sendBtnDisabled = true;
 			}
 		}

		$http.get('localhost:3030/api/feed').success(function(data) {
			console.log(data);
		});

    }]);

5
  • Possible duplicate of XMLHttpRequest cannot load https://www.[website].com/ Commented May 16, 2017 at 20:32
  • This is a browser CORS policy issue. Because you load the angular app from one port, and make Ajax calls to another port, the browser blocks it. You could do one of the following: 1. setup the NodeJS server to serve your angular app at the base url, or if not possible, 2. configure a proxy setting on your XAMPP server to redirect calls to a path (i.e. /api/*) to the NodeJS app on localhost:3030 Commented May 16, 2017 at 21:26
  • A 3rd option, just to get it working, but really not recommended for your production API, is accept all origins: How to enable cross-origin resource sharing (CORS) in the express.js framework on node.js Commented May 16, 2017 at 21:30
  • @JulianSoro I tried setting up a NodeJs server to run my Angularjs on which was easier than expected. I think the server is running now aswell. However now I get an AngularJs error Uncaught Error: [$injector:modulerr] and nothing is loaded. This is my app.js and the controller for the view Commented May 17, 2017 at 7:44
  • If anyone looking for Nodejs API boilerplate with Expressjs and MongoDB. Try this: github.com/maitraysuthar/rest-api-nodejs-mongodb Commented Aug 17, 2019 at 9:57

1 Answer 1

1

This is due to CORS policy, as Julian Soro pointed above.

I was dealing with this problem before when testing on my virtual machine and access the API on the host. If you are using Chrome, probably it could be helpful to mention there is an extension to overcome that. You could download this extension to allow CORS on Chrome. Here is the link to 'Allow-Control-Allow-Origin:*'.

Hope this could help.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.