socket.io and differents folders --- solution found - socket.io

I'm new to socket.io and i already have a problem, minor i think.
I have installed node.js properly and socket.io too with npm. Then just for testing i cut and paste a sample of code from socket.io and everything works well.
Now, i want to strcuture my code and folders and i have created a folder "client" to put a fresh new js file client.js with the client code from the example.
Here is my architecture
/client
client.js
index.html
server.js
client.js :
var socket = io.connect('http://localhost:80');
socket.on('news', function (data) {
alert('sqd');
console.log(data);
socket.emit('my other event', { my: 'data' });
});
server.js
var app = require('http').createServer(handler)
, io = require('socket.io').listen(app)
, fs = require('fs')
app.listen(80);
function handler (req, res) {
fs.readFile(__dirname + '/index.html', 'utf-8',
function (err, data) {
if (err) {
res.writeHead(500);
return res.end('Error loading index.html ' + __dirname);
}
res.writeHead(200, {'Content-Type' : 'text/html'});
res.end(data);
});
}
io.sockets.on('connection', function (socket) {
socket.emit('news', { hello: 'world' });
socket.on('my other event', function (data) {
console.log(data);
});
});
index.html
<!doctype html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title></title>
<script type="text/javascript" src="/client/client.js"></script>
<script type="text/javascript" src="/socket.io/socket.io.js"></script>
</head>
<body>
</body>
</html>
When i refresh my browser at localhost:80 i have a error on my client.js :
Uncaught SyntaxError: Unexpected token <
Resource interpreted as Script but transferred with MIME type text/html
It seems that there's a problem to interpret my js file as a js file. I've read some threads on the question but nothing works.
Can you help me please ?
Thanx :)
Ok i've found a solution... You have to specify the content type for each file request in a static webserver. May be it could help someone.
Here is the handler function :
function handler (req, res) {
var filePath = req.url;
if (filePath == '/') {
filePath = './client/index.html';
} else {
filePath = './client/lib' + req.url;
}
var extname = path.extname(filePath);
var contentType = 'text/html';
switch (extname) {
case '.js':
contentType = 'text/javascript';
break;
case '.css':
contentType = 'text/css';
break;
}
path.exists(filePath, function(exists) {
if (exists) {
fs.readFile(filePath, function(error, content) {
if (error) {
res.writeHead(500);
res.end();
}
else {
res.writeHead(200, { 'Content-Type': contentType });
res.end(content, 'utf-8');
}
});
}
else {
res.writeHead(404);
res.end();
}
});
}
Hope this can help someone.
I love to post a problem and respond by myself with no help. Somehow it meens that i'm desesperate too fast. And i love to tell my life in a post too :)
Ok i'm gonna eat something and drink more coffee !!!

Thank you so much! This solved my problem!! And I changed the switch to following code:
var extname = path.extname(filePath);
var contentTypesByExtention = {
'html': 'text/html',
'js': 'text/javascript',
'css': 'text/css'
};
var contentType = contentTypesByExtention[extname] || 'text/plain';
It may be easier to maintain :)

Only that solves:
function handler (request, response) {
var file = __dirname + (request.url == '/' ? '/index.html' : request.url);
fs.readFile(file, function(error, data) {
if (error) {
response.writeHead(500);
return response.end('Error loading index.html');
}
response.writeHead(200);
response.end(data, 'utf-8');
});
}

that's what i need! thank you!
and
we'll add one code line a top of
server.js
var app = require('http').createServer(handler)
, io = require('socket.io').listen(app)
, fs = require('fs')
**, path = require('path')**

You can use mime module as well:
var mime = require('mime')
, content_type = mime.lookup(filePath);
// handle the request here ...
response.setHeader('Content-Type', content_type);
response.writeHead(200);
response.end(data);

And you must made fs.readFile wrapped by a closure, otherwise some file (especially the last file) will be read more than once, and others will not be read at all. And the contentTypewill not be set as you wish. This is because of the callback strategy used by fs.readFile. The problem does not appear when the html file just load one external file, but as the external files(css, js, png) loaded more than one it will appear as i pointed out above. (I came upoon this by myself)
So your code should make a little change as follows:
;(function (filename, contentType) {
fs.readFile(filename, function(err, file) {
// do the left stuff here
});
}(filename, contentType));

Related

Django GET request in AJAX

