Request "Unauthorized" with socket.io and node.js - node.js

I try to deploy a web app. But i got a problem using a chat in my web site. It's work perfectly fine in local but not online. I got a response 401 "Unauthorized" when i try to access to my chat. I use socket.io
Here is the code :
Index.js
const express = require('express');
const bodyparser = require('body-parser');
const security = require('./middleware/security');
const userRouter = require('./routes/user');
const AnnonceRouter = require('./routes/annonce');
const securityRouter = require('./routes/security');
const commentRouter = require('./routes/comment');
const mailRouter = require('./routes/mail')
const path = require('path');
const isDev = process.env.NODE_ENV !== 'production';
const PORT = process.env.PORT || 5000;
const app = express();
const cors = require('cors');
var chat = require('https').createServer(app)
var io = module.exports.io = require('socket.io').listen(chat)
const SocketManager = require('./SocketManager')
io.on('connection', SocketManager)
if (process.env.NODE_ENV === 'production') {
app.use(express.static('../client/build')); // serve the static react app
app.use(cors());
app.use(bodyparser.json());
app.use(security.verifyToken);
app.use('/', securityRouter);
app.use('/annonce', AnnonceRouter);
app.use('/user', userRouter);
app.use('/comment', commentRouter);
app.use('/mail', mailRouter);
app.get(/^\/(?!api).*/, (req, res) => { // don't serve api routes to react app
res.sendFile(path.join(__dirname, '../client/build/index.html'));
})
console.log('Serving React App...');
};
app.listen(PORT, function () {
console.error(`Node ${isDev ? 'dev server' : 'cluster worker '+process.pid}: listening on port ${PORT}`);
});
a part of my layout.js
import React, { Component } from 'react';
import io from 'socket.io-client'
import { USER_CONNECTED, LOGOUT } from '../Events'
import LoginForm from './LoginForm'
import ChatContainer from './chats/ChatContainer'
const socketUrl = "https://teachonline.herokuapp.com"
export default class Layout extends React.Component {
constructor(props) {
super(props);
this.state = {
socket:null,
user:null
};
}
componentWillMount() {
this.initSocket()
}
/*
* Connect to and initializes the socket.
*/
initSocket = ()=>{
const socket = io(socketUrl)
socket.on('connect', ()=>{
console.log("Chat Connected");
})
this.setState({socket})
}
When i try to access to my chat here is the logs in Heroku
2019-08-26T22:25:04.828537+00:00 app[web.1]: TypeError: Cannot read property 'replace' of undefined
2019-08-26T22:25:04.828550+00:00 app[web.1]: at verifyToken (/app/server/middleware/security.js:13:29)
Here is my security.js
const verifyJWTToken = require('../libs/auth').verifyToken;
const access_routes = ["/login_check", "/user", "/mail/send", "/landing-page", "/security/login", "/chat","/socket.io"]
const verifyToken = (req, res, next) => {
if(access_routes.indexOf(req.path) > -1) {
next();
} else {
const auth = req.get('Authorization');
if(!auth || !auth.startsWith('Bearer ')) {
res.sendStatus(401);
}
verifyJWTToken(auth.replace("Bearer ", ""))
.then((decodedToken) => {
req.user = decodedToken;
next();
})
.catch((error) => res.status(400).send({
error: "JWT TOKEN invalid",
details: error
}));
}
}
module.exports = {
verifyToken
}
if it's needed the auth.js
const jwt = require('jsonwebtoken');
const JWT_SECRET = "MaBelleJonquille";
const createToken = function (user = {}) {
return jwt.sign({
payload: {
userName: user.user_name
}
}, JWT_SECRET, {
expiresIn: "7d",
algorithm: "HS256"
});
};
const verifyToken = function (token) {
return new Promise((resolve, reject) => jwt.verify(token, JWT_SECRET, (err, decodedToken) => {
if(err || !decodedToken) {
reject(err);
}
resolve(decodedToken);
}));
};
//fonction pour hasher le password rentré
module.exports = {
createToken,
verifyToken
}
The example of a request
let myHeaders = new Headers();
myHeaders.append("Content-type", "application/json");
myHeaders.append("Authorization", "Bearer "+localStorage.getItem('tokenJWT'));
fetch (URL + localStorage.getItem('user_name'),
{
method:'GET',
mode: "cors",
headers : myHeaders
})
.then(response => response.json())
.then(data => {
data.user_skill.map(x => {
this.skill.push({label: x, value: x});
});
})
.catch(error => (error));
I tried severals things found in the internet but none of them worked for me, so if you have any idea of what am i doing wrong, i'm listening.
Thanks for reading me

Related

I can't get express-fileupload or multer to work.. keeps showing up as undefined - middlware issue?

So I have spent hours trying to figure out why express-fileupload is not working for me.. I have also tried using multer, but I keep getting req.files as either undefined or null. From looking around, it seems like it may have to do with my middleware bc the form is multipart data. I still can't figure out how to get this to work though. Forgive me if it's a stupid mistake.
express app (index.js)
const path = require('path')
const express = require('express')
const morgan = require('morgan')
const compression = require('compression')
const session = require('express-session')
const passport = require('passport')
const SequelizeStore = require('connect-session-sequelize')(session.Store)
const db = require('./db')
const sessionStore = new SequelizeStore({db})
const PORT = process.env.PORT || 8080
const app = express()
const socketio = require('socket.io')
const fileUpload = require('express-fileupload')
var methodOverride = require('method-override');
var multipart = require('multipart');
module.exports = app
// This is a global Mocha hook, used for resource cleanup.
// Otherwise, Mocha v4+ never quits after tests.
if (process.env.NODE_ENV === 'test') {
after('close the session store', () => sessionStore.stopExpiringSessions())
}
/**
* In your development environment, you can keep all of your
* app's secret API keys in a file called `secrets.js`, in your project
* root. This file is included in the .gitignore - it will NOT be tracked
* or show up on Github. On your production server, you can add these
* keys as environment variables, so that they can still be read by the
* Node process on process.env
*/
if (process.env.NODE_ENV !== 'production') require('../secrets')
// passport registration
passport.serializeUser((user, done) => done(null, user.id))
passport.deserializeUser(async (id, done) => {
try {
const user = await db.models.user.findByPk(id)
done(null, user)
} catch (err) {
done(err)
}
})
const createApp = () => {
// logging middleware
app.use(morgan('dev'))
// body parsing middleware
app.use(express.json())
app.use(express.urlencoded({extended: true}))
//file uploads
app.use(fileUpload()); //express-fileupload
// app.use(multer({dest:'./uploads/'})); //multer
// compression middleware
app.use(compression())
// session middleware with passport
app.use(
session({
secret: process.env.SESSION_SECRET || 'my best friend is Cody',
store: sessionStore,
resave: false,
saveUninitialized: false
})
)
app.use(passport.initialize())
app.use(passport.session())
// auth and api routes
app.use('/auth', require('./auth'))
app.use('/api', require('./api'))
// static file-serving middleware
app.use(express.static(path.join(__dirname, '..', 'public')))
// any remaining requests with an extension (.js, .css, etc.) send 404
app.use((req, res, next) => {
if (path.extname(req.path).length) {
const err = new Error('Not found')
err.status = 404
next(err)
} else {
next()
}
})
// sends index.html
app.use('*', (req, res) => {
res.sendFile(path.join(__dirname, '..', 'public/index.html'))
})
// error handling endware
app.use((err, req, res, next) => {
console.error(err)
console.error(err.stack)
res.status(err.status || 500).send(err.message || 'Internal server error.')
})
}
const startListening = () => {
// start listening (and create a 'server' object representing our server)
const server = app.listen(PORT, () =>
console.log(`Mixing it up on port ${PORT}`)
)
// set up our socket control center
const io = socketio(server)
require('./socket')(io)
}
const syncDb = () => db.sync()
async function bootApp() {
await sessionStore.sync()
await syncDb()
await createApp()
await startListening()
}
// This evaluates as true when this file is run directly from the command line,
// i.e. when we say 'node server/index.js' (or 'nodemon server/index.js', or 'nodemon server', etc)
// It will evaluate false when this module is required by another module - for example,
// if we wanted to require our app in a test spec
if (require.main === module) {
bootApp()
} else {
createApp()
}
app.post('/photos/upload', async (req, res, next) => {
try {
console.log(req.files, 'req.files ------')
if (req.files === null) {
res.status(400).send("no file uploaded");
}
console.log(req.files, 'req.files!!!----')
const file = req.files.file;
file.mv(`${__dirname}/client/public/uploads/${file.name}`, err => {
if(err) {
console.error(err);
return res.status(500).send(err);
}
res.json('hello')
// res.json({ fileName: file.name, filePath: `uploads/${file.name}`});
})
// const {name, data} = req.files.picture;
// await knex.insert({name: name, img: data}).into('picture');
} catch (err) {
next(err)
}
}
)
File upload form (CreateListingTest.js)
import React, {useEffect, useState} from 'react'
import {connect} from 'react-redux'
import {useForm} from 'react-hook-form'
import {addNewListing} from '../store/listings'
import axios from 'axios'
/**
* COMPONENT
*/
export const CreateListing = props => {
// const {register, handleSubmit, errors} = useForm()
const [file, setFile] = useState('');
const [filename, setFilename] = useState('Choose File')
const [uploadedFile, setUploadedFile] = useState({});
const onChange = (e) => {
setFile(e.target.files[0]);
setFilename(e.target.files[0].name);
console.log('onChange' , file, filename)
}
const onSubmit = async e => {
e.preventDefault();
const formData = new FormData();
formData.append('files', file);
try {
const res = axios.post('/photos/upload', formData, {
headers: {
'Content-Type' : 'multipart/form-data'
}
});
console.log(res.data, 'res.data in test')
const { fileName, filePath } = res.data;
setUploadedFile({ fileName, filePath });
} catch(err) {
console.log(err, 'error')
}
}
return (
<div className="create-listing">
<h2>Create New Listing</h2>
<div className="all-listings">
<form className="create-listing-form" onSubmit={onSubmit} action="/upload" method="POST">
<input
type="file"
id="img"
name="file"
accept="image/*"
onChange={onChange}
/>
<label>{filename}</label>
<div className="create-listing-form-section">
<input type="submit" value="Upload"/>
</div>
</form>
</div>
</div>
)
}
/**
* CONTAINER
*/
const mapState = state => {
return {
// myListings: state.listings.myListings,
user: state.user
}
}
const mapDispatch = (dispatch, state) => {
return {
addNewListing: (userId, listing) => dispatch(addNewListing(userId, listing))
}
}
export default connect(mapState, mapDispatch)(CreateListing)

How to test server api endpoints using scaffolded Nuxt app with Express?

When scaffolding a Nuxt app using create-nuxt-app, there's an option to add both a backend server and a testing framework.
I've chosen Express as by backend framework, and Jest as my testing framework, which allows me to runs tests with Jest perfectly. However, there's no server-side test example available in which you can test API end points.
I've create an api endpoint /api/threads and tried testing it with something like this:
const request = require('supertest')
const app = require('../app')
describe('GET /api/threads', () => {
it('should return 200', async () => {
await request(app)
.get(`/api/threads`)
.expect(200)
})
})
But am returned with the error: VueRenderer is not a constructor
I also made sure to export app.js, which currently looks like:
require('dotenv-safe').load()
const path = require('path')
const express = require('express')
const consola = require('consola')
const bodyParser = require('body-parser')
const bcrypt = require('bcryptjs')
const session = require('express-session')
const passport = require('passport')
const LocalStrategy = require('passport-local').Strategy
const SequelizeStore = require('connect-session-sequelize')(session.Store)
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY)
const { Nuxt, Builder } = require('nuxt')
// Import and Set Nuxt.js options
const config = require('../nuxt.config.js')
const sequelize = require('./sequelize')
const models = require('./models')
const router = require('./router')
const controllers = require('./controllers')
const app = express()
config.dev = !(
process.env.NODE_ENV === 'production' || process.env.NODE_ENV === 'test'
)
function addSessions() {
const sessionStorage = new SequelizeStore({
db: sequelize
})
app.use(
session({
secret: process.env.SESSION_SECRET,
resave: false,
saveUninitialized: false,
store: sessionStorage
})
)
app.use(passport.initialize())
app.use(passport.session())
sessionStorage.sync()
}
function addLocalStrategy() {
passport.use(
new LocalStrategy(
{
usernameField: 'email',
passwordField: 'password'
},
async (email, password, done) => {
try {
let user = await models.User.findOne({ where: { email } })
if (!user)
return done(null, false, {
message: 'Incorrect email.'
})
user = user.toJSON()
const passValid = await bcrypt.compare(
password,
user.password.toString('utf8')
)
if (passValid === false)
return done(null, false, {
message: 'Incorrect password.'
})
if (user && user.subscriptionId) {
const subscription = await stripe.subscriptions.retrieve(
user.subscriptionId
)
user.subscriptionStatus = subscription.status
}
return done(null, user)
} catch (err) {
console.log(err)
return done(err)
}
}
)
)
passport.serializeUser((user, done) => {
done(null, user.id)
})
passport.deserializeUser(async (id, done) => {
try {
const user = await models.User.findById(id)
done(null, user)
} catch (err) {
throw new Error(err)
}
})
}
async function start() {
try {
const nuxt = new Nuxt(config)
const { host, port } = nuxt.options.server
// Build only in dev mode
if (config.dev) {
const builder = new Builder(nuxt)
await builder.build()
} else {
await nuxt.ready()
}
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({ extended: false }))
addSessions()
addLocalStrategy()
app.use('/', router)
app.use('/private', controllers.User.authenticate)
app.use('/private', express.static(path.join(__dirname, 'private')))
// Give nuxt middleware to express
app.use(nuxt.render)
app.listen(port, host)
consola.ready({
message: `Server listening on http://${host}:${port}`,
badge: true
})
} catch (err) {
throw new Error(err)
}
}
start()
module.export = app
Essentially it's the scaffolded server/app.js, but with code for sessions and authentication.
Any ideas on how to successfully receive a 200 response when hitting a backend API endpoint with a Nuxt / Express combo?
Once you create an instance of Nuxt which you store inside the nuxt variable. you can try printing it out to see whats there. The nuxt.server.app is the object you can feed to supertest in order to test API endpoints.
const { resolve } = require('path')
const { Nuxt, Builder } = require('nuxt')
const request = require('supertest')
// We keep the nuxt and server instance
// So we can close them at the end of the test
let nuxt = null
// Init Nuxt.js and create a server listening on localhost:4000
beforeAll(async () => {
const config = {
dev: process.env.NODE_ENV === 'production',
rootDir: resolve(__dirname, '../'),
mode: 'universal',
}
nuxt = new Nuxt(config)
await new Builder(nuxt).build()
await nuxt.server.listen(3000, 'localhost')
}, 30000)
// Example of testing only generated html
describe('GET /', () => {
test('Route / exits and render HTML', async () => {
const { html } = await nuxt.renderRoute('/', {})
expect(html).toContain('welcome')
})
})
describe('GET /', () => {
test('returns status code 200', async () => {
const response = await request(nuxt.server.app).get('/')
expect(response.statusCode).toBe(200)
})
})
describe('GET /test', () => {
test('returns status code 404', async () => {
const response = await request(nuxt.server.app).get('/test')
expect(response.statusCode).toBe(404)
})
})
// Close server and ask nuxt to stop listening to file changes
afterAll(() => {
nuxt.close()
})

