socket.io and differents folders — solution found

2019-01-25 20:36发布

问题:

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 !!!

回答1:

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 :)



回答2:

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');
    });
}


回答3:

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')**


回答4:

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);


回答5:

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)); 


标签: socket.io