So I have some code (app.js, in the server)
console.log("Server started. If you're reading this then your computer is still alive."); //Unnecessary test command to make sure everything works.
var express = require("express");
var app = express();
var serv = require("http").Server(app);
app.get("/", function(req, res) {
res.sendFile(__dirname + "/client");
});
app.use("/client", express.static(__dirname + "/client"));
serv.listen(2000);
//Set up server stuff. This isn't touched.
var io = require("socket.io")(serv, {});
io.sockets.on("connection", function(socket) {
console.log("Socket connection"); //This will print to the server, not the developer console in your browser.
});
//Initialize sockets and set up socket listeners. This isn't touched either, except when adding new events.
And some more code:
<!DOCTYPE html>
<html>
<head>
<title>Multiplayer!</title>
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<script src="/socket.io/socket.io.js"></script>
</head>
<body>
<script>
var socket = io();
</script>
</body>
</html>
My folder structure is:
multiplayer_game
app.js
package.json
node_modules (folder)
node stuff
client (folder)
index.html
js (folder)
img (folder)
server (folder)
Where the farther in the file is, the more "nested" it is.
When I open the page by doing node app.js (folder already cd'ed) and go to localhost:2000, I get "Cannot GET /". When I go to localhost:2000/client, I get everything fine. What can I do to fix my code?
You will need a router for that.
const router = express.Router;
router.get('/', function(req, res) {
res.sendFile(__dirname + "/client");
});
app.use('/', router);
A middleware is not capable to handle various http methods.
Related
I'm making a simple client/server connection via node.js modules and a simple HTML page.
the html page is this:
<script type="text/javascript" src="index.js"></script>
Where the index.js file in the same directory is this:
alert("hello!");
This works fine when I manually click on the html page, but when I invoke it using my app.js:
var express = require("express");
var app = express();
var server = require('http').Server(app);
app.get('/', function (req, res) {
res.sendFile(__dirname + '/web/index.html');
});
app.use('/web', express.static(__dirname + '/web'));
server.listen(2000);
console.log('Started Server!');
by calling
node app.js
it does not show the alert when the HTML page loads. I just installed node.js and installed the node express dependencies in this app after I called "node init" on the project.
The path for index.js and static folder does not match. Therfore it fails to load index.js.
This should work:
app.use('/', express.static(__dirname + '/web'));
server.listen(2000);
I am trying to use in socket.io in my node.js app, but my client can't get the library from my sever and I don't know why.
Error: Failed to load resource: the server responded with a http://localhost:3000/socket.io/socket.io.js status of 404 (Not Found)
Server site:
var express = require('express');
var app = express();
var http = require('http').Server(app);
var io = require('socket.io')(http);
app.use(express.static('public'));
app.get('/', function (req, res) {
res.sendFile( __dirname + "/" + "index.html" );
});
app.listen(3000, function () {
console.log('Example app listening on port 3000!');
});
io.on('connection', function(socket){
console.log('a user connected');
});
Client side:
<head>
<link rel="stylesheet" href="/stylesheets/style.css" />
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io();
</script>
</head>
Your index.html code couldn't find socket.io because you are sendig only Index.html for response. Please try following code.
Use following code:
//"client" is folder for client code which contains index.html
app.use(express.static(__dirname + '/client'));
Remove following code. Node.js will find index.html automatically.
app.get('/', function (req, res) {
res.sendFile( __dirname + "/" + "index.html" );
});
Change your index.html
New code:
<script src="https://cdn.socket.io/socket.io-1.3.7.js"></script>
Old code:
<script src="/socket.io/socket.io.js"></script>
I don't know exactly why your code isn't working, but if socket.io is installed properly, then it automatically configures a route in Express to serve the request for /socket.io/socket.io.js. So, apparently socket.io is not configured/installed properly in your situation.
I can tell you that this initialization of Express and socket.io works and does not have the problem you speak of:
var express = require('express');
var app = express();
var server = app.listen(80);
var io = require('socket.io')(server);
I had the same problem in my index.html while learning Node.js.
The console prompted similar error
I removed socket.io module by executing npm r socket.io in my project directory and re-installed it using npm i socket.io and then it worked fine.
I finally got everything working on a certain page, but the issue I'm facing now is when I create additional pages. I realize the issue must be with my routing, but I'm not sure how to change the server side code without effecting my app.
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.on('connection', function(socket){
// socket functions
});
http.listen(3000, function(){
console.log('listening on *:3000');
});
I would like to serve html in a folder 'public' and have files like index.html and other.html in there.
Configure your express app to use a static directory.
app.use(express.static('public'));
All files located under public can now be accessed. So a file called index.html can now be reached via /index.html
Further documentation can be found here:
http://expressjs.com/starter/static-files.html
If your folder is called public then you could do something like
app.use(express.static('./public'))
.get('/', function(req, res) {
res.sendFile('index.html', {root: 'public/'});
})
I am playing around and trying to learn the MEAN stack to create a single page application. I was able to get my back-end routes to work correctly. I've tested it using Postman and get the results I expect, however I cannot get my front-end to talk to the back-end correctly.
I reduced my front-end to very basic html and javascript, but still get a syntax error "Unexpected token <". When I inspect my coreTest.js file in the browser, I see that it's just a copy of my html file, rather than javascript code.
When I run index.html by itself (without server.js) coreTest.js runs just fine. I'm not sure why, when running my server.js file, my coreTest.js file doesn't work properly.
server.js
// Setup
var express = require('express');
var app = express(); // create app w/ express
var mongoose = require('mongoose'); // used for MongoDB connection
var morgan = require('morgan'); // log requests to the console
var bodyParser = require('body-parser'); // pull information from HTML POST
var methodOverride = require('method-override'); // simulate DELETE and PUT requests
// Configure
mongoose.connect('localhost:27017/test'); // connect to localhost db "test"
// varify connection
var db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error: '));
app.use(express.static(__dirname + '/public')); // set static files location
app.use(morgan('dev')); // log every request to console
app.use(bodyParser.urlencoded({'extended':'true'})); // parse application/x-www-form-url
app.use(bodyParser.json());
app.use(bodyParser.json({ type: 'application/vnd.api+json' })); // parse vnd.api+json as json
app.use(methodOverride());
// define db model
var Todo = mongoose.model('Todo', {
text: String
});
var router = express.Router();
router.route("/todos")
.get(function(req, res) {
Todo.find(function(err, todos) {
if (err)
res.send(err);
res.json(todos);
});
})
.post(function(req, res) {
var todo = new Todo();
todo.text = req.body.text;
todo.save(function(err) {
if (err)
res.send(err);
res.json({mes: "Todo item created"});
})
});
router.route("/todos/:todo_id")
.delete(function(req, res) {
Todo.remove( {
_id: req.params.todo_id
}, function(err, todo) {
if (err)
res.send(err);
res.json({mes: "Successfully deleted"});
});
});
// route to application
router.route("*")
.get(function(req, res) {
res.sendfile('./public/index.html');
});
// Register our routes
app.use('/api', router);
// Listen, start node app
app.listen(8080);
console.log("app listening on port 8080");
coreTest.js
alert("ping");
index.html
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Starter MEAN Single Page Application</title>
<script type="text/javascript" src="coreTest.js"></script>
</head>
<body>
I did it!! Wooo!!
</body>
</html>
I suspect the problem is between
app.use(express.static(__dirname + '/public'));
and
// route to application
router.route("*")
.get(function(req, res) {
res.sendfile('./public/index.html');
});
When you're running the server, your client-side code is trying to load "coreTest.js", which is matched by the last rule ; and so the server returns the content of index.html.
I'm not sure what you mean about "runing index.html by itself" ; if you mean "visiting file://..../public/index.html", it works because the browser will try to load coreTest.js from your file system.
Try using the "static" plugin only to serve files from "public", and use this prefix in the client side code :
app.use("/public", express.static(...))
and in the client
<script type=".." src="public/coreTest.js"></script>
Getting the path rights will depend on what's on your disk.
This might help, too : static files with express.js
I was able to solve my issue using what phtrivier recommended.
Instead of serving my files from "public" I chose to serve them from "api" because I already set my router to take requests from that path as well.
app.use("/api", express.static(__dirname + '/public'));
I didn't need to change my reference to coreTest.js in the html because my files were organized with coreTest already in the root directory like this:
public
-index.html
-coreTest.js
I've been following the tutorial at https://www.tutorialspoint.com/socket.io/, and I have the following 2 files:
app.js:
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
app.get('/', function(req, res) {
res.sendFile('index.html', {root: __dirname});
});
io.on('connection', function(socket) {
console.log('A user connected');
//Send a message after a timeout of 4 seconds
setTimeout(function() {
socket.send('Sent a message 4 seconds after connection!');
}, 4000);
socket.on('disconnect', function () {
console.log('A user disconnected');
});
});
http.listen(80, function() {
console.log('listening on *:80');
});
index.html:
<!DOCTYPE html>
<html>
<head>
<title>Hello world</title>
</head>
<script src = "/socket.io/socket.io.js"></script>
<script>
var socket = io();
socket.on('message', function(data){document.write(data)});
</script>
<body>Hello world</body>
</html>
If I run this in Node.js version 10.16.3 and visit http://localhost/, everything works fine. The server console logs:
A user connected
And the browser eventually displays:
Sent a message 4 seconds after connection!
So far, so good!
The problems arise when I try to run this from my website. Let's pretend it's called example.com.
My web hosting provider uses the same version of Node.js, and has set it up so that each Node.js application runs in a subfolder. Let's pretend it's called example.com/x.
When visiting http://example.com/x, the browser displays:
Cannot GET /x/
So in app.js, I changed this:
app.get('/', function(req, res) {
res.sendFile('index.html', {root: __dirname});
});
...to this:
app.get('/x', function(req, res) {
// Redirect if no slash at the end
if (!req.url.endsWith('/')) {
res.redirect(301, req.url + '/')
}
res.sendFile('index.html', {root: __dirname});
});
Now the initial page loads, but the browser console logs:
The resource from “http://example.com/socket.io/socket.io.js” was blocked due to MIME type (“text/html”) mismatch (X-Content-Type-Options: nosniff).
Loading failed for the <script> with source “http://example.com/socket.io/socket.io.js”.
ReferenceError: io is not defined
Obviously, my app doesn't get a chance to handle this request because it's addressed to the main domain.
So I changed both files:
In app.js, I changed this line:
var io = require('socket.io')(http);
to this:
var io = require('socket.io')(http, {path: "/x/socket.io"});
And in index.html, I changed this line:
<script src = "/socket.io/socket.io.js"></script>
to this:
<script src = "/x/socket.io/socket.io.js"></script>
This got rid of the errors in the browser console, but it still doesn't seem to be connecting.
The browser never displays:
Sent a message 4 seconds after connection!
Same when I run all this in http://localhost/x/, and the Node.js console never logs:
A user connected
Is there an easier way to go about all this than the changes I've been making so far?
If not, what more do I need to do to get this working?
One step left.
In index.html, change this line:
var socket = io();
...to this:
var socket = io.connect("/", {path: "/x/socket.io"});
This should work for both http://example.com/x and http://localhost/x.