pax_global_header00006660000000000000000000000064146037235630014523gustar00rootroot0000000000000052 comment=5261d91b210735a5a79367ff9faebde2dea28788 rack-cache-1.17.0/000077500000000000000000000000001460372356300135725ustar00rootroot00000000000000rack-cache-1.17.0/.github/000077500000000000000000000000001460372356300151325ustar00rootroot00000000000000rack-cache-1.17.0/.github/workflows/000077500000000000000000000000001460372356300171675ustar00rootroot00000000000000rack-cache-1.17.0/.github/workflows/development.yml000066400000000000000000000024201460372356300222320ustar00rootroot00000000000000name: Development on: [push, pull_request] jobs: test: name: ${{matrix.ruby}} on ${{matrix.os}} (${{matrix.gemfile}}) runs-on: ${{matrix.os}}-latest continue-on-error: ${{matrix.experimental}} strategy: matrix: os: - ubuntu - macos ruby: - "2.7" - "3.0" - "3.1" - "3.2" - "3.3" gemfile: - gems/rack_v2.rb - gems/rack_v2-1.rb - gems/rack_v3.rb experimental: [false] include: - os: ubuntu ruby: truffleruby experimental: true - os: ubuntu ruby: jruby experimental: true - os: ubuntu ruby: head experimental: true env: BUNDLE_GEMFILE: ${{matrix.gemfile}} steps: - uses: actions/checkout@v3 - name: Installing packages (ubuntu) if: matrix.os == 'ubuntu' run: sudo apt-get install libmemcached-dev - name: Installing packages (macos) if: matrix.os == 'macos' run: brew install libmemcached - uses: ruby/setup-ruby@v1 with: ruby-version: ${{matrix.ruby}} bundler-cache: true - run: bundle exec rake rack-cache-1.17.0/.github/workflows/gh-pages.yml000066400000000000000000000012511460372356300214040ustar00rootroot00000000000000name: Github Pages on: push: branches: - main permissions: contents: write jobs: build-and-deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - uses: ruby/setup-ruby@v1 with: ruby-version: '2.7' bundler-cache: true # runs 'bundle install' and caches installed gems automatically - name: Install and Build 🔧 run: bundle exec rake doc:gh-pages - name: Deploy 🚀 uses: JamesIves/github-pages-deploy-action@v4.3.3 with: branch: gh-pages # The branch the action should deploy to. folder: doc/gh-pages # The folder the action should deploy. rack-cache-1.17.0/.gitignore000066400000000000000000000003171460372356300155630ustar00rootroot00000000000000\[. tags .vimrc /dist /coverage /doc/api /doc/*.png /doc/*.pdf /doc/*.svg /doc/config /doc/configuration.html /doc/index.html /doc/license.html /doc/storage.html /doc/faq.html /doc/gh-pages gems.locked /pkg rack-cache-1.17.0/CHANGES000066400000000000000000000274451460372356300146010ustar00rootroot00000000000000## 1.13.0 * Support lowercase Vary and Age headers ## 1.12.0 * Add a fault_tolerant flag to fail-over to stale cache ## 1.11.1 * when ignoring parts of the query, remove query in key when all params are ignored ## 1.11.0 * Add a proc to allow ignoring parts of the query string in the key ## 1.10.0 * Pass Options To Underlying Storage Driver * bump required ruby version to 2.3 ## 1.9.0 * make purge not raise when not implemented ## 1.8.0 * Meta stores will purge keys when no entity store entries are found ## 1.7.2 * Fix key generation for requests with no query strings ## 1.7.0 * Meta stores now receive a third ttl argument to write when use_native_ttl is used. ## 1.6.1 * Revert 'No longer read responses from cache when we already have them' ## 1.6.0 * Noop backend * No longer read responses from cache when we already have them * renamed files from entitystore -> entity_store (metastore/cachecontrol/appengine) and added warns for old ones ## 1.5.1 * fix key generation for query strings that include encoded equals ## 1.5.0 * only catch StandardError and not Exception ## 1.4.3 * After overriding the REQUEST_METHOD, store the original request method in "rack.methodoverride.original_method" ## 1.4.1 * Ignore invalid Expires date as per RFC ## 1.4.0 * Not invalidating the cache for preflight CORS request ## 1.3.1 / October 2015 * Support Ruby 1.9 ## 1.3 / Octorber 2015 * Ruby 2.0 only * Gracefully degrade when cache store goes offline * allow_reload/revalidate is not enabled by default * Make Rack::Cache multithread friendly ## 1.2 / March 2012 * Fix a cookie leak vulnerability effecting large numbers of Rails 3.x installs: https://github.com/rtomayko/rack-cache/pull/52 * Never 304 on PUT or POST requests. * Misc bundler and test tooling fixes. ## 1.1 / September 2011 * Allow (INM/IMS) validation requests through to backend on miss. Makes it possible to use validation for private / uncacheable responses. A number of people using Rails's stale?() helper reported that their validation logic was never kicking in. * Add rack env rack-cache.force-pass option to bypass rack-cache on per request basis * Fix an issue with memcache namespace not being set when using the :namespace option instead of :prefix_key. * Fix test failures due to MockResponse changes in recent Rack version (issue #34) ## 1.0.3 / August 2011 * Fix bug passing options to memcached and dalli * Document cache_key ## 1.0.1 / April 2011 * Added lib/rack-cache.rb to match package name for auto-requiring machinery. * Fixed a number of issues caused by Rack::Cache not closing the body received from the application. Rack::Lock and other middleware use body.close to signal the true end of request processing so failure to call this method can result in strange issues (e.g., "ThreadError: deadlock; recursive locking") * Fixed a bug where Rack::Cache would blow up writing the rack env to the meta store when the env contained an all uppercase key whose value wasn't marshalable. Passenger and some other stuff write such keys apparently. * The test suite has moved from test-spec to bacon. This is a short term solution to the problem of not being able to run tests under Ruby 1.9.x. The test suite will be moved to basic Test::Unit style sometime in the future. ## 1.0 / December 2010 * Rack::Cache is 1.0 and will now maintain semantic versioning * Add Dalli memcache client support and removed support for the unmaintained memcache-client library. You will need to move your apps to Dalli before upgrading rack-cache to 1.0. ## 0.5.3 / September 2010 * A matching If-Modified-Since is ignored if an If-None-Match is also provided and doesn't match. This is in line with RFC 2616. * Converts string status codes to integers before returns to workaround bad behaving rack middleware and apps. * Misc doc clean up. ## 0.5.2 / September 2009 * Exceptions raised from the metastore are not fatal. This makes a lot of sense in most cases because its okay for the cache to be down - it shouldn't blow up your app. ## 0.5.1 / June 2009 * Added support for memcached clusters and other advanced configuration provided by the memcache-client and memcached libraries. The "metastore" and "entitystore" options can now be set to a MemCache object or Memcached object: memcache = MemCache.new(['127.1.1.1', '127.1.1.2'], :namespace => "/foo") use Rack::Cache, :metastore => memcache, :entitystore => memcache * Fix "memcached://" metastore URL handling. The "memcached" variation blew up, the "memcache" version was fine. ## 0.5.0 / May 2009 * Added meta and entity store implementations based on the memcache-client library. These are the default unless the memcached library has already been required. * The "allow_reload" and "allow_revalidate" options now default to false instead of true. This means we break with RFC 2616 out of the box but this is the expected configuration in a huge majority of gateway cache scenarios. See the docs on configuration options for more information on these options: http://tomayko.com/src/rack-cache/configuration * Added Google AppEngine memcache entity store and metastore implementations. To use GAE's memcache with rack-cache, set the "metastore" and "entitystore" options as follows: use Rack::Cache, :metastore => 'gae://cache-meta', :entitystore => 'gae://cache-body' The 'cache-meta' and 'cache-body' parts are memcache namespace prefixes and should be set to different values. ## 0.4.0 / March 2009 * Ruby 1.9.1 / Rack 1.0 compatible. * Invalidate cache entries that match the request URL on non-GET/HEAD requests. i.e., POST, PUT, DELETE cause matching cache entries to be invalidated. The cache entry is validated with the backend using a conditional GET the next time it's requested. * Implement "Cache-Control: max-age=N" request directive by forcing validation when the max-age provided exceeds the age of the cache entry. This can be disabled by setting the "allow_revalidate" option to false. * Properly implement "Cache-Control: no-cache" request directive by performing a full reload. RFC 2616 states that when "no-cache" is present in the request, the cache MUST NOT serve a stored response even after successful validation. This is slightly different from the "no-cache" directive in responses, which indicates that the cache must first validate its entry with the origin. Previously, we implemented "no-cache" on requests by passing so no new cache entry would be stored based on the response. Now we treat it as a forced miss and enter the response into the cache if it's cacheable. This can be disabled by setting the "allow_reload" option to false. * Assume identical semantics for the "Pragma: no-cache" request header as the "Cache-Control: no-cache" directive described above. * Less crazy logging. When the verbose option is set, a single log entry is written with a comma separated list of trace events. For example, if the cache was stale but validated, the following log entry would be written: "cache: stale, valid, store". When the verbose option is false, no logging occurs. * Added "X-Rack-Cache" response header with the same comma separated trace value as described above. This gives some visibility into how the cache processed the request. * Add support for canonicalized cache keys, as well as custom cache key generators, which are specified in the options as :cache_key as either any object that has a call() or as a block. Cache key generators get passed a request object and return a cache key string. ## 0.3.0 / December 2008 * Add support for public and private cache control directives. Responses marked as explicitly public are cached even when the request includes an Authorization or Cookie header. Responses marked as explicitly private are considered uncacheable. * Added a "private_headers" option that dictates which request headers trigger default "private" cache control processing. By default, the Cookie and Authorization headers are included. Headers may be added or removed as necessary to change the default private logic. * Adhere to must-revalidate/proxy-revalidate cache control directives by not assigning the default_ttl to responses that don't include freshness information. This should let us begin using default_ttl more liberally since we can control it using the must-revalidate/proxy-revalidate directives. * Use the s-maxage Cache-Control value in preference to max-age when present. The ttl= method now sets the s-maxage value instead of max-age. Code that used ttl= to control freshness at the client needs to change to set the max-age directive explicitly. * Enable support for X-Sendfile middleware by responding to #to_path on bodies served from disk storage. Adding the Rack::Sendfile component upstream from Rack::Cache will result in cached bodies being served directly by the web server (instead of being read in Ruby). * BUG: MetaStore hits but EntityStore misses. This would 500 previously; now we detect it and act as if the MetaStore missed as well. * Implement low level #purge method on all concrete entity store classes -- removes the entity body corresponding to the SHA1 key provided and returns nil. * Basically sane handling of HEAD requests. A HEAD request is never passed through to the backend except when transitioning with pass!. This means that the cache responds to HEAD requests without invoking the backend at all when the cached entry is fresh. When no cache entry exists, or the cached entry is stale and can be validated, the backend is invoked with a GET request and the HEAD is handled right before the response is delivered upstream. * BUG: The Age response header was not being set properly when a stale entry was validated. This would result in Age values that exceeded the freshness lifetime in responses. * BUG: A cached entry in a heap meta store could be unintentionally modified by request processing since the cached objects were being returned directly. The result was typically missing/incorrect header values (e.g., missing Content-Type header). [dkubb] * BUG: 304 responses should not include entity headers (especially Content-Length). This is causing Safari/WebKit weirdness on 304 responses. * BUG: The If-None-Match header was being ignored, causing the cache to send 200 responses to matching conditional GET requests. ## 0.2.0 / 2008-10-24 / Initial Release * Document events and transitions in `rack/cache/config/default.rb` * Basic logging support (`trace`, `warn`, `info`, `error` from within Context) * EntityStore: store entity bodies keyed by SHA * MetaStore: store response headers keyed by URL * Last-Modified/ETag validation * Vary support * Implement error! transition * New Rack::Cache::Core * memcached meta and entity store implementations * URI based storage configuration * Read options from Rack env if present (rack-cache.XXX keys) * `object` is now `entry` * Documentation framework and website * Document storage areas and implementations * Document configuration/events ## 0.1.0 / 2008-07-21 / Proof of concept (unreleased) * Basic core with event support * `#import` method for bringing in config files * Freshness based expiration * RFC 2616 If-Modified-Since based validation * A horribly shitty storage back-end (Hash in mem) * Don't cache hop-by-hop headers: Connection, Keep-Alive, Proxy-Authenticate, Proxy-Authorization, TE, Trailers, Transfer-Encoding, Upgrade rack-cache-1.17.0/MIT-LICENSE000066400000000000000000000020471460372356300152310ustar00rootroot00000000000000Copyright (c) 2008 Ryan Tomayko Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. rack-cache-1.17.0/README.md000066400000000000000000000071201460372356300150510ustar00rootroot00000000000000Rack::Cache =========== Rack::Cache is suitable as a quick drop-in component to enable HTTP caching for Rack-based applications that produce freshness (`expires`, `cache-control`) and/or validation (`last-modified`, `etag`) information: * Standards-based (RFC 2616) * Freshness/expiration based caching * Validation (`if-modified-since` / `if-none-match`) * `vary` support * `cache-control` `public`, `private`, `max-age`, `s-maxage`, `must-revalidate`, and `proxy-revalidate`. * Portable: 100% Ruby / works with any Rack-enabled framework * Disk, memcached, and heap memory storage backends For more information about Rack::Cache features and usage, see: https://rack.github.io/rack-cache/ Rack::Cache is not overly optimized for performance. The main goal of the project is to provide a portable, easy-to-configure, and standards-based caching solution for small to medium sized deployments. More sophisticated / high-performance caching systems (e.g., Varnish, Squid, httpd/mod-cache) may be more appropriate for large deployments with significant throughput requirements. Installation ------------ gem install rack-cache Basic Usage ----------- `Rack::Cache` is implemented as a piece of Rack middleware and can be used with any Rack-based application. If your application includes a rackup (`.ru`) file or uses Rack::Builder to construct the application pipeline, simply require and use as follows: ```Ruby require 'rack/cache' use Rack::Cache, metastore: 'file:/var/cache/rack/meta', entitystore: 'file:/var/cache/rack/body', verbose: true run app ``` Assuming you've designed your backend application to take advantage of HTTP's caching features, no further code or configuration is required for basic caching. Using with Rails ---------------- ```Ruby # config/application.rb config.action_dispatch.rack_cache = true # or config.action_dispatch.rack_cache = { verbose: true, metastore: 'file:/var/cache/rack/meta', entitystore: 'file:/var/cache/rack/body' } ``` You should now see `Rack::Cache` listed in the middleware pipeline: rake middleware [more information](https://snippets.aktagon.com/snippets/302-how-to-setup-and-use-rack-cache-with-rails) Using with Dalli ---------------- Dalli is a high performance memcached client for Ruby. More information at: https://github.com/mperham/dalli ```Ruby require 'dalli' require 'rack/cache' use Rack::Cache, verbose: true, metastore: "memcached://localhost:11211/meta", entitystore: "memcached://localhost:11211/body" run app ``` Noop entity store ----------------- Does not persist response bodies (no disk/memory used).
Responses from the cache will have an empty body.
Clients must ignore these empty cached response (check for `x-rack-cache` response header).
Atm cannot handle streamed responses, patch needed. ```Ruby require 'rack/cache' use Rack::Cache, verbose: true, metastore: entitystore: "noop:/" run app ``` Ignoring tracking parameters in cache keys ----------------- It's fairly common to include tracking parameters which don't affect the content of the page. Since Rack::Cache uses the full URL as part of the cache key, this can cause unneeded churn in your cache. If you're using the default key class `Rack::Cache::Key`, you can configure a proc to ignore certain keys/values like so: ```Ruby Rack::Cache::Key.query_string_ignore = proc { |k, v| k =~ /^(trk|utm)_/ } ``` License: MIT
[![Development](https://github.com/rack/rack-cache/actions/workflows/development.yml/badge.svg)](https://github.com/rack/rack-cache/actions/workflows/development.yml) rack-cache-1.17.0/Rakefile000066400000000000000000000040771460372356300152470ustar00rootroot00000000000000require 'bundler/setup' require 'bundler/gem_tasks' require 'rake/clean' require 'bump/tasks' task :default => :test CLEAN.include %w[coverage/ doc/api doc/gh-pages tags] CLOBBER.include %w[dist] desc 'Run tests' task :test do sh "bundle exec mtest test" end desc 'Generate test coverage report' task :rcov do sh "rcov -I.:lib:test test/*_test.rb" end # DOC ======================================================================= desc 'Build all documentation' task :doc => %w[doc:api doc:markdown] desc 'Build API documentation (doc/api)' task 'doc:api' => 'doc/api/index.html' file 'doc/api/index.html' => FileList['lib/**/*.rb'] do |f| rm_rf 'doc/api' sh((<<-SH).gsub(/[\s\n]+/, ' ').strip) rdoc --op doc/api --charset utf8 --fmt hanna --line-numbers --main cache.rb --title 'Rack::Cache API Documentation' #{f.prerequisites.join(' ')} SH end CLEAN.include 'doc/api' desc 'Build markdown documentation files' task 'doc:markdown' FileList['doc/*.markdown'].each do |source| dest = "doc/#{File.basename(source, '.markdown')}.html" file dest => [source, 'doc/layout.html.erb'] do |f| puts "markdown: #{source} -> #{dest}" if verbose require 'erb' unless defined? ERB template = File.read(source) content = Markdown.new(ERB.new(template, 0, "%<>").result(binding), :smart).to_html content.match("

(.*)

")[1] rescue '' layout = ERB.new(File.read("doc/layout.html.erb"), 0, "%<>") output = layout.result(binding) File.open(dest, 'w') { |io| io.write(output) } end task 'doc:markdown' => dest CLEAN.include dest end desc 'Move documentation to directory for github pages' task 'doc:gh-pages' => [:clean, :doc] do html_files = FileList['doc/*.markdown'].map { |file| file.gsub('.markdown', '.html')} css_files = FileList['doc/*.css'] FileUtils.mkdir('doc/gh-pages') FileUtils.cp_r('doc/api/', 'doc/gh-pages/api') FileUtils.cp([*html_files, *css_files], 'doc/gh-pages') end desc 'Start the documentation development server' task 'doc:server' do sh 'cd doc && thin --rackup server.ru --port 3035 start' end rack-cache-1.17.0/doc/000077500000000000000000000000001460372356300143375ustar00rootroot00000000000000rack-cache-1.17.0/doc/configuration.markdown000066400000000000000000000131031460372356300207500ustar00rootroot00000000000000Configuration ============= __Rack::Cache__ includes a configuration system that can be used to specify fairly sophisticated cache policy on a global or per-request basis. Setting Cache Options --------------------- Cache options can be set when the __Rack::Cache__ object is created, or by setting a `rack-cache.