NodeJS REST API自定义404响应:替换默认Cannot Get提示
Hey there! Great job getting started with Node.js, Express, and building your REST API. Let's tackle that custom 404 response first, then share some helpful tips for your upcoming CRUD endpoints.
How to Add Custom 404 JSON Response
Express processes middleware and routes in the exact order you define them. To catch all undefined routes, you just need to add a catch-all middleware at the very end of your route definitions (after all your API endpoints like /api/domains.json).
Here's the snippet you need to add:
// Catch all undefined routes and return custom 404 JSON app.use((req, res) => { res.status(404).json({ code: 404, message: "Not found" }); });
Why This Works
By placing this middleware last, Express will only trigger it if none of your defined routes match the incoming request. This completely replaces the default "Cannot GET /ROUTE" message with your clean, custom JSON response.
Updated Full Code (With 404 Fix & Improvements)
Here's your code with the 404 handler added, plus a few small tweaks to make your server more robust:
var http = require("http"); var express = require('express'); var app = express(); var mysql = require('mysql'); var bodyParser = require('body-parser'); var connection = mysql.createConnection({ host : 'localhost', user : 'root', password : 'root', database : 'restapi', port : '8889' }); connection.connect(function(err) { if (err) { console.error('Failed to connect to database:', err); process.exit(1); // Exit gracefully if DB connection fails } console.log('Congrats you are connected') }); app.use( bodyParser.json() ); // Support JSON-encoded bodies app.use(bodyParser.urlencoded({ // Support URL-encoded bodies extended: true })); var server = app.listen(3000, "127.0.0.1", function () { var host = server.address().address var port = server.address().port console.log("Example app listening at http://%s:%s", host, port) }); app.all('/*', function(req, res, next) { // CORS headers res.header("Access-Control-Allow-Origin", "*"); // Tip: Restrict this to your frontend domain later! res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS'); res.header('Access-Control-Allow-Headers', 'Content-type,Accept,X-Access-Token,X-Key'); if (req.method == 'OPTIONS') { res.status(200).end(); } else { next(); } }); // GET Domains app.get('/api/domains.json', function (req, res, next) { connection.query('select * from domain', function (error, results, fields) { if (error) { return next(error); // Pass errors to global handler instead of crashing the server } if (results.length === 0) { // More reliable check for empty results res.status(404).json({ code: 404, message: "Not found" }); } else { res.json({ code: 200, message: 'success', datas: results }); } }); }); // Catch all undefined routes app.use((req, res) => { res.status(404).json({ code: 404, message: "Not found" }); }); // Global error handler (catches DB errors and other server issues) app.use((err, req, res, next) => { console.error('Server error:', err); res.status(500).json({ code: 500, message: "Internal server error" }); });
Key Improvements in the Updated Code:
- Safer DB Connection Handling: Instead of throwing an error on connection failure, we log it and exit gracefully to avoid hanging processes.
- Better Error Propagation: In the GET route, we pass database errors to
next()instead of throwing, which lets the global error handler handle them without crashing the server. - More Accurate Empty Result Check: Checking
results.length === 0works reliably even if the query returns an empty array, unlike checkingresults[0] === undefined.
Tips for Your Upcoming CRUD Endpoints
As you add POST, PUT, and DELETE endpoints, here are some best practices to keep your code clean and secure:
- Use Express Routers: Split your routes into separate files (e.g.,
routes/domains.js) to keep your main app file organized. Example:
Then import it in your main app:// routes/domains.js const express = require('express'); const router = express.Router(); router.get('/domains.json', (req, res, next) => { /* ... */ }); router.post('/domains.json', (req, res, next) => { /* ... */ }); // Add PUT/DELETE endpoints here module.exports = router;app.use('/api', require('./routes/domains')); - Validate Request Data: Use libraries like
express-validatorto validate incoming JSON/URL-encoded data before hitting the database (prevents bad data from being saved). - Avoid SQL Injection: Always use parameterized queries with
mysql(e.g.,connection.query('SELECT * FROM domain WHERE id = ?', [req.params.id], ...)). - Clean Up Connections: When your server shuts down, close the MySQL connection to avoid resource leaks.
内容的提问来源于stack exchange,提问作者Yns_D

