I have the following index.js for my node js. When i run my coverage, it is telling me that else path is not taken for this line: if(enableCompression) {.
My .env is setting process.env.ENABLE_COMPRESSION = 'true' by default.
How do I test that path? I tried setting process.env.ENABLE_COMPRESSION = 'false' in my test case but it does not rerun the index.js again as the server is already started.
How do i go about doing it? I am using sinon for my unit test.
index.js:
require('dotenv').config({ path: require('find-config')('.env') });
const PORT = process.env.PORT;
const ENABLE_COMPRESSION = process.env.ENABLE_COMPRESSION;
let express = require('express');
let compression = require('compression');
//logging
let log4js = require('log4js');
log4js.configure('./config/log4js.json');
//Please do not remove this line, since CLI uses this line as guidance to import new controllers
let app = express();
let enableCompression = ENABLE_COMPRESSION === "true";
if(enableCompression) {
app.use(compression());
}
app.use(log4js.connectLogger(log4js.getLogger("app"), { level: 'auto' }));
let log = log4js.getLogger("api-app");
//importing route
let routes = require('./api/rest/apiRest');
//register the route
routes(app);
//reached here throw error 404, means no routes to handle inc. request
app.use((req, res, next) => {
const error = new Error('Not found');
error.status = 404;
next(error);
});
// catch errors
app.use((error, req, res, next) => {
log.error("ERROR - " + req.url + " - " + error.message);
res.status(error.status || 500);
res.json({
error: {
message: error.message
}
});
});
//start application
module.exports = app.listen(PORT, () => {
log.info('API server started on: ' + PORT);
});
Related
different response result when I use localhost url or the heroku url
As you can see in the picture, in blue we succesfully have the result response. But not when hosted in heroku (green on picture).
Here is the response from api when I try to fetch:
response
But those params are set in .env file (backend).
Can someone help me with this ? The cors is configured on the backend, so I don't know what I can do more...
server.js:
const express = require("express");
const path = require("path");
const bodyParser = require("body-parser");
const cors = require("cors");
const dotenv = require("dotenv");
const colors = require("colors");
const dbConnect = require("./database/dbConnect");
dotenv.config();
// *** ROUTES IMPORT ***
const usersRoutes = require("./routes/users-routes");
const ovhRoutes = require("./routes/ovh-routes");
const renewDomainsRoutes = require("./routes/renew-domain-routes");
const meRoutes = require("./routes/me-routes");
const internetBsRoutes = require("./routes/internetbs-routes");
const domainsRoutes = require("./routes/domains-routes");
const orderRoutes = require("./routes/order-routes");
// execute database connection
dbConnect();
const app = express();
app.use(bodyParser.json());
app.use(cors());
/**
* ROUTES
*/
app.use("/api/users", usersRoutes); // => /api/users/...
app.use("/api/ovh", ovhRoutes); // => /api/ovh/...
app.use("/api/renew", renewDomainsRoutes);
app.use("/api/me", meRoutes);
app.use("/api/internetbs", internetBsRoutes);
app.use("/api/domains", domainsRoutes);
app.use("/api/order", orderRoutes);
app.use((req, res, next) => {
throw new HttpError("Could not find this route.", 404);
});
app.use((error, req, res, next) => {
if (res.headerSent) {
return next(error);
}
res.status(error.code || 500);
res.json({ message: error.message || "An unknown error occurred!" });
});
/**
* DEPLOYMENT
*/
if (process.env.NODE_ENV === "production") {
// Step 1:
app.use(express.static(path.resolve(__dirname, "./client/build")));
// Step 2:
app.get("*", function (request, response) {
response.sendFile(path.resolve(__dirname, "./client/build", "index.html"));
});
}
app.listen(
process.env.PORT || 5000,
console.log(`Server is running on port ${process.env.PORT}`.blue.bold)
);
The data are fetched from internet.bs API.
Thanks all!
I'm workin with a custom error response that I found in a tutorial. it's working correctly in all the node server, but in a specifies line it doesn't take the argument that specified the error code. It should return a 401 error but instead is returning me a 500 error code.
errorResponse.js
class ErrorResponse extends Error {
constructor(message, statusCode) {
super(message);
this.statusCode = statusCode;
}
}
module.exports = ErrorResponse;
The next is the porcion of code that doesn't working well.
auth.js
return next(new ErrorResponse('Unauthorized', 401))
If I use this aproach the error code is the correct.
return res.status(401).json('Unauthorized')
Edited and share server.js
require('dotenv').config({path: './config.env'});
const express = require('express');
const connectDB = require('./config/db');
const errorHandler = require('./middlewares/error');
connectDB();
const app = express();
app.use(express.json());
app.use('/api/auth', require('./routes/auth'));
app.use('/api/private', require('./routes/private'));
const PORT = process.env.PORT || 5000;
const server = app.listen(PORT, () => console.log('server on port', PORT));
process.on("unhandledRejection", (err, promise) => {
console.log(`logged Error: ${err}`)
server.close(() => process.exit(1))
});
app.use(errorHandler);
error.js
const errorHandler = (err, req, res, next) =>{
let error = { ...err };
error.message = err.message
if(err.code === 11000) {
const message = `Error de duplicaciĆ³n`;
error = new ErrorResponse(message, 400)
}
if(err.name === "ValidationError") {
const message = Object.values(err.errors).map((val) => val.message);
err = new ErrorResponse(message, 400)
}
res.status(error.status || 500 ).json({
succes: false,
error: error.message || "Error del servidor"
})
}
As stated in the title, I'm getting 'address already in use error' when trying to add socket.io to an existing express app.
It happens on every port so the only thing I can think of is it's trying to set port 8000 twice. I don't see where, however.
Here is the error in the console.
Here is my config.js
module.exports = {
PORT: process.env.PORT || 8000,
NODE_ENV: process.env.NODE_ENV || 'development',
DATABASE_URL: process.env.DATABASE_URL || 'postgresql://postgres#localhost/quik'
}
.env
NODE_ENV=development
PORT=8000
And here is my main express app. I've tried setting PORT from process.env and directly with '8000'.
require('dotenv').config()
const morgan = require('morgan')
const cors = require('cors')
const helmet = require('helmet')
const { NODE_ENV } = require('./config')
const userRouter = require('./user/user_router')
const pinsRouter = require('./pins/pins_router')
const chatRouter = require('./chat/chat_router')
const config = require('./config')
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.on('chat message', function(msg){
io.emit('chat message', msg);
});
});
http.listen(config.PORT, function(){
console.log('listening on *:8000');
});
const morganOption = (NODE_ENV === 'production')
? 'tiny'
: 'common';
app.use(morgan(morganOption))
app.use(helmet())
app.use(cors())
app.use('/user_route', userRouter)
app.use('/pins_route', pinsRouter)
app.use('/chat_route', chatRouter)
app.get('/', (req, res) => {
res.send('Hello, world!')
})
app.use(function errorHandler(error, req, res, next) {
let response
if (NODE_ENV === 'production') {
response = { error: { message: 'server error' } }
} else {
console.error(error)
response = { message: error.message, error }
}
res.status(500).json(response)
})
module.exports = app
The stack trace in the error appears like you are calling app.listen() somewhere (probably from your server.js - line 13). You need to go find that code and remove it. You only want to attempt to start your same server once and your http.listen() is already starting it once.
I am new to express and next and was trying to set 'localhost:3000/newpage' and 'localhost:3000/newpage/' as the same route however as I add a '/' at the end it shows a 404 error.
I am using "next-routes" for dynamic routing and have created routes.js file that looks like this:
const nextRoutes = require("next-routes");
const routes = (module.exports = nextRoutes());
routes.add("index", "/");
routes.add("newpage", "/newpage/:slug"); //with body parser this doesnt work
and my server.js file looks like this:
const express = require("express");
const next = require("next");
const routes = require("./routes");
const dev = process.env.NODE_ENV !== "production";
const port = process.env.PORT || 3000;
const app = next({ dev });
const handle = app.getRequestHandler();
const bodyParser = require("body-parser");
const handler = routes.getRequestHandler(app);
app
.prepare()
.then(() => {
const server = express();
server.use(bodyParser.json()); //with this dynamic routes dont work
server.use (handler); //with this dynamic routes work but / url show 404
server.get("*", (req, res) => {
server.use(handler);
if (req.url.endsWith("/")) {
req.url = req.url.slice(0, -1); // works only when using body parser
}
return handle(req, res);
});
server.listen(port, (err) => {
if (err) throw err;
console.log("> Ready on http://localhost:3000");
});
})
.catch((ex) => {
console.error(ex.stack);
process.exit(1);
});
You can modify the url that you get before passing it to Next's handling.
const next = require('next');
const express = require('express');
const routes = require('./routes');
const port = process.env.PORT || 3000;
const dev = process.env.NODE_ENV !== 'production';
const app = next({dev});
const handle = app.getRequestHandler();
// const handler = routes.getRequestHandler(app); // redundant line
app.prepare().then(() => {
const server = express();
// server.use(handler); // <-- this line is redundant since you need only one handle!
server.get('*', (req, res) => {
if (req.url.endsWith('/')) {
req.url = req.url.slice(0, -1); // remove the last slash
}
return handle(req, res);
});
server.listen(port, (err) => {
if (err) throw err;
console.log('> Ready on http://localhost:3000');
});
});
Working example: https://codesandbox.io/s/express-nextjs-react-c47y8?file=/src/index.js
Navigate to /form or /form/
I had to install the body-parser package then used body-parser. I also changed the folder structure such that I didn't have to import the routes. The final code in server.js looks like this:
const express = require("express");
const next = require("next");
const dev = process.env.NODE_ENV !== "production";
const port = process.env.PORT || 3000;
const app = next({ dev });
const handle = app.getRequestHandler();
app
.prepare()
.then(() => {
const server = express();
server.get("*", (req, res) => {
if (req.url.endsWith("/")) {
req.url = req.url.slice(0, -1); // remove the last slash
}
return handle(req, res);
});
server.listen(port, (err) => {
if (err) throw err;
console.log("> Ready on http://localhost:3000");
});
})
.catch((ex) => {
console.error(ex.stack);
process.exit(1);
});
Working locally but when running prod build, I get the 401 error. Not sure what I am missing. I am having {message: "Invalid Token"} whenever I tried to make a call to any api within the app.
Server.js
require('rootpath')();
const express = require('express');
const app = express();
const cors = require('cors');
const bodyParser = require('body-parser');
const jwt = require('./_helpers/Jwt');
const errorHandler = require('_helpers/Error-handler');
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(cors());
// use JWT auth to secure the api
app.use(jwt());
// api routes
app.use('/users', require('./users'));
// global error handler
app.use(errorHandler);
// start server
const port = process.env.NODE_ENV === 'production' ? (process.env.PORT || 80) : 4000;
if (process.env.NODE_ENV === 'production') {
app.use(express.static('../portal/dist'));
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, 'portal', 'dist', 'index.html'))
})
}
const server = app.listen(port, function () {
console.log('Server listening on port ' + port);
});
JWT.js
const expressJwt = require('express-jwt');
const config = require('../config.json');
const userService = require('../users/user.service');
module.exports = jwt;
function jwt() {
const secret = app.set('JWT_TOKEN', (process.env.JWT_TOKEN)) ;
return expressJwt({ secret }).unless({
path: [
// public routes that don't require authentication
'/users/authenticate',
'/users/register'
]
});
}
async function isRevoked(req, payload, done) {
const user = await userService.getById(payload.sub);
// revoke token if user no longer exists
if (!user) {
return done(null, true);
}
done();
};
Error handler.js
module.exports = errorHandler;
function errorHandler(err, req, res, next) {
if (typeof (err) === 'string') {
// custom application error
return res.status(400).json({ message: err });
}
if (err.name === 'ValidationError') {
// mongoose validation error
return res.status(400).json({ message: err.message });
}
if (err.name === 'UnauthorizedError') {
// jwt authentication error
return res.status(401).json({ message: 'Invalid Token' });
}
// default to 500 server error
return res.status(500).json({ message: err.message });
}
config.js
{
"secret": "Gu_*s+dF]x$E~n2B:#FwS.&Y;#M:sLMQ"
}
Added the interceptor into the app module. Not sure if I am missing something.
You need to provide isRevoked to the jwt instance
return expressJwt({ secret, isRevoked })