Tài liệu

Tham chiếu Context - Helpers và bộ nhớ đệm

Tham chiếu Context - Helpers và bộ nhớ đệm Các hàm tiện ích cho tác vụ phổ biến và thao tác cache phân tán. Hàm hỗ trợ Các hàm tiện ích cho tác vụ phổ biến. Mọi hàm hỗ trợ đều cần await . Tạo token JWT const token = await $ctx.$helpers.$jwt(payload, expiration); // Example const

Tham chiếu Context - Helpers và bộ nhớ đệm

Các hàm tiện ích cho tác vụ phổ biến và thao tác cache phân tán.

Hàm hỗ trợ

Các hàm tiện ích cho tác vụ phổ biến. Mọi hàm hỗ trợ đều cần await.

Tạo token JWT

const token = await $ctx.$helpers.$jwt(payload, expiration);

// Example
const token = await $ctx.$helpers.$jwt(
  { userId: 123, email: '[email protected]' },
  '7d'  // Expires in 7 days
);

Định dạng thời hạn: - - 15 phút. - '1h'- 1 giờ - '1d'- 1 ngày - 7 ngày - 30 Ngày

Băm mật khẩu

// Hash password
const hash = await $ctx.$helpers.$bcrypt.hash(plainPassword);

// Verify password
const isValid = await $ctx.$helpers.$bcrypt.compare(plainPassword, hashedPassword);

// Example
const hashedPassword = await $ctx.$helpers.$bcrypt.hash('myPassword123');
const isValid = await $ctx.$helpers.$bcrypt.compare('myPassword123', hashedPassword);

Tự tạo slug

Tạo slug thân thiện với URL từ văn bản.

const slug = $ctx.$helpers.autoSlug(text);

// Example
const slug = $ctx.$helpers.autoSlug('My Product Name');
// Result: 'my-product-name'

Hàm hỗ trợ crypto

Sử dụng$ctx.$helpers.$cryptocho các trình trợ giúp mật mã bị chặn bên trong móc, trình xử lý, luồng và tập lệnh websocket.

const id = $ctx.$helpers.$crypto.randomUUID();
const token = $ctx.$helpers.$crypto.randomBytes(32, 'base64url');
const digest = $ctx.$helpers.$crypto.sha256('payload');
const signature = $ctx.$helpers.$crypto.hmacSha256('payload', 'shared-secret');

Các mã hóa được hỗ trợ chorandomBytes, 1 vàhmacSha256hex, 4 vàbase64url.randomBytesđược giới hạn ở 4096 byte.

Tạo khóa SSH với cùng một trình trợ giúp tiền điện tử:

const keyPair = await $ctx.$helpers.$crypto.generateSshKeyPair('[email protected]');

// keyPair.publicKey is OpenSSH format.
// keyPair.privateKey is RSA PKCS#1 PEM.

Không sử dụng legacy$ctx.$helpers.$sshhoặc trình trợ giúp mã hóa thủ công trong các tập lệnh mới. Các giá trị cơ sở dữ liệu cần mã hóa ở phần còn lại nên được lưu trữ trong các cột được đánh dấuisEncrypted=true; các tập lệnh đọc và ghi các giá trị văn bản thuần túy.

Hàm sleep

Tạm dừng một tập lệnh động trong một khoảng thời gian giới hạn. Thời gian chạy kẹp độ trễ từ 0 đến 30000 mili giây.

await $ctx.$helpers.$sleep(1000);

Hàm hỗ trợ storage

Tải tệp lên storage.

const fileResult = await $ctx.$storage.$upload({
  originalname: 'image.jpg',
  filename: 'custom-filename.jpg',
  mimetype: 'image/jpeg',
  buffer: fileBuffer,
  size: 1024000,
  folder: 123,  // Optional: folder ID
  storageConfig: 1,  // Optional: storage config ID
  title: 'My Image',  // Optional
  description: 'Image description'  // Optional
});

Hàm cập nhật tệp

Cập nhật tệp đã có.

await $ctx.$storage.$update(fileId, {
  buffer: newFileBuffer,
  originalname: 'new-name.jpg',
  mimetype: 'image/jpeg',
  folder: 456,
  title: 'Updated Title'
});

Hàm xóa tệp

Xóa tệp.

await $ctx.$storage.$delete(fileId);

Đăng ký một đối tượng đã tồn tại trong phần phụ trợ lưu trữ được định cấu hình mà không cần tải lên byte:

await $ctx.$storage.$registerFile({
  filename: 'backup.sql.gz',
  mimetype: 'application/gzip',
  location: 'backups/project-1/backup.sql.gz',
  size: 1024,
  storageConfig: 1,
});

Giới hạn tần suất

Bảo vệ các tuyến API của bạn với giới hạn tốc độ linh hoạt bằng cách sử dụng thuật toán cửa sổ trượt Redis.

const result = await $ctx.$helpers.$rateLimit.byIp({
  maxRequests: 100,
  perSeconds: 60
});

if (!result.allowed) {
  $ctx.$throw['429'](`Rate limit exceeded. Try again in ${result.retryAfter}s`);
}

Mẫu giới hạn tần suất

Phương thức Định dạng khóa Mô tả
byIp(options) ip:{ip}:{route} Giới hạn tốc độ theo IP máy khách trên mỗi tuyến đường
0 user:{userId}:{route} Giới hạn mức giá theo người dùng được xác thực trên mỗi tuyến đường
0 route:{route} Giới hạn tỷ lệ trên toàn cầu cho mỗi tuyến đường (tất cả người dùng/giới hạn chia sẻ IP)
byIpGlobal(options) ip:{ip} Giới hạn tốc độ theo IP trên tất cả các tuyến đường
byUserGlobal(options) user:{userId} Giới hạn mức giá của người dùng trên tất cả các tuyến đường
check(key, options) Khóa tùy chỉnh Giới hạn tốc độ với khóa tùy chỉnh
reset(key) - Đặt lại giới hạn tốc độ cho một khóa
status(key, options) - Kiểm tra trạng thái giới hạn tốc độ mà không tăng

