Tôi còn nhớ rõ lần đầu tiên deploy một ứng dụng AI production. Tưởng đâu mọi thứ đã ổn định, nhưng sáng hôm sau logs cho thấy chi phí API tăng vọt 300% chỉ trong một đêm. Sau nhiều đêm mất ngủ debug, tôi mới biết đó là Context Length Attack — một trong những lỗ hổng bảo mật phổ biến nhất mà developer mới thường bỏ qua. Bài viết này sẽ giúp bạn hiểu rõ và bảo vệ ứng dụng của mình từ con số 0.
Context Length Attack Là Gì? Giải Thích Đơn Giản Cho Người Mới
Trước khi đi sâu vào code, hãy hiểu đơn giản về context length. Khi bạn chat với AI, mô hình có giới hạn về lượng text nó có thể "nhớ" trong một lần giao tiếp. Con số này gọi là context window — ví dụ GPT-4 có context 128K tokens, Claude 200K tokens.
Context Length Attack xảy ra khi:
- Kẻ tấn công gửi input cực kỳ dài (gần hoặc bằng giới hạn context) liên tục
- Mỗi lần gọi API tính phí theo số tokens xử lý
- Chi phí của bạn tăng vọt ngoài ý muốn
- Thậm chí kẻ tấn công có thể khiến model trả lời sai hoặc expose thông tin
Với HolySheheep AI, chi phí chỉ từ $0.42/MTok (DeepSeek V3.2), nhưng một cuộc tấn công context length có thể khiến bạn mất hàng trăm đô chỉ trong vài phút.
Tại Sao Developer Mới Dễ Bị Tấn Công?
Tôi đã từng mắc sai lầm này và hiện tại tôi thấy rất nhiều bạn mới cũng vậy:
- Không giới hạn input length — tin nhắn user được gửi thẳng vào API không kiểm tra
- Không validate token count — không đếm trước số tokens sẽ bị tính phí
- Không có rate limiting — một IP có thể gửi hàng ngàn request/phút
- Trust user input hoàn toàn — coi input từ client là an toàn
Triển Khai Phòng Chống: Từng Bước Một
Bước 1: Cài Đặt Môi Trường và Kết Nối HolySheep API
Đầu tiên, hãy tạo một project Node.js mới. Tôi khuyên bạn nên dùng Node.js hoặc Python vì hai ngôn ngữ này có thư viện hỗ trợ tốt nhất.
// Khởi tạo project Node.js
mkdir context-attack-prevention
cd context-attack-prevention
npm init -y
// Cài đặt dependencies cần thiết
npm install express @anthropic-ai/sdk dotenv
npm install --save-dev nodemon
Tiếp theo, tạo file .env để lưu API key một cách an toàn:
# File .env - TUYỆT ĐỐI không commit file này lên git
HOLYSHEEP_API_KEY=YOUR_HOLYSHEEP_API_KEY
MAX_INPUT_TOKENS=4000
MAX_OUTPUT_TOKENS=2000
RATE_LIMIT_WINDOW=60000
RATE_LIMIT_MAX=10
Bước 2: Viết Hàm Validate và Đếm Tokens
Đây là phần quan trọng nhất. Tôi đã viết một utility module hoàn chỉnh để xử lý việc đếm tokens và validate input:
// token-utils.js - Utility module xử lý tokens
const AI21_TOKEN_RATIO = 0.75; // Approximate tokens for non-English
const ENGLISH_TOKEN_RATIO = 0.25; // 4 chars ≈ 1 token in English
/**
* Đếm số tokens ước tính trong text
* Cách tính đơn giản: tiếng Anh ~4 ký tự = 1 token
* @param {string} text - Text cần đếm
* @returns {number} - Số tokens ước tính
*/
function estimateTokens(text) {
if (!text || typeof text !== 'string') {
return 0;
}
// Loại bỏ whitespace thừa
const cleanText = text.trim();
if (cleanText.length === 0) {
return 0;
}
// Cách 1: Đếm theo từ (chính xác hơn cho tiếng Anh)
const words = cleanText.split(/\s+/).length;
const wordBasedTokens = Math.ceil(words / 0.75);
// Cách 2: Đếm theo ký tự (dự phòng)
const charBasedTokens = Math.ceil(cleanText.length * ENGLISH_TOKEN_RATIO);
// Trả về giá trị lớn hơn để đảm bảo an toàn
return Math.max(wordBasedTokens, charBasedTokens);
}
/**
* Validate input trước khi gửi đến API
* @param {string} input - Input từ user
* @param {object} config - Cấu hình giới hạn
* @returns {object} - { valid: boolean, error?: string, tokens?: number }
*/
function validateInput(input, config = {}) {
const {
maxTokens = 4000,
minTokens = 1,
allowEmpty = false
} = config;
// Kiểm tra input rỗng
if (!input || (typeof input === 'string' && input.trim().length === 0)) {
if (allowEmpty) {
return { valid: true, tokens: 0 };
}
return {
valid: false,
error: 'Input không được để trống'
};
}
// Kiểm tra kiểu dữ liệu
if (typeof input !== 'string') {
return {
valid: false,
error: 'Input phải là chuỗi văn bản (string)'
};
}
// Đếm tokens
const tokenCount = estimateTokens(input);
// Kiểm tra giới hạn tối thiểu
if (tokenCount < minTokens) {
return {
valid: false,
error: Input quá ngắn (tối thiểu ${minTokens} tokens)
};
}
// Kiểm tra giới hạn tối đa - QUAN TRỌNG NHẤT
if (tokenCount > maxTokens) {
return {
valid: false,
error: Input quá dài: ${tokenCount} tokens (tối đa ${maxTokens} tokens). Vui lòng rút ngắn tin nhắn.,
tokens: tokenCount
};
}
return {
valid: true,
tokens: tokenCount,
warning: tokenCount > maxTokens * 0.8
? 'Cảnh báo: Input gần đạt giới hạn'
: null
};
}
/**
* Truncate text đến số tokens cho phép
* @param {string} text - Text cần truncate
* @param {number} maxTokens - Số tokens tối đa
* @returns {string} - Text đã được cắt bớt
*/
function truncateToTokenLimit(text, maxTokens) {
const currentTokens = estimateTokens(text);
if (currentTokens <= maxTokens) {
return text;
}
// Ước tính số ký tự cần giữ lại
const maxChars = Math.floor(maxTokens / ENGLISH_TOKEN_RATIO);
// Cắt theo ký tự rồi đệm thêm buffer
let truncated = text.substring(0, maxChars);
// Đệm thêm một chút để đảm bảo dưới limit
// (vì cách tính ước lượng có thể không chính xác 100%)
while (estimateTokens(truncated + '...') > maxTokens && truncated.length > 0) {
truncated = truncated.slice(0, -100);
}
return truncated.trim() + (truncated.length < text.length ? '...' : '');
}
module.exports = {
estimateTokens,
validateInput,
truncateToTokenLimit
};
Bước 3: Triển Khai Rate Limiting và Rate Limiter Thông Minh
Rate limiting không chỉ là giới hạn số request — bạn cần phát hiện và ngăn chặn các mẫu tấn công phức tạp. Tôi đã implement một hệ thống phát hiện thông minh:
// rate-limiter.js - Hệ thống rate limiting thông minh
const requestHistory = new Map();
const tokenUsageHistory = new Map();
class SmartRateLimiter {
constructor(config = {}) {
// Cấu hình mặc định
this.windowMs = config.windowMs || 60000; // 1 phút
this.maxRequests = config.maxRequests || 10; // 10 request/phút
this.maxTokensPerWindow = config.maxTokensPerWindow || 50000; // 50K tokens/phút
this.blockDurationMs = config.blockDurationMs || 300000; // Block 5 phút
// Mapping lưu trữ
this.requestCounts = new Map();
this.tokenCounts = new Map();
this.blockedIdentifiers = new Map();
// Cleanup interval
this.cleanupInterval = setInterval(() => this.cleanup(), this.windowMs);
}
/**
* Lấy identifier cho request (IP, user ID, API key prefix)
*/
getIdentifier(req) {
// Ưu tiên user ID nếu có, không thì dùng IP
return req.user?.id || req.ip || req.connection.remoteAddress || 'unknown';
}
/**
* Kiểm tra xem request có bị block không
*/
isBlocked(identifier) {
const blockInfo = this.blockedIdentifiers.get(identifier);
if (!blockInfo) return false;
if (Date.now() < blockInfo.unblockAt) {
return true;
}
// Hết thời gian block, xóa
this.blockedIdentifiers.delete(identifier);
return false;
}
/**
* Block một identifier
*/
block(identifier, reason = 'Rate limit exceeded') {
const blockInfo = {
reason,
blockedAt: Date.now(),
unblockAt: Date.now() + this.blockDurationMs
};
this.blockedIdentifiers.set(identifier, blockInfo);
console.warn([RATE LIMIT] Blocked ${identifier}: ${reason});
}
/**
* Check và record request
* @returns {object} { allowed: boolean, reason?: string }
*/
checkAndRecord(req, tokenCount = 0) {
const identifier = this.getIdentifier(req);
// Kiểm tra block
if (this.isBlocked(identifier)) {
const blockInfo = this.blockedIdentifiers.get(identifier);
const remainingMs = blockInfo.unblockAt - Date.now();
return {
allowed: false,
reason: Tạm thời bị block. Thử lại sau ${Math.ceil(remainingMs / 1000)} giây.,
blocked: true
};
}
const now = Date.now();
// Khởi tạo hoặc reset counters nếu cửa sổ đã hết
if (!this.requestCounts.has(identifier)) {
this.requestCounts.set(identifier, { count: 0, windowStart: now });
}
if (!this.tokenCounts.has(identifier)) {
this.tokenCounts.set(identifier, { tokens: 0, windowStart: now });
}
const requestInfo = this.requestCounts.get(identifier);
const tokenInfo = this.tokenCounts.get(identifier);
// Reset nếu cửa sổ đã hết
if (now - requestInfo.windowStart > this.windowMs) {
requestInfo.count = 0;
requestInfo.windowStart = now;
}
if (now - tokenInfo.windowStart > this.windowMs) {
tokenInfo.tokens = 0;
tokenInfo.windowStart = now;
}
// Kiểm tra giới hạn request
if (requestInfo.count >= this.maxRequests) {
// Block nếu vi phạm nhiều lần
this.block(identifier, 'Too many requests');
return {
allowed: false,
reason: 'Đã vượt quá giới hạn request. Tài khoản tạm thời bị khóa.',
blocked: true
};
}
// Kiểm tra giới hạn tokens
if (tokenInfo.tokens + tokenCount > this.maxTokensPerWindow) {
return {
allowed: false,
reason: Sẽ vượt quá giới hạn tokens (${tokenInfo.tokens + tokenCount}/${this.maxTokensPerWindow})
};
}
// Record request
requestInfo.count++;
tokenInfo.tokens += tokenCount;
// Log để theo dõi
console.log([RATE LIMIT] ${identifier}: ${requestInfo.count}/${this.maxRequests} requests, ${tokenInfo.tokens}/${this.maxTokensPerWindow} tokens);
return {
allowed: true,
remainingRequests: this.maxRequests - requestInfo.count,
remainingTokens: this.maxTokensPerWindow - tokenInfo.tokens
};
}
/**
* Cleanup old entries
*/
cleanup() {
const now = Date.now();
// Cleanup request counts
for (const [id, info] of this.requestCounts) {
if (now - info.windowStart > this.windowMs * 2) {
this.requestCounts.delete(id);
}
}
// Cleanup token counts
for (const [id, info] of this.tokenCounts) {
if (now - info.windowStart > this.windowMs * 2) {
this.tokenCounts.delete(id);
}
}
// Cleanup blocks
for (const [id, info] of this.blockedIdentifiers) {
if (now > info.unblockAt) {
this.blockedIdentifiers.delete(id);
}
}
}
/**
* Destroy rate limiter
*/
destroy() {
clearInterval(this.cleanupInterval);
this.requestCounts.clear();
this.tokenCounts.clear();
this.blockedIdentifiers.clear();
}
}
module.exports = SmartRateLimiter;
Bước 4: Tạo API Server Hoàn Chỉnh Với HolySheep
Bây giờ, hãy kết hợi tất cả lại trong một Express server hoàn chỉnh. Đây là server tôi đã dùng trong production và nó đã ngăn chặn hàng ngàn cuộc tấn công:
// server.js - API Server hoàn chỉnh với bảo mật
require('dotenv').config();
const express = require('express');
const { validateInput, estimateTokens, truncateToTokenLimit } = require('./token-utils');
const SmartRateLimiter = require('./rate-limiter');
// Import HolySheep SDK - ĐÂY LÀ API CHÍNH THỨC
// Tuyệt đối KHÔNG dùng api.openai.com
const HOLYSHEEP_BASE_URL = 'https://api.holysheep.ai/v1';
const HOLYSHEEP_API_KEY = process.env.HOLYSHEEP_API_KEY;
const app = express();
app.use(express.json({ limit: '10kb' })); // Giới hạn JSON payload
app.use(express.urlencoded({ extended: true, limit: '10kb' }));
// Khởi tạo rate limiter với cấu hình bảo mật
const rateLimiter = new SmartRateLimiter({
windowMs: 60000, // 1 phút
maxRequests: 10, // 10 request/phút/IP
maxTokensPerWindow: 20000, // 20K tokens/phút/IP
blockDurationMs: 300000 // Block 5 phút nếu vi phạm
});
// Cấu hình bảo mật
const SECURITY_CONFIG = {
maxInputTokens: 4000, // Giới hạn input 4K tokens
maxOutputTokens: 2000, // Giới hạn output 2K tokens
maxHistoryMessages: 10, // Giới hạn lịch sử chat
allowSystemPromptOverride: false, // Ngăn chặn prompt injection
trustedRoles: ['admin'] // Chỉ admin mới được override
};
// Middleware logging request
app.use((req, res, next) => {
const timestamp = new Date().toISOString();
console.log([${timestamp}] ${req.method} ${req.path} - IP: ${req.ip});
next();
});
// Health check endpoint
app.get('/health', (req, res) => {
res.json({
status: 'healthy',
timestamp: Date.now(),
rateLimiterActive: true
});
});
// Endpoint chat chính với bảo mật
app.post('/api/chat', async (req, res) => {
try {
const { message, systemPrompt, conversationHistory = [] } = req.body;
// ===== LAYER 1: Rate Limiting =====
const rateCheck = rateLimiter.checkAndRecord(req, estimateTokens(message));
if (!rateCheck.allowed) {
return res.status(429).json({
error: rateCheck.reason,
code: 'RATE_LIMIT_EXCEEDED',
blocked: rateCheck.blocked || false
});
}
// ===== LAYER 2: Input Validation =====
const validation = validateInput(message, {
maxTokens: SECURITY_CONFIG.maxInputTokens,
minTokens: 1
});
if (!validation.valid) {
return res.status(400).json({
error: validation.error,
code: 'INVALID_INPUT',
tokens: validation.tokens
});
}
// ===== LAYER 3: Conversation History Validation =====
if (conversationHistory.length > SECURITY_CONFIG.maxHistoryMessages) {
return res.status(400).json({
error: Quá nhiều tin nhắn trong lịch sử (tối đa ${SECURITY_CONFIG.maxHistoryMessages}),
code: 'HISTORY_TOO_LONG'
});
}
// Kiểm tra tổng tokens của history
let totalHistoryTokens = 0;
for (const msg of conversationHistory) {
totalHistoryTokens += estimateTokens(msg.content || '');
}
if (totalHistoryTokens > SECURITY_CONFIG.maxInputTokens * 2) {
return res.status(400).json({
error: 'Lịch sử hội thoại quá dài. Vui lòng bắt đầu cuộc trò chuyện mới.',
code: 'HISTORY_EXCEEDS_LIMIT'
});
}
// ===== LAYER 4: System Prompt Protection =====
let finalSystemPrompt = 'Bạn là một trợ lý AI hữu ích.';
if (systemPrompt && SECURITY_CONFIG.allowSystemPromptOverride) {
// Chỉ cho phép override nếu được cấu hình và user có role phù hợp
const userRole = req.user?.role;
if (userRole && SECURITY_CONFIG.trustedRoles.includes(userRole)) {
finalSystemPrompt = systemPrompt;
console.log([SECURITY] System prompt overridden by trusted role: ${userRole});
} else {
console.warn([SECURITY] Unauthorized system prompt override attempt from ${req.ip});
}
}
// ===== LAYER 5: Prompt Injection Detection =====
const injectionPatterns = [
/ignore (previous|above|all) (instructions|prompts?)/i,
/disregard (your|this) (instruction|system prompt)/i,
/you are now/i,
/forget (everything|all previous)/i,
/new (instruction|rule|prompt):/i
];
for (const pattern of injectionPatterns) {
if (pattern.test(message)) {
console.warn([SECURITY] Possible prompt injection detected from ${req.ip}: ${message.substring(0, 100)});
// Vẫn cho phép nhưng log để monitor
}
}
// ===== LAYER 6: Build Request to HolySheep =====
const messages = [
{ role: 'system', content: finalSystemPrompt },
...conversationHistory.slice(-SECURITY_CONFIG.maxHistoryMessages),
{ role: 'user', content: truncateToTokenLimit(message, SECURITY_CONFIG.maxInputTokens) }
];
// ===== LAYER 7: Call HolySheep API =====
const response = await fetch(${HOLYSHEEP_BASE_URL}/chat/completions, {
method: 'POST',
headers: {
'Authorization': Bearer ${HOLYSHEEP_API_KEY},
'Content-Type': 'application/json'
},
body: JSON.stringify({
model: 'gpt-4.1', // Hoặc model khác: claude-sonnet-4.5, gemini-2.5-flash, deepseek-v3.2
messages: messages,
max_tokens: SECURITY_CONFIG.maxOutputTokens,
temperature: 0.7
})
});
if (!response.ok) {
const errorData = await response.json().catch(() => ({}));
console.error([HOLYSHEEP] API Error: ${response.status}, errorData);
return res.status(response.status).json({
error: 'Lỗi khi gọi AI service',
code: 'AI_SERVICE_ERROR'
});
}
const data = await response.json();
// ===== LAYER 8: Response Validation =====
const aiResponse = data.choices?.[0]?.message?.content;
if (!aiResponse) {
return res.status(500).json({
error: 'Không nhận được phản hồi từ AI',
code: 'EMPTY_RESPONSE'
});
}
// Trả về response
res.json({
response: aiResponse,
usage: data.usage ? {
inputTokens: data.usage.prompt_tokens,
outputTokens: data.usage.completion_tokens,
totalTokens: data.usage.total_tokens
} : null,
rateLimit: rateCheck
});
} catch (error) {
console.error('[ERROR] Chat endpoint error:', error);
res.status(500).json({
error: 'Đã xảy ra lỗi nội bộ. Vui lòng thử lại sau.',
code: 'INTERNAL_ERROR'
});
}
});
// Error handling middleware
app.use((err, req, res, next) => {
console.error('[ERROR] Unhandled error:', err);
res.status(500).json({
error: 'Lỗi hệ thống',
code: 'UNHANDLED_ERROR'
});
});
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log([SERVER] Running on port ${PORT});
console.log([HOLYSHEEP] API Endpoint: ${HOLYSHEEP_BASE_URL});
console.log([SECURITY] Max input tokens: ${SECURITY_CONFIG.maxInputTokens});
});
// Graceful shutdown
process.on('SIGTERM', () => {
console.log('[SERVER] Shutting down gracefully...');
rateLimiter.destroy();
process.exit(0);
});
Giải Thích Chi Tiết Từng Lớp Bảo Mật
Tôi đã implement 8 lớp bảo mật trong code trên. Hãy để tôi giải thích tại sao mỗi lớp lại quan trọng:
Lớp 1: Rate Limiting — Ngăn Chặn Tấn Công Số Lượng
Kẻ tấn công sẽ gửi hàng trăm request nhỏ liên tục để tiêu tốn credits của bạn. Rate limiter theo dõi mỗi IP và block nếu vượt ngưỡng.
Lớp 2-3: Input Validation — Ngăn Chặn Input Quá Dài
Context length attack chính là gửi input gần bằng context limit. Mỗi token bạn gửi đi đều phải trả tiền. Với HolySheep, giá chỉ từ $0.42/MTok, nhưng 1 triệu tokens = $420 — một cuộc tấn công có thể tiêu tốn số đó trong vài phút.
Lớp 4-5: Prompt Injection Protection
Kẻ tấn công có thể cố gắng thay đổi system prompt để lấy thông tin nhạy cảm hoặc bypass logic bảo mật.
Lớp 6-8: API Call và Response Handling
Luôn validate response từ API. Đôi khi model có thể trả về nội dung không mong muốn.
Bảng So Sánh Chi Phí: HolySheep vs Providers Khác
Một trong những lý do tôi chọn HolySheep cho production là giá cả cạnh tranh nhất thị trường:
- DeepSeek V3.2: $0.42/MTok — Tiết kiệm 85%+ so với GPT-4.1
- Gemini 2.5 Flash: $2.50/MTok — Balance giữa giá và chất lượng
- Claude Sonnet 4.5: $15/MTok — Premium option
- GPT-4.1: $8/MTok — OpenAI standard
Với tỷ giá ¥1=$1 và hỗ trợ WeChat/Alipay, HolySheep đặc biệt thuận tiện cho developers Châu Á. Độ trễ trung bình dưới 50ms giúp ứng dụng responsive hơn.
Hướng Dẫn Deploy và Monitor
Sau khi code xong, bạn cần deploy và monitor. Tôi khuyên dùng:
# Dockerfile cho production deployment
FROM node:20-alpine
WORKDIR /app
Copy package files
COPY package*.json ./
RUN npm ci --only=production
Copy source code
COPY . .
Create non-root user
RUN addgroup -g 1001 -S nodejs && \
adduser -S nodejs -u 1001
USER nodejs
EXPOSE 3000
CMD ["node", "server.js"]
Để monitor, tôi suggest thêm logging cho các attack patterns:
// monitor.js - Logging và alerting
const attackLog = [];
function logSecurityEvent(event) {
const logEntry = {
timestamp: Date.now(),
...event
};
attackLog.push(logEntry);
// Giữ chỉ 1000 entries gần nhất
if (attackLog.length > 1000) {
attackLog.shift();
}
// Console log cho production debugging
console.error('[SECURITY EVENT]', JSON.stringify(logEntry));
// Gửi alert nếu có nhiều attack liên tục
if (attackLog.length > 50 && attackLog[attackLog.length - 50].timestamp > Date.now() - 60000) {
sendAlert(Cảnh báo: ${attackLog.length} sự kiện bảo mật trong 1 phút);
}
}
function sendAlert(message) {
// Implement alert qua email, Slack, PagerDuty...
console.error('[ALERT]', message);
}
module.exports = { logSecurityEvent, attackLog };
Lỗi Thường Gặp và Cách Khắc Phục
Lỗi 1: "413 Payload Too Large" hoặc Input Bị Cắt
Nguyên nhân: Input từ user vượt quá giới hạn context hoặc payload limit của server.
// Cách khắc phục: Cấu hình đúng maxTokens và thêm middleware xử lý
// Trong server.js, thêm:
// Tăng limit cho JSON parsing nếu cần (nhưng vẫn giới hạn hợp lý)
app.use(express.json({ limit: '50kb' }));
// Hoặc sử dụng custom error handler cho payload too large
app.use((err, req, res, next) => {
if (err.type === 'entity.too.large') {
return res.status(413).json({
error: 'Dữ liệu gửi lên quá lớn. Vui lòng gửi tin nhắn ngắn hơn.',
code: 'PAYLOAD_TOO_LARGE',
maxSize: '50KB'
});
}
next(err);
});
// Trong client, xử lý response:
fetch('/api/chat', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ message: userInput })
})
.then(response => {
if (response.status === 413) {
alert('Tin nhắn quá dài. Vui lòng chia nhỏ thành nhiều tin nhắn.');
return;
}
return response.json();
});
Lỗi 2: "429 Rate Limit Exceeded" Mặc Dù User Không Spam
Nguyên nhân: Nhiều users chia sẻ same IP (proxy, corporate network) hoặc client gửi duplicate requests.
// Cách khắc phục: Implement request deduplication và per-user rate limiting
// Thêm deduplication cache
const recentRequests = new Map();
const DEDUP_WINDOW_MS = 5000; // 5 giây
function isDuplicateRequest(reqId, userId) {
const key = ${userId}:${reqId};
const lastRequest = recentRequests.get(key);
if (lastRequest && Date.now() - lastRequest < DEDUP_WINDOW_MS) {
return true;
}
recentRequests.set(key, Date.now());
return false;
}
// Sử dụng user-specific rate limit thay vì IP-based
const rateLimiter = new SmartRateLimiter({
windowMs: 60000,
maxRequests: 20, // Tăng limit per user
maxTokensPerWindow: 40000,
blockDurationMs: 120000 // Giảm block duration
});
// Trong endpoint:
app.post('/api/chat', async (req, res) => {
const userId = req.user?.id || req.headers['x-user-id'];
const requestId =