I’m new to express about a few weeks old and i came in with the assumption that error handling will be just as easy as it is with springboot. I was wrong. So I have this express app set up in this way:
- request comes in and is intercepted by middleware like so
// auth endpoint
app.use(`/api/v1/auth`, authRouter)
- request is sent to router
// login router
router.route("/login").post(authController.handleLogin);
- The router
const handleLogin = async (req: Request, res: Response<AuthResponse>) => {
try {
const body: UserAuthenticationBody = req.body;
const isAuthenticated = await authService.authenticate(body); // Assuming authenticate returns a boolean indicating authentication status
console.log({ accessTokenSecret })
if (isAuthenticated) {
const user: UserDocument = await userService.getUserProfile(body.username);
console.log(user);
const accessToken = jwt.sign({
_id: user._id,
firstname: user.firstname,
lastname: user.lastname,
username: body.username,
}, accessTokenSecret, { expiresIn: '2h' });
console.log("Here-1")
return res.status(HttpStatusCode.BAD_REQUEST).json({
message: "Authentication successful",
status: HttpStatusCode.OK,
data: {
accessToken: accessToken
}
});
} else {
console.log("Here-2")
return res.status(401).json({
message: "Authentication failed",
status: HttpStatusCode.UNAUTHORIZED
});
}
} catch (err: any) {
console.log("Here-3")
return res.status(HttpStatusCode.INTERNAL_SERVER_ERROR).json({
message: err.message,
status: HttpStatusCode.INTERNAL_SERVER_ERROR
});
}
}
- The auth service that is being called
const authenticate = async (credentials: UserAuthenticationBody): Promise<boolean> => {
try {
const user: UserDocument | null = await User.findOne({
$or: [
{ username: credentials.username },
{ email: credentials.username }
]
});
if (!user) {
// User not found
throw new Error("user does not exist");
}
// Compare the provided password with the hashed password stored in the database
const passwordMatch = await bcrypt.compare(credentials.password, user.password);
return passwordMatch;
}
catch (error: any) {
console.log("error in auth");
throw error;
}
}
**
The problem is that when a user is not found an error is thrown and the catch clause in handle login is indeed triggered but the response status is OK despite me having specified to say it should it should be a 500 INTERNAL_SERVER_ERROR. Whats even more confusing that the message returned from the response json object is "user does not exist" **
I did check the value of the enum INTERNAL_SERVER ERROR and it is 500.
I tried using a global handler but i think i’m might have misconfigured it so i am not sure if i was doing it right.
What am i doing wrong?
this is what the rest of my server index looks like
import dotenv from "dotenv";
dotenv.config();
import express, { Request, Response, NextFunction } from "express";
import compression from "compression";
import cors from "cors";
import http from "http";
import { Server as SocketIoServer, Socket } from "socket.io";
import mongoose from "mongoose";
import { connectDB } from "./config/DbConfigurations";
import { ChatMessage } from "./api/v1/models";
// Connect to DB
connectDB();
const app = express();
const server = http.createServer(app);
const io = new SocketIoServer(server, {
cors: {
origin: "*",
methods: "*"
}
});
const port = process.env.PORT || 5000;
// middleware
app.use(express.json());
// app.use(compression());
app.use(cors());
// Make sure request has a bearer token unless its
import { authController } from "./api/v1/controllers";
// app.use(authController.authenticateToken)
import {
authRouter,
usersRouter,
groupsRouter,
journalsRouter
} from "./api/v1/routes/index";
// Error handling middleware
app.use((err: Error, req: Request, res: Response, next: NextFunction) => {
console.error(err.stack);
res.status(500).json({
message: 'Internal Server Error',
status: 500
});
});
// auth endpoint
app.use(`/api/v1/auth`, authRouter)
// users endpoint
app.use(`/api/v1/users`, usersRouter);
// journals endpoint
app.use("/api/v1/journals", journalsRouter)
// groups endpoint
app.use(`/api/v1/groups`, groupsRouter)
// Socket.IO connection handler
io.on('connection', (socket: Socket) => {
console.log('A user connected');
// Join a chat room based on the pair of users
socket.on('joinChat', (data) => {
console.log("Chat created")
const { sender, receiver } = data;
const room = [sender, receiver].sort().join('-');
socket.join(room);
});
// Handle incoming messages
socket.on('chatMessage', async (data) => {
const { sender, receiver, content } = data;
// Broadcast the message to the appropriate chat room
const chatRoom = [sender, receiver].sort().join('-');
const message = new ChatMessage({ chatRoom, sender, receiver, content, timestamp: new Date() });
await message.save();
io.to(chatRoom).emit('chatMessage', message);
});
// Handle disconnections
socket.on('disconnect', () => {
console.log('A user disconnected');
});
});
// Only if we connect to a DB should we listen to api requests
mongoose.connection.once('open', () => {
console.log("Connected to MongoDB");
server.listen(port, () => console.log("server listening on port: ", port));
})
2
Answers
Did a thorough debugging and the express app is returning the correct status. The problem was the the routes in nextjs frontend. I completely forgot about them.
this was it before
NextResponse.json defaulted to 200 because i didn't specify the status code. This is what it looks like now. Was a simple solution, just an oversight.
This is after
I don’t have enough reputation to comment your post, so instead I’m posting an answer, this did happen to me one time,
HttpStatusCode.BAD_REQUEST
was not working in my project, I don’t know why, so instead I sent 400 as an int:Try it and let me know if this did work for you, otherwise i’ll just delete my answer.