nodejs-express-server

安装量: 524
排名: #2066

安装

npx skills add https://github.com/aj-geddes/useful-ai-prompts --skill nodejs-express-server

Node.js Express Server Overview

Create robust Express.js applications with proper routing, middleware chains, authentication mechanisms, and database integration following industry best practices.

When to Use Building REST APIs with Node.js Implementing server-side request handling Creating middleware chains for cross-cutting concerns Managing authentication and authorization Connecting to databases from Node.js Implementing error handling and logging Instructions 1. Basic Express Setup const express = require('express'); const app = express(); const PORT = process.env.PORT || 3000;

// Middleware app.use(express.json()); app.use(express.urlencoded({ extended: true }));

// Routes app.get('/health', (req, res) => { res.json({ status: 'OK', timestamp: new Date().toISOString() }); });

// Error handling app.use((err, req, res, next) => { console.error(err.stack); res.status(err.status || 500).json({ error: err.message, requestId: req.id }); });

app.listen(PORT, () => { console.log(Server running on port ${PORT}); });

  1. Middleware Chain Implementation // Logging middleware const logger = (req, res, next) => { const start = Date.now(); res.on('finish', () => { const duration = Date.now() - start; console.log(${req.method} ${req.path} ${res.statusCode} ${duration}ms); }); next(); };

// Authentication middleware const authenticateToken = (req, res, next) => { const token = req.headers['authorization']?.split(' ')[1]; if (!token) return res.status(401).json({ error: 'No token' });

jwt.verify(token, process.env.JWT_SECRET, (err, user) => { if (err) return res.status(403).json({ error: 'Invalid token' }); req.user = user; next(); }); };

// Error catching middleware wrapper const asyncHandler = (fn) => (req, res, next) => { Promise.resolve(fn(req, res, next)).catch(next); };

app.use(logger); app.use(express.json()); app.get('/protected', authenticateToken, (req, res) => { res.json({ user: req.user }); });

  1. Database Integration (PostgreSQL with Sequelize) const { Sequelize, DataTypes } = require('sequelize');

const sequelize = new Sequelize( process.env.DB_NAME, process.env.DB_USER, process.env.DB_PASS, { host: process.env.DB_HOST, dialect: 'postgres', logging: false } );

const User = sequelize.define('User', { id: { type: DataTypes.UUID, defaultValue: DataTypes.UUIDV4, primaryKey: true }, email: { type: DataTypes.STRING, unique: true, allowNull: false }, password: DataTypes.STRING, role: { type: DataTypes.ENUM('user', 'admin'), defaultValue: 'user' } }, { timestamps: true });

// Sync database sequelize.sync({ alter: true });

  1. Authentication with JWT const jwt = require('jsonwebtoken'); const bcrypt = require('bcrypt');

const generateToken = (userId) => { return jwt.sign( { userId, iat: Math.floor(Date.now() / 1000) }, process.env.JWT_SECRET, { expiresIn: '24h' } ); };

app.post('/login', asyncHandler(async (req, res) => { const { email, password } = req.body; const user = await User.findOne({ where: { email } });

if (!user) return res.status(404).json({ error: 'User not found' });

const validPassword = await bcrypt.compare(password, user.password); if (!validPassword) return res.status(401).json({ error: 'Invalid password' });

const token = generateToken(user.id); res.json({ token, user: { id: user.id, email: user.email } }); }));

  1. RESTful Routes with CRUD Operations const userRouter = express.Router();

// GET all users (with pagination) userRouter.get('/', authenticateToken, asyncHandler(async (req, res) => { const { page = 1, limit = 20 } = req.query; const users = await User.findAndCountAll({ offset: (page - 1) * limit, limit: parseInt(limit) });

res.json({ data: users.rows, pagination: { page, limit, total: users.count } }); }));

// GET single user userRouter.get('/:id', authenticateToken, asyncHandler(async (req, res) => { const user = await User.findByPk(req.params.id); if (!user) return res.status(404).json({ error: 'Not found' }); res.json({ data: user }); }));

// POST create user userRouter.post('/', asyncHandler(async (req, res) => { const { email, password } = req.body; const hashedPassword = await bcrypt.hash(password, 10);

const user = await User.create({ email, password: hashedPassword });

res.status(201).json({ data: user }); }));

// PATCH update user userRouter.patch('/:id', authenticateToken, asyncHandler(async (req, res) => { const user = await User.findByPk(req.params.id); if (!user) return res.status(404).json({ error: 'Not found' });

await user.update(req.body, { fields: ['email', 'role'] });

res.json({ data: user }); }));

// DELETE user userRouter.delete('/:id', authenticateToken, asyncHandler(async (req, res) => { const user = await User.findByPk(req.params.id); if (!user) return res.status(404).json({ error: 'Not found' });

await user.destroy(); res.status(204).send(); }));

app.use('/api/users', userRouter);

  1. Error Handling Middleware class AppError extends Error { constructor(message, statusCode) { super(message); this.statusCode = statusCode; Error.captureStackTrace(this, this.constructor); } }

app.use((err, req, res, next) => { err.statusCode = err.statusCode || 500;

if (err.name === 'SequelizeValidationError') { return res.status(400).json({ error: 'Validation failed', details: err.errors.map(e => ({ field: e.path, message: e.message })) }); }

if (process.env.NODE_ENV === 'production') { return res.status(err.statusCode).json({ error: err.message, requestId: req.id }); }

res.status(err.statusCode).json({ error: err.message, stack: err.stack }); });

app.use((req, res) => { res.status(404).json({ error: 'Route not found' }); });

  1. Environment Configuration require('dotenv').config();

const config = { port: process.env.PORT || 3000, env: process.env.NODE_ENV || 'development', database: { url: process.env.DATABASE_URL, dialect: 'postgres' }, jwt: { secret: process.env.JWT_SECRET, expiresIn: '24h' }, cors: { origin: process.env.CORS_ORIGIN || 'http://localhost:3000' } };

module.exports = config;

Best Practices ✅ DO Use middleware for cross-cutting concerns Implement proper error handling Validate input data before processing Use async/await for async operations Implement authentication on protected routes Use environment variables for configuration Add logging and monitoring Use HTTPS in production Implement rate limiting Keep route handlers focused and small ❌ DON'T Handle errors silently Store sensitive data in code Use synchronous operations in routes Forget to validate user input Implement authentication in route handlers Use callback hell (use promises/async-await) Expose stack traces in production Trust client-side validation only Complete Example const express = require('express'); const jwt = require('jsonwebtoken'); const { Sequelize, DataTypes } = require('sequelize');

const app = express(); app.use(express.json());

const sequelize = new Sequelize('postgres://user:pass@localhost/db');

const User = sequelize.define('User', { email: DataTypes.STRING, password: DataTypes.STRING });

const authenticateToken = (req, res, next) => { const token = req.headers['authorization']?.split(' ')[1]; jwt.verify(token, 'secret', (err, user) => { if (err) return res.status(403).json({ error: 'Forbidden' }); req.user = user; next(); }); };

app.get('/users', authenticateToken, async (req, res, next) => { try { const users = await User.findAll(); res.json({ data: users }); } catch (err) { next(err); } });

app.post('/users', async (req, res, next) => { try { const user = await User.create(req.body); res.status(201).json({ data: user }); } catch (err) { next(err); } });

app.listen(3000, () => console.log('Server running on port 3000'));

返回排行榜