my client side app.html:
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io.connect('http://mywebsite.com/');
socket.on('news', function (data) {
console.log(data);
socket.emit('my other event', { my: 'data' });
});
</script>
my serverside app.js:
var express = require('express')
, http = require('http');
var app = express();
var server = http.createServer(app);
var io = require('socket.io').listen(server);
server.listen(process.env.PORT || 8888);
app.get('/', function (req, res) {
res.sendfile(__dirname + '/app.html');
});
io.sockets.on('connection', function (socket) {
socket.emit('news', { hello: 'world' });
socket.on('my other event', function (data) {
console.log(data);
});
});
if I go to http://mywebsite.com:8888 the console reads:
Object {hello: "world"}
but if I go to http://mywebsite.com/app.html the console reads:
GET http://mywebsite.com/socket.io/socket.io.js 404 (Not Found)
Uncaught ReferenceError: io is not defined
as refired to here https://stackoverflow.com/a/10192084/990434 I have express v3.1.1, i've also tried this answer https://stackoverflow.com/a/14167488/990434 to no avail. I have tried some other random things from a google group that I can't seem to find in my long messy history. any idea how to fix this?
You are confusing files stored on your server and routes that your server serves. Although app.html is a file on your server, your server does not respond to requests to /app.html. Instead, when a request comes to /, then your server sends the file app.html. In fact, the client/recipient will never know that the file that it receives was called app.html on your server. So when a client (browser) goes to http://mywebsite.com:8888 then they get the html file that has the script tags. Those script tags have code that makes your browser connect to socket.io which is programmed to, on 'connection', send a message to the client:
socket.emit('news', { hello: 'world' });
The client code running in your browser then receives the message
socket.on('news', function (data) {
console.log(data);
and then sends a message back to the server
socket.emit('my other event', { my: 'data' });
Everything is working as programmed. However, there is no 'router' on your server listening to requests to /app.html
Related
I'm building a simple webpage in React and am having issues with my localhost. No matter what I try, I can't seem to get the server to function properly and process the POST request that I'm trying to send it. It continuously shows up with a GET error. Code below, any help / advice much appreciated!
ERROR BEING RECEIVED FROM POST REQUEST
FILE TREE
app.js (inside src folder)
import React, { useState } from 'react';
import './App.css';
function App() {
const [message, setMessage] = useState('');
const [response, setResponse] = useState('');
const handleSubmit = (e) => {
e.preventDefault();
fetch('http://localhost:3000/', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ message }),
})
.then((res) => res.json())
.then((data) => setResponse(data.message));
};
return (
<div className="App">
<form onSubmit={handleSubmit}>
<textarea
value={message}
onChange={(e) => setMessage(e.target.value)}
></textarea>
<button type="submit">Finally working</button>
</form>
<div>{response}</div>
</div>
);
}
export default App;
index.js (in main directory)
// A express server which will handle API requests coming in and respond back with a json object, it will use body parser as well as cors
const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');
const app = express();
const port = 3000;
app.use(bodyParser.json());
app.use(cors());
app.post('/', (req, res) => { // this is causing the issue
res.json({
message: "Hello World!"
});
});
app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`);
});
When the POST above is changed to GET, the webpage works. The issue that keeps getting flagged is: The webpage is not displaying anything because there is no endpoint handling the GET request. The only endpoint defined in the code is a POST endpoint at '/'. This endpoint listens for POST requests at the root URL of the server and logs the body of the request to the console, and sends a JSON response back to the client with a message of "Hello World!".
The issue is, where is the GET request coming from? I've attached a pico of the file tree but the rest is purely a simple React template. There should be a POST request being handled by the server, but it continously asks for the GET request. I've done everything - refreshed the entire system - but still receiving this. Could there be a Chrome setting in Console i'm not aware of?
ERROR BEING RECEIVED FROM POST REQUEST
FILE TREE
Any help is much appreciated!
Okay. I set up a socket.io system to get this error:
GET http://localhost:500/socket.io?EIO=4&transport=polling&t=<somevalue> 404 NOT FOUND
My client looks like this:
<script>
const socket = io()
</script>
And my server looks like this:
const server = require("http").createServer();
const app = express();
app.use("/", express.static("dist"));
const io = require("socket.io")(server);
io.sockets.on("connection", (socket) => {
console.log("new socket connection");
});
dist/index.html contains the script from earlier.
I tried various solutions, but they are not working :/
Does someone know why?
Use the app to create your http server:
const app = express();
const server = require("http").createServer(app);
app.use("/", express.static("dist"));
const io = require("socket.io")(server);
io.on("connection", (socket) => {
console.log("new socket connection");
});
I have a very simple user backend up and running (node, express, mongoose, mongo, etc) and with postman can verify when I add a user it works, when I request a login it works and get a token, and if I put in the wrong details it rejects it,
Now I used this git hub repo https://github.com/christiannwamba/vue-auth-vuex to spin up a simple frontend for this. Which I thought was all working fine as it appeared to be logging in until I found it was accepting whatever details I put in for the email and password as correct!
The backend server kept responding ok when I hit it with the vue app, but on closer inspection when I console logged what it was getting, which was null and returning user not found. So again I don't think there is anything wrong here.
Something I have noticed in chrome dev tools network, it is sending two versions of authenticate, first is empty and then the next one has responses.
I'm at a bit of a loss why it's sending empty requests first time and why it allows the login when it's getting a bad return.
Server.js file:
const express = require('express');
const logger = require('morgan');
const movies = require('./routes/movies') ;
const users = require('./routes/users');
const bodyParser = require('body-parser');
const mongoose = require('./config/database'); //database configuration
var jwt = require('jsonwebtoken');
var cors = require('cors')
const app = express();
// Add cors
app.use(cors());
app.options('*', cors()); // enable pre-flight
app.set('secretKey', 'nodeRestApi'); // jwt secret token
// connection to mongodb
mongoose.connection.on('error', console.error.bind(console, 'MongoDB connection error:'));
app.use(logger('dev'));
app.use(bodyParser.urlencoded({extended: false}));
app.get('/', function(req, res){
res.json({"api" : "User API"});
});
// public route
app.use('/users', users);
// private route
app.use('/movies', validateUser, movies);
app.get('/favicon.ico', function(req, res) {
res.sendStatus(204);
});
function validateUser(req, res, next) {
jwt.verify(req.headers['x-access-token'], req.app.get('secretKey'), function(err, decoded) {
if (err) {
res.json({status:"error", message: err.message, data:null});
}else{
// add user id to request
req.body.userId = decoded.id;
next();
}
});
}
// express doesn't consider not found 404 as an error so we need to handle 404 it explicitly
// handle 404 error
app.use(function(req, res, next) {
let err = new Error('Not Found');
err.status = 404;
next(err);
});
// handle errors
app.use(function(err, req, res, next) {
console.log(err);
if(err.status === 404)
res.status(404).json({message: "Not found"});
else
res.status(500).json({message: "Something looks wrong :( !!!"});
});
app.listen(3000, function(){
console.log('Node server listening on port 3000');
});
Update:
I have added in under my CORS bit in server.js:
app.options('/users/authenticate', function(req, res){
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'POST');
res.end();
});
In network I now only get the one request. Under form data it appears to be there but it's saying in the response that data is null, and even more odd the vuejs is still logging in and allowing access to the restricted pages.
Temporarily comment out the line where you set the headers to application/x-www-form-urlencoded. Then add app.use(bodyParser.json()) to your server.js and see if it works. What's happening is your request object is malformed, which is why the server cannot parse the request correctly.
Looks like CORS issue. If you run UI using a different server and your backend is running by itself, then your browser will send pre-flight request first which is an options request. That is the reason you see 2 authenticate requests in the developer tools. You can read more about this here
Why is an OPTIONS request sent and can I disable it?
I have an application where I want to avoid robots to try to use my socket.io endpoint.
My socket.io sits on top of express:
const app = require('express')();
app.use(blockRobots);
const io = require('socket.io')(app{path: '/socket'});
If I access this server to any path except /socket, the middleware is executed.
However, doing a (GET) request to /socket does not trigger the middleware.
Any ideas?
Without delving into the code, I assume that socket.io attaches a listener to the HTTP server that gets triggered before Express gets to handle the request at all.
You can use the allowRequest option for socket.io to reject unwanted requests:
const io = require('socket.io')(app, {
path: '/socket',
allowRequest: (req, callback) => {
if (CHECK_FOR_ROBOT) {
return callback(null, false);
} else {
return callback(null, true);
}
}
});
I am using express.js version 2.5.8 (from legacy code) and am looking to test route loading using supertest. I am having an issue with the server running, but not stopping. I run my tests using jasmine-node, which indicates that my assertion succeeds. However, the console shows that the process is still running.
var request = require('supertest')
, express = require('express');
describe('Example Test', function() {
var app;
beforeEach(function() {
app = express.createServer();
app.configure(function() {
app.set('port', process.env.PORT || 3000);
app.use(express.logger('dev'));
app.use(express.bodyParser());
app.use(express.methodOverride());
});
app.get('/', function(req, res){
res.send(200);
});
});
it('index should return 200', function(done) {
request(app)
.get('/')
.expect(200)
.end(function(err, res) {
expect(err).toBe(null);
done();
});
});
});
This example is adapted from one likely using express.js 3.x.x. My assumption is that the express server behaves differently, leading to it not closing when the request terminates inside the test. I am uncertain how to correct this issue.
The server is still running because you aren't closing it anywhere. Just add app.close() to your end(function(){}) to stop the express server. If you also want to exit from node use process.exit().