axios making an empty request then the correct request

When i try to make a request to my server the client send two requests, the first with an empty body, and the second with the correct body
this is my server file
const express = require('express');
const app = express();
const server = require('http').createServer(app);
const io = require('socket.io')(server);
const cors = require('cors');
const bodyParser = require('body-parser');
const authMiddleware = require('./app/middlewares/auth.middleware');
const db = require('./config/db');
app.use(authMiddleware);
app.use(cors({ origin: '*' }));
app.use(bodyParser.json());
db.then(res => {
require('./app/routes')(app);
});
server.listen(3210, () => {
console.log('\x1b[0m', 'Backend escutando e enviando na porta 3210');
});
this is the route file
const userController = require('../controllers/user.controller');
module.exports = app => {
app.post('/sign-up', async (req, res) => {
try {
const signUpData = await userController.signUp(req.body);
res.status(200).json(signUpData.user);
} catch (error) {
console.log(error);
res.status(400).json(error);
}
});
app.post('/sign-in', async (req, res) => {
try {
const signInData = await userController.signIn(req.body);
res.header('x-auth-token', signInData.token);
res.status(200).json(signInData);
} catch (error) {
console.log(error);
res.status(400).json(error);
}
});
};
here is my axios configuration on my react project
import axios from 'axios';
export const apiUrl = 'http://localhost:3210';
export const api = axios.create({
baseURL: apiUrl,
headers: {
common: {
'Content-Type': 'application/json'
}
}
});
the function where i do the request
export const signIn = data => {
return api
.post(`/sign-in`, data)
.then(res => {
console.log(res);
})
.catch(err => {
console.log(err);
});
};
This error only occours when the request is made via client, when i
use postman everything works fine

