Skip to content

ronalddddd/proxy-cache

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

72 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Build Status Code Climate

Proxy Cache

Programmable reverse caching proxy. Use as a stand-alone app or an express middleware. Comes with TTL and MongoDB adapters.

Features

  • Request pooling: multiple requests with a cache miss will be pooled, i.e. only one request will be made upstream
  • Fast in memory caching -- adapter cache are used as a second layer
  • Extensible Adapter API
  • Express middleware compatible
  • Gzip compression when using the stand-alone server
  • Stale-caching: serve stale cache while updating the cache object asynchronously in the background
  • Remove cache objects (largest and least hit ones first) after a set memory threshold (defaults to 2GiB)

Install

npm install rn-proxy-cache

Usage

Stand-alone server with simple global-TTL caching

Note the --spoof-host-header option rewrites your "Host" header value to match the target host value. You probably won't use this in a normal proxy-cache setup unless you're running some sort of mirror site.

npm start \
--target-host="highscalability.com:80" \
--proxy-port=8080 \
--spoof-host-header \
--ttl=30000
  • --target-host="www.google.com:80": your upstream host.
  • --proxy-port=8080: the port for this proxy server.
  • --spoof-host-header: use this to rewrite Host header value to the --target-host value. Only useful if your upstream application needs to use the domain specified by the --target-host value.
  • --ttl=30000: TTL caching in milliseconds, defaults to 600000ms (10 minutes)

Stand-alone server using MongoDB as a global cache expire schedule and persistent cache storage

npm start \
--target-host="www.apple.com:80" \
--proxy-port=8080 \
--spoof-host-header \
--mongodb-url="mongodb://localhost:27017/test" \
--use-external-cache \
--watch-interval=60000 \
  • --mongodb-url: Supply this to use the MongoDB adapter. Will watch the PublishSchedule collection that contains documents with the publish_date ISO Date string field and clears cache accordingly.
  • --use-external-cache: Enables storing cached objects in the external storage interface provided by the adapter, useful if you run multiple instances of the proxy or surviving restarts
  • --watch-interval: How long between each time it checks the PublishSchedule collection. Defaults to 30sec.

Additional parameters when running as a stand-alone server

  • --mem-usage: Shows memory usage info every 30sec.
  • --verbose-log: Verbose logging for debugging.

Express middleware

var ProxyCache = require('rn-proxy-cache'),
    express = require('express'),
    app = express();

var proxyCache = new ProxyCache({
    targetHost: "highscalability.com:80",
    spoofHostHeader: true // again, doubt you need to enable this if you're running your own site
});

app.use(proxyCache.createMiddleware());

proxyCache.ready.then(function() {
    app.listen(8181, function () {
        console.log("ProxyCache server is ready");
    });
});

Use new ProxyCache(options) to create a new instance of the proxy cache. options are:

  • targetHost: the upstream host to proxy to. Defaults to "localhost:80"
  • httpProtocol: "http" or "https", defaults to "http".
  • Adapter: the cache adapter module to use, see lib/adapters for examples. Defaults to the TTL adapter.
  • adapterOptions: adapters are passed these options when constructed, i.e. new Adapter(proxyCacheInstance, options)
  • httpProxyOptions: upstream proxy requests are made using http-proxy, these options are passed to the httpProxy.createProxyServer() method.
  • allowStaleCache: allow stale cache to be served while asynchronously making a request upstream to update the cache object.
  • spoofHostHeader: rewrite the upstream request header Host value to match targetHost
  • memGiBThreshold: the maximum memory threshold before cleaning up some less hit cache objects to free memory

Optionally set req.shouldCache to let ProxyCache know if a request should be cached.

Creating a custom Adapter

To implement a custom Adapter, create a node module with the following constructor interface: CacheAdapter(proxyCache, options){ ... }.

There are 2 things you can do with a custom adapter:

  1. Decide when to invalidate the memory cache by calling proxyCache.clearAll()
  2. Implement external cache storage with the following interfaces as CacheAdapter's prototype methods: setCache(key, value), getCache(key), clearCache(), all returning a promise that resolves when the task is completed.

Finally if you need to init the adapter asynchronously, you can set a .ready promise property on the adapter instance and resolve when ready.

Notes

  • "host-rewrite" option is disabled for redirects.
  • Response status codes from upstream that's greater than 200 are not cached.
  • Empty response bodies are not cached.
  • mobile-detect is used to generate part of the cache key prefix: phone or not_phone. This should be the most common case of upstream response variations. Ideally, we should use Vary headers provided by upstream responses.

TODOs

Pull requests are welcome :)

  • Expose ProxyCache instance in express routes -- http.ClientRequest#proxyCache
  • Express middleware API, e.g. proxyCache.createMiddleware(app, /\/api\/.*/, { targetProtocol: 'https', targetHost: 'localhost:8081', rewriteUrl: rewriteUrlMethod })
  • When targetHost is not provided, set upstream to the local response stream (aka http.ServerResponse object in the express route), instead of the proxy response generate with http-proxy
  • Support ETag for browsers and Vary for upstream response variations. See RFC2616 for more.
  • Dockerfile, systemd unitfile templates, and other proc management files
  • Add feature to regenerate cache (precache), generating the ones with the most cache hits first
  • Add option to override ProxyCache.prototype.getCacheKey method
  • Handle very large responses?

About

Programmable reverse caching proxy. Optional MongoDB cache layer.

Resources

License

Stars

Watchers

Forks

Packages

No packages published