You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node.js服务器端AJAX结果缓存方案咨询:中间件及Varnish可行性

Great question! Let’s break this down into two clear parts to address both your middleware and Varnish questions:

1. Express Middleware for In-Memory AJAX Response Caching

Since you’re dealing with image data stored in MongoDB, you’ll want middleware that can handle both binary and text-based AJAX responses in memory. Here are two reliable options tailored to your use case:

  • apicache (Quick & Low-Code)
    This lightweight middleware is purpose-built for caching API/AJAX responses, uses in-memory storage by default, and requires almost zero setup to get started. It handles binary data (like your MongoDB-stored images) seamlessly, and lets you define cache durations per route.

    Example implementation:

    const apicache = require('apicache');
    const cache = apicache.middleware;
    
    // Cache image GET requests for 10 minutes
    app.get('/api/images/:imageId', cache('10 minutes'), async (req, res) => {
      const image = await Image.findById(req.params.imageId);
      res.set('Content-Type', image.contentType);
      res.send(image.data); // apicache automatically caches this binary buffer
    });
    

    You can also customize cache keys (e.g., include query params or user IDs for personalized caching) and add X-Cache headers to debug hit/miss rates.

  • Custom Middleware with lru-cache (Fine-Grained Control)
    If you need tighter control over cache limits, eviction policies, or custom invalidation logic, use lru-cache (a popular Least Recently Used cache library) to build a custom middleware. This is ideal if you want to cap memory usage or add rules to invalidate cache when images are updated in MongoDB.

    Example:

    const LRU = require('lru-cache');
    // Configure cache: max 200 entries, 10-minute TTL
    const imageCache = new LRU({ max: 200, ttl: 600000 });
    
    const cacheMiddleware = (req, res, next) => {
      const cacheKey = `${req.method}-${req.originalUrl}`; // Unique key for each request
      const cachedData = imageCache.get(cacheKey);
    
      if (cachedData) {
        res.set('X-Cache', 'HIT');
        res.set('Content-Type', cachedData.contentType);
        return res.send(cachedData.buffer);
      }
    
      // Override res.send to cache the response before sending it
      const originalSend = res.send;
      res.send = function(data) {
        imageCache.set(cacheKey, {
          buffer: data,
          contentType: res.get('Content-Type')
        });
        res.set('X-Cache', 'MISS');
        originalSend.call(this, data);
      };
    
      next();
    };
    
    // Apply middleware to your image route
    app.get('/api/images/:imageId', cacheMiddleware, async (req, res) => {
      const image = await Image.findById(req.params.imageId);
      res.set('Content-Type', image.contentType);
      res.send(image.data);
    });
    
2. Does Varnish Support Caching AJAX Results?

Absolutely! Varnish can cache AJAX responses, but you’ll need to adjust its default configuration because AJAX requests often include headers like X-Requested-With: XMLHttpRequest that Varnish doesn’t cache by default.

Key Configuration Steps:

  1. Allow Caching for AJAX Headers: Update your VCL (Varnish Configuration Language) to recognize and cache requests with the X-Requested-With header.
  2. Ensure Valid Cache Headers: Make sure your Express backend returns Cache-Control headers (e.g., public, max-age=600) to tell Varnish how long to keep the cached response.

Example VCL snippet to enable AJAX caching:

sub vcl_recv {
  // Cache GET AJAX requests (adjust if you use POST for AJAX)
  if (req.method == "GET" && req.http.X-Requested-With == "XMLHttpRequest") {
    // Remove cookies only if responses are not user-specific
    // Keep cookies if you need per-user cached versions
    unset req.http.Cookie;
    return (hash);
  }
}

sub vcl_backend_response {
  // Enforce caching for AJAX responses if backend doesn't set headers
  if (bereq.http.X-Requested-With == "XMLHttpRequest") {
    set beresp.ttl = 10m;
    set beresp.http.Cache-Control = "public, max-age=600";
    set beresp.http.X-Varnish-Cache = "Cached";
  }
}

Important Notes:

  • If your AJAX responses are user-specific (e.g., authenticated users get unique images), don’t unset the Cookie header—Varnish will automatically use the cookie as part of the cache key to store separate versions for each user.
  • For compressed responses, add Vary: Accept-Encoding to your backend headers so Varnish caches both gzipped and uncompressed versions.

内容的提问来源于stack exchange,提问作者Chong Lip Phang

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 08:44:26