I need to get some HTML using AJAX.
My view work fine as long as I use jQuery:
view.py
def my_ajax(request):
if request.is_ajax():
my_form = MyForm()
context = {
'form': my_form
}
return render(request, 'myapp/form.html', context)
main.js (jQuery load)
$(document).ready(function() {
$('#foo').click(function() {
$('#bar').load('{% url "myapp:form" %}');
});
});
If I use the JavaScript XMLHttpRequest I have to remove if request.is_ajax(): from the view otherwise I got the error The view myapp.views.my_ajax didn't return an HttpResponse object. It returned None instead.
main.js (XMLHttpRequest)
(function() {
document.getElementById('foo').addEventListener("click", function() {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (xhttp.readyState == 4 && xhttp.status == 200) {
document.getElementById("bar").innerHTML = xhttp.responseText;
}
};
xhttp.open("GET", '{% url "myapp:form" %}', true);
xhttp.send();
}, false);
})();
What I'm doing wrong in the XMLHttpRequest?
I am surely missing something but I would like to use Vanilla JavaScript this time.
Thanks!
Try to add xhttp.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); after var xhttp = new XMLHttpRequest();.

Can i use and is secure to use AJAX in my Server Node?

i would like to use native ajax to make some calls inside my node.js server.
Is this secure ?? Can i do it without problems ???
Here's and example:
.... NODE
app.post('/postReceptor', function(req, res, next) {
var data1 = req.body['input1'];
var data2 = req.body['input2'];
var xhr;
if (window.XMLHttpRequest) { // Mozilla, Safari, ...
xhr = new XMLHttpRequest();
} else if (window.ActiveXObject) { // IE
try {
xhr = new ActiveXObject('Msxml2.XMLHTTP');
}
catch (e) {
try {
xhr = new ActiveXObject('Microsoft.XMLHTTP');
}
catch (e) {}
}
}
xhr.open('GET', encodeURI('HTTP://WWW.WEBSITE.COM'), true);
xhr.send(null);
xhr.onreadystatechange = function() {
if(xhr.readyState === 4) { // done
if(xhr.status === 200) { // complete
res.render('renderPage', {
sendingData: xhr.responseText
});
}
}
};
});
This is to verify an external page some customer data sent by the client !
Thanks !
Doing AJAX calls is a concept that is originated from the client side and you are in the server so you don't have the XMLHttpRequest function available on Node.JS.
So to make a HTTP request from Node.JS, you could use http.request or use another library like request helping you to code without complexities, here is an example using the request library:
var request = require('request');
var URL = 'http://www.google.com';
request(URL, function(error, response, body) {
if (!error && response.statusCode === 200) {
console.log(body);
}
});
Thanks for the answers. I got the answer to the question using the library https://www.npmjs.com/package/xmlhttprequest
Risto Novik, this is a simple example and of course i have to validate the fields!

complex nodejs url mapping

I need help in url mapping in express.js framework in nodejs.
router.get('/first/:second_param', function(res,req){
//processing second_param and rendering a template,
res.render('first.html');
});
router.get('/first/:second_param/get_items', function(res,req){
//again evaluating second_param and and responding accordingly
res.send(jsonData);
});
Is this kind of routing possible in Express 4.0?
first.html makes a ajax request at url './get_items'
Yes, it is possible to do it with Express 4.0.
Here is an example:
you need to install ejs and express: npm install ejs express
app.js file:
var express = require('express');
var app = express();
app.set('view engine', 'ejs');
app.get('/', function(req, res) {
res.redirect('/home/2');
});
app.get('/home/:itemId', function(req, res) {
var itemId = req.params.itemId;
console.log(itemId);
res.render('index');
});
app.get('/api/items/:itemId', function(req, res) {
var itemId = req.params.itemId;
console.log('item id: %s', itemId);
res.json([{name: 'item1'}]);
});
app.listen(8080, function() {
console.log('server up and running at 8080');
});
views/index.ejs file:
<!doctype html>
<html>
<head>
</head>
<body>
<h1>Hello World!</h1>
<script>
function responseGET() {
if(this.readyState !== 4 || this.status !== 200) return;
alert(this.responseText);
}
function getItems(URL) {
var request = new XMLHttpRequest();
request.open('GET', URL, true);
request.onreadystatechange = responseGET.bind(request);
request.send(null);
}
function domReady() {
getItems('http://localhost:8080/api/items/1');
}
document.addEventListener('DOMContentLoaded', domReady);
</script>
</body>
</html>
Basically I am have a server which is serving an index.html when someone requests at /home/:itemId and also I am exposing another route for serving items /api/items/:itemId.
From the client side once the DOM is ready I am requesting to /api/items/:itemId some items which then are displayed in the index html.

