Answer
Whistle supports a plugin system that allows extending its functionality by developing plugins to implement custom network request processing logic.
Plugin Development Basics
1. Create Plugin Project
bashmkdir whistle-plugin-demo cd whistle-plugin-demo npm init -y
2. Create Plugin Entry File
Create index.js file:
javascriptmodule.exports = function(server, options) { // Plugin initialization logic console.log('Whistle plugin demo loaded'); // Listen to request events server.on('request', function(req, res) { // Handle request if (req.url === '/api/plugin-demo') { res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(JSON.stringify({ message: 'Hello from whistle plugin', timestamp: Date.now() })); } }); // Listen to response events server.on('response', function(req, res) { // Handle response console.log('Response:', req.url, res.statusCode); }); };
3. Configure package.json
json{ "name": "whistle-plugin-demo", "version": "1.0.0", "description": "A demo whistle plugin", "main": "index.js", "whistleConfig": { "name": "demo", "description": "Demo plugin for whistle" } }
Plugin Functionality Implementation
1. Request Interception and Modification
javascriptmodule.exports = function(server, options) { server.on('request', function(req, res) { // Modify request headers req.headers['X-Custom-Header'] = 'Custom Value'; // Log request information console.log('Request URL:', req.url); console.log('Request Method:', req.method); console.log('Request Headers:', req.headers); }); };
2. Response Interception and Modification
javascriptmodule.exports = function(server, options) { server.on('response', function(req, res) { // Modify response headers res.setHeader('X-Response-Header', 'Custom Response'); // Modify response body const originalEnd = res.end; res.end = function(chunk, encoding) { if (chunk) { const body = chunk.toString(); const modifiedBody = body.replace(/old/g, 'new'); originalEnd.call(res, modifiedBody, encoding); } else { originalEnd.call(res, chunk, encoding); } }; }); };
3. Middleware Pattern
javascriptmodule.exports = function(server, options) { // Use Express-style middleware server.use(function(req, res, next) { console.log('Middleware:', req.url); next(); }); // Route handling server.get('/api/test', function(req, res) { res.json({ success: true }); }); };
Plugin Configuration Options
javascriptmodule.exports = function(server, options) { // Get plugin configuration const customConfig = options.customConfig || {}; const port = options.port || 3000; console.log('Plugin options:', options); };
Installing and Using Plugins
1. Local Plugin Installation
bashcd whistle-plugin-demo npm link w2 install demo
2. Global Plugin Installation
bashnpm install -g whistle-plugin-demo w2 install demo
3. Use Plugin in Rules
shellwww.example.com plugin://demo
Advanced Features
1. WebSocket Support
javascriptmodule.exports = function(server, options) { server.on('upgrade', function(req, socket, head) { // Handle WebSocket upgrade requests console.log('WebSocket upgrade:', req.url); }); };
2. File System Operations
javascriptconst fs = require('fs'); const path = require('path'); module.exports = function(server, options) { server.on('request', function(req, res) { if (req.url === '/api/file') { const filePath = path.join(__dirname, 'data.json'); const data = fs.readFileSync(filePath, 'utf8'); res.end(data); } }); };
3. Database Integration
javascriptconst mysql = require('mysql'); module.exports = function(server, options) { const connection = mysql.createConnection({ host: 'localhost', user: 'root', password: 'password', database: 'test' }); server.on('request', function(req, res) { if (req.url === '/api/users') { connection.query('SELECT * FROM users', function(error, results) { if (error) { res.statusCode = 500; res.end(JSON.stringify({ error: error.message })); } else { res.end(JSON.stringify(results)); } }); } }); };
Best Practices
-
Error Handling
- Add appropriate error handling logic
- Log errors
- Provide friendly error messages
-
Performance Optimization
- Avoid blocking operations
- Use caching to reduce repeated calculations
- Use async operations appropriately
-
Security
- Validate input parameters
- Prevent injection attacks
- Encrypt sensitive information
-
Documentation and Testing
- Write clear usage documentation
- Add unit tests
- Provide example code