Tùy chọn

{
  maxRequests: 100,  // Maximum requests allowed in the window
  perSeconds: 60     // Time window in seconds
}

Đối tượng kết quả

{
  allowed: boolean,     // Whether the request is allowed
  remaining: number,    // Remaining requests in window
  resetAt: number,      // Unix timestamp when window resets
  retryAfter: number,   // Seconds to wait before retry (0 if allowed)
  limit: number,        // The max requests limit
  window: number        // The window in seconds
}

Ví dụ

Số lần đăng nhập giới hạn tốc độ theo IP:

// In preHook for POST /auth/login
const result = await $ctx.$helpers.$rateLimit.byIp({
  maxRequests: 5,
  perSeconds: 60
});

if (!result.allowed) {
  $ctx.$throw['429'](`Too many login attempts. Try again in ${result.retryAfter}s`);
}

** API giới hạn tỷ lệ theo người dùng:**

// In preHook for API routes
const result = await $ctx.$helpers.$rateLimit.byUser({
  maxRequests: 1000,
  perSeconds: 3600  // 1 hour
});

if (!result.allowed) {
  $ctx.$throw['429'](`API rate limit exceeded. Try again in ${result.retryAfter}s`);
}

Bỏ qua giới hạn tỷ lệ cho quản trị viên:

if (!$ctx.$user?.isRootAdmin) {
  const result = await $ctx.$helpers.$rateLimit.byIp({
    maxRequests: 100,
    perSeconds: 60
  });

  if (!result.allowed) {
    $ctx.$throw['429']('Rate limit exceeded');
  }
}

** Khóa tùy chỉnh cho tài nguyên cụ thể:**

const resourceId = $ctx.$params.id;
const result = await $ctx.$helpers.$rateLimit.check(
  `resource:${resourceId}:${$ctx.$user?.id || $ctx.$req.ip}`,
  { maxRequests: 10, perSeconds: 60 }
);

if (!result.allowed) {
  $ctx.$throw['429']('Too many requests to this resource');
}

Kiểm tra trạng thái không tăng:

// Check if rate limited without counting the request
const status = await $ctx.$helpers.$rateLimit.status(
  `ip:${$ctx.$req.ip}:/api/expensive`,
  { maxRequests: 5, perSeconds: 3600 }
);

if (!status.allowed) {
  $ctx.$throw['429']('Daily limit reached');
}

Đặt lại giới hạn tỷ lệ sau khi hành động thành công:

// In postHook after successful action
await $ctx.$helpers.$rateLimit.reset(`ip:${$ctx.$req.ip}:/auth/forgot-password`);

Cache

Các thao tác user cache và khóa phân tán. Mọi hàm cache đều cần await.

$ctx.$cachelưu trữ dữ liệu ứng dụng được tạo bởi trình xử lý, móc, luồng, tập lệnh websocket và@CACHEmacro. Sử dụng các khóa logic nhưuser:123; không bao gồmNODE_NAME, 4 hoặc bất kỳ tiền tố không gian tên Redis nào. Khi bộ nhớ cache người dùng Redis được bật, Enfyra lưu trữ các giá trị đó trong không gian tên ứng dụng hiện tại làNODE_NAME:user_cache:*.

Bộ nhớ cache của người dùng có phân bổ mềm được kiểm soát bởiREDIS_USER_CACHE_LIMIT_MB(mặc định30). Nếu phân bổ vượt quá, Enfyra chỉ loại bỏ các khóa bộ nhớ cache người dùng ít được sử dụng gần đây nhất. Các phím System Redis như ảnh chụp nhanh bộ nhớ cache thời gian chạy, hàng đợi BullMQ, Socket.IO, đo từ xa thời gian chạy và khóa không được tính hoặc loại bỏ bởi hạn ngạch này.

Lấy giá trị cache

const cachedValue = await $ctx.$cache.get(key);

// Example
const user = await $ctx.$cache.get('user:123');

Đặt giá trị cache

// Set with TTL (time-to-live in milliseconds)
await $ctx.$cache.set(key, value, ttlMs);

// Example - cache for 5 minutes
await $ctx.$cache.set('user:123', userData, 300000);

// Set without expiration
await $ctx.$cache.setNoExpire(key, value);

Ưu tiênset(key, value, ttlMs)với TTL cho dữ liệu hoạt động.setNoExpiregiữ một giá trị liên tục từ góc độ TTL, nhưng nó vẫn có thể bị trục xuất nếu vượt quá phân bổ bộ đệm người dùng.

Khóa phân tán

Nhận và nhả khóa cho các thao tác quan trọng.

// Acquire lock
const lockAcquired = await $ctx.$cache.acquire(key, value, ttlMs);

// Release lock
const released = await $ctx.$cache.release(key, value);

// Example
const lockKey = `user-lock:${userId}`;
const lockValue = $ctx.$user.id;
const acquired = await $ctx.$cache.acquire(lockKey, lockValue, 10000); // 10 seconds

if (acquired) {
  try {
    // Critical operation here
  } finally {
    await $ctx.$cache.release(lockKey, lockValue);
  }
}

Kiểm tra cache tồn tại

const exists = await $ctx.$cache.exists(key, value);

// Example
const lockExists = await $ctx.$cache.exists('user-lock:123', 'user-456');

Xóa khóa cache

await $ctx.$cache.deleteKey(key);

// Example
await $ctx.$cache.deleteKey('user:123');

Tiếp theo