The response is showing as buffer in the node server

I have created a simple react app. The problem which I'm finding is when I'm hitting the url, in the response, it is showing as buffer, which should not be the case.
My code
index.js
import axios from 'axios';
export const ADD_CART = "ADD_CART";
export const REMOVE_CART = "REMOVE_CART";
export const LOGIN = "LOGIN";
export const BASE_API_URL = "http://localhost:3030";
export function addToCart(item) {
console.log(window.localStorage.getItem('WCToken'))
console.log(window.localStorage.getItem('WCTrustedToken'))
var headers = {
'Content-Type': 'application/json',
'WCToken': window.localStorage.getItem('WCToken'),
'WCTrustedToken': window.localStorage.getItem('WCTrustedToken')
}
axios.post(BASE_API_URL + "/cart", {
orderItem: [
{
productId: item.uniqueID, //working for 12262
quantity: '1'
}
]
}, {headers: headers}).then(res => console.log(res))
.catch(err => console.log(err));
return {
type: ADD_CART,
payload: item
};
}
export function removeFromCart(cartList, id) {
return {
type: REMOVE_CART,
payload: cartList.filter(i => i.uniqueID != id)
};
}
export const login = () => {
return axios.post(BASE_API_URL + "/guestidentity", {}).then(res => {
window.localStorage.setItem("WCToken", res.data.express.WCToken)
window.localStorage.setItem("WCTrustedToken", res.data.express.WCTrustedToken)
return {
type: LOGIN,
payload: {}
}
}).catch(e => {
console.log(e);
return {
type: LOGIN,
payload: {}
}
});
};
server.js
const express = require('express');
const cors = require('cors');
const bodyParser = require('body-parser');
const Client = require('node-rest-client').Client;//import it here
const app = express();
const helmet = require('helmet');
const morgan = require('morgan');
// enhance your app security with Helmet
app.use(helmet());
// use bodyParser to parse application/json content-type
app.use(bodyParser.json());
// log HTTP requests
app.use(morgan('combined'));
app.use(cors());
process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = 0
app.post('/guestidentity',(req, res) => {
console.log("Hello from Server")
var client = new Client();
// direct way
client.post("https://149.129.128.3:5443/wcs/resources/store/1/guestidentity", (data, response) => {
res.send({ express: data });
});
});
app.post('/cart',(req, res) => {
console.log("Hello from Server")
var client = new Client();
// direct way
client.post("https://149.129.128.3:5443/wcs/resources/store/1/cart", (data, response) => {
res.send({ express: data });
});
});
const port = 3030;
app.listen(port, () => console.log(`Server running on port ${port}`));
I dont know where my code is getting wrong and why buffer is showing in response. Can somebody please guide me on this. Or provide me an insight how to troubleshoot this issue.
You are sending to the client an object with the form:
{
express: data
}
And when you log that on the console you see that data is an object:
{
data: [],
type: "buffer"
}
Which means that your post request inside express is returning that object.

