├── .gitignore ├── Gemfile ├── Gemfile.lock ├── MIT-LICENSE ├── README.md ├── Rakefile ├── lib ├── rails_weak_etags.rb └── rails_weak_etags │ ├── middleware.rb │ ├── railtie.rb │ └── version.rb ├── rails_weak_etags.gemspec └── test ├── dummy ├── README.rdoc ├── Rakefile ├── app │ ├── assets │ │ ├── images │ │ │ └── .keep │ │ ├── javascripts │ │ │ └── application.js │ │ └── stylesheets │ │ │ └── application.css │ ├── controllers │ │ ├── application_controller.rb │ │ └── concerns │ │ │ └── .keep │ ├── helpers │ │ └── application_helper.rb │ ├── mailers │ │ └── .keep │ ├── models │ │ ├── .keep │ │ └── concerns │ │ │ └── .keep │ └── views │ │ └── layouts │ │ └── application.html.erb ├── bin │ ├── bundle │ ├── rails │ └── rake ├── config.ru ├── config │ ├── application.rb │ ├── boot.rb │ ├── database.yml │ ├── environment.rb │ ├── environments │ │ ├── development.rb │ │ ├── production.rb │ │ └── test.rb │ ├── initializers │ │ ├── backtrace_silencers.rb │ │ ├── filter_parameter_logging.rb │ │ ├── inflections.rb │ │ ├── mime_types.rb │ │ ├── secret_token.rb │ │ ├── session_store.rb │ │ └── wrap_parameters.rb │ ├── locales │ │ └── en.yml │ └── routes.rb ├── lib │ └── assets │ │ └── .keep ├── log │ └── .keep └── public │ ├── 404.html │ ├── 422.html │ ├── 500.html │ └── favicon.ico ├── integration └── navigation_test.rb ├── rails_weak_etags_test.rb └── test_helper.rb /.gitignore: -------------------------------------------------------------------------------- 1 | .bundle/ 2 | log/*.log 3 | pkg/ 4 | test/dummy/db/*.sqlite3 5 | test/dummy/db/*.sqlite3-journal 6 | test/dummy/log/*.log 7 | test/dummy/tmp/ 8 | test/dummy/.sass-cache 9 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | # Declare your gem's dependencies in rails_weak_etags.gemspec. 4 | # Bundler will treat runtime dependencies like base dependencies, and 5 | # development dependencies will be added by default to the :development group. 6 | gemspec 7 | 8 | # Declare any dependencies that are still in development here instead of in 9 | # your gemspec. These might include edge Rails or gems from your path or 10 | # Git. Remember to move these dependencies to your gemspec before releasing 11 | # your gem to rubygems.org. 12 | 13 | # To use debugger 14 | # gem 'debugger' 15 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: . 3 | specs: 4 | rails_weak_etags (0.0.4) 5 | rails (> 3.1) 6 | 7 | GEM 8 | remote: https://rubygems.org/ 9 | specs: 10 | actionmailer (4.0.8) 11 | actionpack (= 4.0.8) 12 | mail (~> 2.5.4) 13 | actionpack (4.0.8) 14 | activesupport (= 4.0.8) 15 | builder (~> 3.1.0) 16 | erubis (~> 2.7.0) 17 | rack (~> 1.5.2) 18 | rack-test (~> 0.6.2) 19 | activemodel (4.0.8) 20 | activesupport (= 4.0.8) 21 | builder (~> 3.1.0) 22 | activerecord (4.0.8) 23 | activemodel (= 4.0.8) 24 | activerecord-deprecated_finders (~> 1.0.2) 25 | activesupport (= 4.0.8) 26 | arel (~> 4.0.0) 27 | activerecord-deprecated_finders (1.0.3) 28 | activesupport (4.0.8) 29 | i18n (~> 0.6, >= 0.6.9) 30 | minitest (~> 4.2) 31 | multi_json (~> 1.3) 32 | thread_safe (~> 0.1) 33 | tzinfo (~> 0.3.37) 34 | arel (4.0.2) 35 | builder (3.1.4) 36 | erubis (2.7.0) 37 | hike (1.2.3) 38 | i18n (0.6.11) 39 | mail (2.5.4) 40 | mime-types (~> 1.16) 41 | treetop (~> 1.4.8) 42 | mime-types (1.25.1) 43 | minitest (4.7.5) 44 | multi_json (1.10.1) 45 | polyglot (0.3.5) 46 | rack (1.5.2) 47 | rack-test (0.6.2) 48 | rack (>= 1.0) 49 | rails (4.0.8) 50 | actionmailer (= 4.0.8) 51 | actionpack (= 4.0.8) 52 | activerecord (= 4.0.8) 53 | activesupport (= 4.0.8) 54 | bundler (>= 1.3.0, < 2.0) 55 | railties (= 4.0.8) 56 | sprockets-rails (~> 2.0) 57 | railties (4.0.8) 58 | actionpack (= 4.0.8) 59 | activesupport (= 4.0.8) 60 | rake (>= 0.8.7) 61 | thor (>= 0.18.1, < 2.0) 62 | rake (10.3.2) 63 | sprockets (2.12.1) 64 | hike (~> 1.2) 65 | multi_json (~> 1.0) 66 | rack (~> 1.0) 67 | tilt (~> 1.1, != 1.3.0) 68 | sprockets-rails (2.1.3) 69 | actionpack (>= 3.0) 70 | activesupport (>= 3.0) 71 | sprockets (~> 2.8) 72 | sqlite3 (1.3.9) 73 | thor (0.19.1) 74 | thread_safe (0.3.4) 75 | tilt (1.4.1) 76 | treetop (1.4.15) 77 | polyglot 78 | polyglot (>= 0.3.1) 79 | tzinfo (0.3.39) 80 | 81 | PLATFORMS 82 | ruby 83 | 84 | DEPENDENCIES 85 | rails_weak_etags! 86 | sqlite3 87 | -------------------------------------------------------------------------------- /MIT-LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2014 John Naegle 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Rails Weak E-Tags 2 | 3 | Converts strong e-tags generated by your Rails application into weak e-tags that can be passed through a web server with gzip compression enabled. 4 | 5 | Based on this stack overflow question: http://stackoverflow.com/questions/18693718/weak-etags-in-rails 6 | 7 | ## Installation 8 | 9 | Add this line to your application's Gemfile: 10 | 11 | gem 'rails_weak_etags' 12 | 13 | And then execute: 14 | 15 | $ bundle 16 | 17 | Or install it yourself as: 18 | 19 | $ gem install rails_weak_etags 20 | 21 | ## Usage 22 | 23 | 24 | ## Contributing 25 | 26 | 1. Fork it 27 | 2. Create your feature branch (`git checkout -b my-new-feature`) 28 | 3. Commit your changes (`git commit -am 'Add some feature'`) 29 | 4. Push to the branch (`git push origin my-new-feature`) 30 | 5. Create new Pull Request 31 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | begin 2 | require 'bundler/setup' 3 | rescue LoadError 4 | puts 'You must `gem install bundler` and `bundle install` to run rake tasks' 5 | end 6 | 7 | require 'rdoc/task' 8 | 9 | RDoc::Task.new(:rdoc) do |rdoc| 10 | rdoc.rdoc_dir = 'rdoc' 11 | rdoc.title = 'RailsWeakEtags' 12 | rdoc.options << '--line-numbers' 13 | rdoc.rdoc_files.include('README.rdoc') 14 | rdoc.rdoc_files.include('lib/**/*.rb') 15 | end 16 | 17 | APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__) 18 | load 'rails/tasks/engine.rake' 19 | 20 | 21 | 22 | Bundler::GemHelper.install_tasks 23 | 24 | require 'rake/testtask' 25 | 26 | Rake::TestTask.new(:test) do |t| 27 | t.libs << 'lib' 28 | t.libs << 'test' 29 | t.pattern = 'test/**/*_test.rb' 30 | t.verbose = false 31 | end 32 | 33 | 34 | task default: :test 35 | -------------------------------------------------------------------------------- /lib/rails_weak_etags.rb: -------------------------------------------------------------------------------- 1 | require 'rails_weak_etags/middleware' 2 | require "rails_weak_etags/railtie" 3 | -------------------------------------------------------------------------------- /lib/rails_weak_etags/middleware.rb: -------------------------------------------------------------------------------- 1 | module RailsWeakEtags 2 | # http://stackoverflow.com/questions/18693718/weak-etags-in-rails 3 | class Middleware 4 | def initialize(app) 5 | @app = app 6 | end 7 | 8 | def call(env) 9 | status, headers, body = nil, nil, nil 10 | 11 | # make request etags "strong" before calling the app. Restore the original 12 | # header before passing control back. Rack 1.6 added weak e-tag support 13 | # for digest bodies, so it needs to see the weak etag. 14 | request_etag = env['HTTP_IF_NONE_MATCH'] 15 | if request_etag && request_etag =~ /^W\// 16 | env['HTTP_IF_NONE_MATCH'] = request_etag[2..-1] 17 | status, headers, body = @app.call(env) 18 | env['HTTP_IF_NONE_MATCH'] = request_etag 19 | else 20 | status, headers, body = @app.call(env) 21 | end 22 | 23 | # make all response etags "weak" 24 | response_etag = headers['ETag'] 25 | if response_etag && response_etag !~ /^W\// 26 | headers['ETag'] = "W/#{response_etag}" 27 | end 28 | 29 | [status, headers, body] 30 | end 31 | end 32 | end 33 | -------------------------------------------------------------------------------- /lib/rails_weak_etags/railtie.rb: -------------------------------------------------------------------------------- 1 | module RailsWeakEtags 2 | class Railtie < ::Rails::Railtie 3 | initializer "rails_weak_etags.configure_rails_initialization" do |app| 4 | app.middleware.insert_before(Rack::ETag, RailsWeakEtags::Middleware) 5 | end 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /lib/rails_weak_etags/version.rb: -------------------------------------------------------------------------------- 1 | module RailsWeakEtags 2 | VERSION = "0.0.2" 3 | end 4 | -------------------------------------------------------------------------------- /rails_weak_etags.gemspec: -------------------------------------------------------------------------------- 1 | $:.push File.expand_path("../lib", __FILE__) 2 | 3 | # Maintain your gem's version: 4 | require "rails_weak_etags/version" 5 | 6 | # Describe your gem and declare its dependencies: 7 | Gem::Specification.new do |s| 8 | s.name = "rails_weak_etags" 9 | s.version = RailsWeakEtags::VERSION 10 | s.authors = ["John Naegle"] 11 | s.email = ["john.naegle@gmail.com"] 12 | s.homepage = "http://github.com/john.naegle/rails_weak_etags" 13 | s.summary = "Converts strong e-tags to weak." 14 | s.description = "Converts strong e-tags to weak so they can be passed through nginx with g-zip compression enabled" 15 | 16 | s.files = Dir["{app,config,db,lib}/**/*", "MIT-LICENSE", "Rakefile", "README.rdoc"] 17 | s.test_files = Dir["test/**/*"] 18 | 19 | s.add_dependency "rails", "> 3.1" 20 | 21 | s.add_development_dependency "sqlite3" 22 | end 23 | -------------------------------------------------------------------------------- /test/dummy/README.rdoc: -------------------------------------------------------------------------------- 1 | == README 2 | 3 | This README would normally document whatever steps are necessary to get the 4 | application up and running. 5 | 6 | Things you may want to cover: 7 | 8 | * Ruby version 9 | 10 | * System dependencies 11 | 12 | * Configuration 13 | 14 | * Database creation 15 | 16 | * Database initialization 17 | 18 | * How to run the test suite 19 | 20 | * Services (job queues, cache servers, search engines, etc.) 21 | 22 | * Deployment instructions 23 | 24 | * ... 25 | 26 | 27 | Please feel free to use a different markup language if you do not plan to run 28 | rake doc:app. 29 | -------------------------------------------------------------------------------- /test/dummy/Rakefile: -------------------------------------------------------------------------------- 1 | # Add your own tasks in files placed in lib/tasks ending in .rake, 2 | # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. 3 | 4 | require File.expand_path('../config/application', __FILE__) 5 | 6 | Dummy::Application.load_tasks 7 | -------------------------------------------------------------------------------- /test/dummy/app/assets/images/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnnaegle/rails_weak_etags/0cb5d89cae2e86d0918c29bd3a8380bba3b97502/test/dummy/app/assets/images/.keep -------------------------------------------------------------------------------- /test/dummy/app/assets/javascripts/application.js: -------------------------------------------------------------------------------- 1 | // This is a manifest file that'll be compiled into application.js, which will include all the files 2 | // listed below. 3 | // 4 | // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts, 5 | // or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path. 6 | // 7 | // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the 8 | // compiled file. 9 | // 10 | // Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details 11 | // about supported directives. 12 | // 13 | //= require_tree . 14 | -------------------------------------------------------------------------------- /test/dummy/app/assets/stylesheets/application.css: -------------------------------------------------------------------------------- 1 | /* 2 | * This is a manifest file that'll be compiled into application.css, which will include all the files 3 | * listed below. 4 | * 5 | * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets, 6 | * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path. 7 | * 8 | * You're free to add application-wide styles to this file and they'll appear at the top of the 9 | * compiled file, but it's generally better to create a new file per style scope. 10 | * 11 | *= require_self 12 | *= require_tree . 13 | */ 14 | -------------------------------------------------------------------------------- /test/dummy/app/controllers/application_controller.rb: -------------------------------------------------------------------------------- 1 | class ApplicationController < ActionController::Base 2 | # Prevent CSRF attacks by raising an exception. 3 | # For APIs, you may want to use :null_session instead. 4 | protect_from_forgery with: :exception 5 | end 6 | -------------------------------------------------------------------------------- /test/dummy/app/controllers/concerns/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnnaegle/rails_weak_etags/0cb5d89cae2e86d0918c29bd3a8380bba3b97502/test/dummy/app/controllers/concerns/.keep -------------------------------------------------------------------------------- /test/dummy/app/helpers/application_helper.rb: -------------------------------------------------------------------------------- 1 | module ApplicationHelper 2 | end 3 | -------------------------------------------------------------------------------- /test/dummy/app/mailers/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnnaegle/rails_weak_etags/0cb5d89cae2e86d0918c29bd3a8380bba3b97502/test/dummy/app/mailers/.keep -------------------------------------------------------------------------------- /test/dummy/app/models/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnnaegle/rails_weak_etags/0cb5d89cae2e86d0918c29bd3a8380bba3b97502/test/dummy/app/models/.keep -------------------------------------------------------------------------------- /test/dummy/app/models/concerns/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnnaegle/rails_weak_etags/0cb5d89cae2e86d0918c29bd3a8380bba3b97502/test/dummy/app/models/concerns/.keep -------------------------------------------------------------------------------- /test/dummy/app/views/layouts/application.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |You may have mistyped the address or the page may have moved.
55 |If you are the application owner check the logs for more information.
57 | 58 | 59 | -------------------------------------------------------------------------------- /test/dummy/public/422.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |Maybe you tried to change something you didn't have access to.
55 |If you are the application owner check the logs for more information.
57 | 58 | 59 | -------------------------------------------------------------------------------- /test/dummy/public/500.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |If you are the application owner check the logs for more information.
56 | 57 | 58 | -------------------------------------------------------------------------------- /test/dummy/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnnaegle/rails_weak_etags/0cb5d89cae2e86d0918c29bd3a8380bba3b97502/test/dummy/public/favicon.ico -------------------------------------------------------------------------------- /test/integration/navigation_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class NavigationTest < ActionDispatch::IntegrationTest 4 | fixtures :all 5 | 6 | # test "the truth" do 7 | # assert true 8 | # end 9 | end 10 | 11 | -------------------------------------------------------------------------------- /test/rails_weak_etags_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class RailsWeakEtagsTest < ActiveSupport::TestCase 4 | test "truth" do 5 | assert_kind_of Module, RailsWeakEtags 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /test/test_helper.rb: -------------------------------------------------------------------------------- 1 | # Configure Rails Environment 2 | ENV["RAILS_ENV"] = "test" 3 | 4 | require File.expand_path("../dummy/config/environment.rb", __FILE__) 5 | require "rails/test_help" 6 | 7 | Rails.backtrace_cleaner.remove_silencers! 8 | 9 | # Load support files 10 | Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f } 11 | 12 | # Load fixtures from the engine 13 | if ActiveSupport::TestCase.method_defined?(:fixture_path=) 14 | ActiveSupport::TestCase.fixture_path = File.expand_path("../fixtures", __FILE__) 15 | end 16 | --------------------------------------------------------------------------------