Post with AngularJS doesn't work

I would like to send a post request to my API. It works with jQuery :
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script>
$.ajax({
type: "POST",
url: "api.php?option=inscription",
data: {lol : "mess"}
});
</script>
But it doesn't with AngularJS :
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"> </script>
{{1+1}}
<script>
$http.post('api.php?option=inscription', {lol : "mess2"})
.success(function(){alert('cool');});
</script>
If someone can help me. Thank you !
UPDATE :
Thank for your answers, I wanted to simplify but it wasn't clear anymore. So with your help, this is my new code, and the problem is the same. The data in the backend is empty ;
frontend :
<html ng-app="myApp">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"> </script>
<div ng-controller="MainCtrl"></div>
{{data}}
<script>
var app = angular.module('myApp', []);
app.service('SomeService', function($http) {
this.readData = function(dataUrl, dataTobePosted) {
var back = $http.post(dataUrl, dataTobePosted);
back.success(function(data){
console.log(data);
return data;
}).error(function(data, status, headers, config) {
return status;
});
}
});
app.controller('MainCtrl', function($scope, $http, SomeService){
$scope.readData = function(url) {
var dataTobePosted = {"lol": "mess"};
$scope.data = SomeService.readData(url, dataTobePosted);
}
$scope.readData('api.php?option=inscription');
});
</script>
</html>
For clarity, I am suggesting a simple implementation. However, further reading may needed in order to understand the behaviour precisely.
angular.module('myApp').service('SomeService', function($http) {
this.readData = function(dataUrl, dataTobePosted) {
// read data;
return $http.post(dataUrl, dataTobePosted)
.then(function(res) {
return res.data;
}, function(res) {
return res;
}
}
return this;
});
angular.module('myApp').controller('MyController', function($scope, SomeService) {
$scope.readData = function(url) {
var dataTobePosted = {"lol": "mess"};
SomeService.readData(url, dataTobePosted)
.then(function(res) {
$scope.data = res;
}, function(res) {
// Display error
}
}
$scope.readData('api.php?option=inscription');
}
Usage in the HTML page
<div ng-controller="MyController">
{{data}}
</div>
You're using AngularJS as if it's jQuery. It's not. AngularJS works with dependency injection, so you need to wrap your $http call inside a controller.
You should probably read up on AngularJS. A few useful links:
https://docs.angularjs.org/guide/introduction
https://docs.angularjs.org/guide/controller
https://docs.angularjs.org/guide/di
"Thinking in AngularJS" if I have a jQuery background?
My bad, my problem came from my backend in the php I just get my data with :
$data = json_decode(file_get_contents("php://input"));
and not with $_POST

socket.io not working in Chrome

i'm trying the this simple socket.io example and it works in Safari (send/receive from both sides). However, in the Chrome the client receives messages but the server won't receive messages sent by the client
index.html
<!doctype html>
<html>
<head>
<title>web sockets</title>
<meta charset="utf-8">
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io.connect('http://localhost:8888');
socket.on('news', function (data) {
console.log(data);
writeMessage(data);
socket.emit('my other event', { my: 'data' });
});
function writeMessage(msg) {
var msgArea = document.getElementById("msgArea");
if (typeof msg == "object") {
msgArea.innerHTML = msg.hello;
}
else {
msgArea.innerHTML = msg;
}
}
</script>
</head>
<body>
<div id="msgArea">
</div>
</body>
</html>
server.js
var app = require('http').createServer(handler)
, io = require('/usr/local/lib/node_modules/socket.io').listen(app)
, fs = require('fs')
app.listen(8888);
function handler (req, res) {
fs.readFile(__dirname + '/index.html',
function (err, data) {
if (err) {
res.writeHead(500);
return res.end('Error loading index.html');
}
res.writeHead(200);
res.end(data);
});
}
io.sockets.on('connection', function (socket) {
socket.emit('news', { hello: 'world' });
socket.on('my other event', function (data) {
console.log(data);
});
});
Am I missing something? Chrome is on v.19
You can use http://socket.io-test.com to see if the problem is with your browser/proxy or your code.

Resources