Response is showing as buffer in reactjs app

I have created a simple react app. The problem which I'm finding is when I'm hitting the url, in the response, it is showing as buffer, which should not be the case.
My code
index.js
import axios from 'axios';
export const ADD_CART = "ADD_CART";
export const REMOVE_CART = "REMOVE_CART";
export const LOGIN = "LOGIN";
export const BASE_API_URL = "http://localhost:3030";
export function addToCart(item) {
console.log(window.localStorage.getItem('WCToken'))
console.log(window.localStorage.getItem('WCTrustedToken'))
var headers = {
'Content-Type': 'application/json',
'WCToken': window.localStorage.getItem('WCToken'),
'WCTrustedToken': window.localStorage.getItem('WCTrustedToken')
}
axios.post(BASE_API_URL + "/cart", {
orderItem: [
{
productId: item.uniqueID, //working for 12262
quantity: '1'
}
]
}, {headers: headers}).then(res => console.log(res))
.catch(err => console.log(err));
return {
type: ADD_CART,
payload: item
};
}
export function removeFromCart(cartList, id) {
return {
type: REMOVE_CART,
payload: cartList.filter(i => i.uniqueID != id)
};
}
export const login = () => {
return axios.post(BASE_API_URL + "/guestidentity", {}).then(res => {
window.localStorage.setItem("WCToken", res.data.express.WCToken)
window.localStorage.setItem("WCTrustedToken", res.data.express.WCTrustedToken)
return {
type: LOGIN,
payload: {}
}
}).catch(e => {
console.log(e);
return {
type: LOGIN,
payload: {}
}
});
};
server.js
const express = require('express');
const cors = require('cors');
const bodyParser = require('body-parser');
const Client = require('node-rest-client').Client;//import it here
const app = express();
const helmet = require('helmet');
const morgan = require('morgan');
// enhance your app security with Helmet
app.use(helmet());
// use bodyParser to parse application/json content-type
app.use(bodyParser.json());
// log HTTP requests
app.use(morgan('combined'));
app.use(cors());
process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = 0
app.post('/guestidentity',(req, res) => {
console.log("Hello from Server")
var client = new Client();
// direct way
client.post("https://149.129.128.3:5443/wcs/resources/store/1/guestidentity", (data, response) => {
res.send({ express: data });
});
});
app.post('/cart',(req, res) => {
console.log("Hello from Server")
var client = new Client();
// direct way
client.post("https://149.129.128.3:5443/wcs/resources/store/1/cart", (data, response) => {
res.send({ express: data });
});
});
const port = 3030;
app.listen(port, () => console.log(`Server running on port ${port}`));
I dont know where my code is getting wrong and why buffer is showing in response. Can somebody please guide me on this. Or provide me an insight how to troubleshoot this issue.
You might need to config your client as to parse response as JSON.
var options = {
mimetypes: {
json: ["application/json", "application/my-custom-content-type-for-json;charset=utf-8"]
}
};
var client = new Client(options);

Resources