From 0e44859a0921989c3cec513909b7414cfd588d32 Mon Sep 17 00:00:00 2001 From: Aditya Prakash Date: Sun, 21 Mar 2021 16:12:12 +0530 Subject: [PATCH 1/2] Enable zeitwerk autoloader this is default for rails 6.0 config. nesting of middlewares was updated to match expected class names by zeitwerk. requried to pass `rake zeitwerk:check ``` NameError: uninitialized constant Hostess ``` lib is part of autoload_path. we need to explicity exclude folder from lib which don't need to be autoloated (initializers/zeitwerk.rb). --- config/application.rb | 2 + config/environments/development.rb | 4 +- config/environments/production.rb | 4 +- config/environments/staging.rb | 4 +- config/environments/test.rb | 2 +- config/initializers/zeitwerk.rb | 6 +++ lib/gemcutter/middleware/hostess.rb | 51 ++++++++++++++++++++++++++ lib/gemcutter/middleware/redirector.rb | 28 ++++++++++++++ lib/middleware/hostess.rb | 49 ------------------------- lib/middleware/redirector.rb | 26 ------------- test/unit/hostess_test.rb | 4 +- test/unit/redirector_test.rb | 2 +- 12 files changed, 97 insertions(+), 85 deletions(-) create mode 100644 config/initializers/zeitwerk.rb create mode 100644 lib/gemcutter/middleware/hostess.rb create mode 100644 lib/gemcutter/middleware/redirector.rb delete mode 100644 lib/middleware/hostess.rb delete mode 100644 lib/middleware/redirector.rb diff --git a/config/application.rb b/config/application.rb index 2fb5beedc69..c991beff052 100644 --- a/config/application.rb +++ b/config/application.rb @@ -25,6 +25,8 @@ class Application < Rails::Application # Initialize configuration defaults for originally generated Rails version. config.load_defaults 5.2 + config.autoloader = :zeitwerk + # Settings in config/environments/* take precedence over those specified here. # Application configuration can go into files in config/initializers # -- all .rb files in that directory are automatically loaded after loading diff --git a/config/environments/development.rb b/config/environments/development.rb index f4d2df04ddb..7c0eefba131 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -1,4 +1,4 @@ -require_relative "../../lib/middleware/hostess" +require_relative "../../lib/gemcutter/middleware/hostess" require "active_support/core_ext/integer/time" Rails.application.configure do @@ -66,7 +66,7 @@ # Raises error for missing translations. # config.i18n.raise_on_missing_translations = true - config.middleware.use Hostess + config.middleware.use Gemcutter::Middleware::Hostess # Annotate rendered view with file names. # config.action_view.annotate_rendered_view_with_filenames = true diff --git a/config/environments/production.rb b/config/environments/production.rb index 42e364ef28e..397781e6dfd 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -1,5 +1,5 @@ require Rails.root.join("config", "secret") if Rails.root.join("config", "secret.rb").file? -require_relative "../../lib/middleware/redirector" +require_relative "../../lib/gemcutter/middleware/redirector" require "active_support/core_ext/integer/time" Rails.application.configure do @@ -120,7 +120,7 @@ compression_min_size: 524_288 } - config.middleware.use Redirector + config.middleware.use Gemcutter::Middleware::Redirector # Inserts middleware to perform automatic connection switching. # The `database_selector` hash is used to pass options to the DatabaseSelector diff --git a/config/environments/staging.rb b/config/environments/staging.rb index 1cd7a3190bc..d713b6502fa 100644 --- a/config/environments/staging.rb +++ b/config/environments/staging.rb @@ -1,5 +1,5 @@ require Rails.root.join("config", "secret") if Rails.root.join("config", "secret.rb").file? -require_relative "../../lib/middleware/redirector" +require_relative "../../lib/gemcutter/middleware/redirector" Rails.application.configure do # Settings specified here will take precedence over those in config/application.rb. @@ -117,5 +117,5 @@ compression_min_size: 524_288 } - config.middleware.use Redirector + config.middleware.use Gemcutter::Middleware::Redirector end diff --git a/config/environments/test.rb b/config/environments/test.rb index f526bf125cc..6f949441a1d 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -1,4 +1,4 @@ -require_relative "../../lib/middleware/redirector" +require_relative "../../lib/gemcutter/middleware/redirector" require "active_support/core_ext/integer/time" # The test environment is used exclusively to run your application's diff --git a/config/initializers/zeitwerk.rb b/config/initializers/zeitwerk.rb new file mode 100644 index 00000000000..24007e472b8 --- /dev/null +++ b/config/initializers/zeitwerk.rb @@ -0,0 +1,6 @@ +# ignore rake tasks because don't need to autoload them +Rails.autoloaders.main.ignore(Rails.root.join("lib/tasks")) + +# does not require autoload. ignore SqsWorker to supress following: +# expected file lib/shoryuken/sqs_worker.rb to define constant Shoryuken::SqsWorker +Rails.autoloaders.main.ignore(Rails.root.join("lib/shoryuken")) diff --git a/lib/gemcutter/middleware/hostess.rb b/lib/gemcutter/middleware/hostess.rb new file mode 100644 index 00000000000..1e8542b6085 --- /dev/null +++ b/lib/gemcutter/middleware/hostess.rb @@ -0,0 +1,51 @@ +module Gemcutter::Middleware + class Hostess < Rack::Static + def initialize(app, options = {}) + options[:root] = RubygemFs.instance.base_dir + + options[:urls] = %w[ + /specs.4.8.gz + /latest_specs.4.8.gz + /prerelease_specs.4.8.gz + /quick/rubygems-update-1.3.6.gemspec.rz + /yaml.Z + /yaml.z + /Marshal.4.8.Z + /quick/index.rz + /quick/latest_index.rz + /yaml + /Marshal.4.8 + /specs.4.8 + /latest_specs.4.8 + /prerelease_specs.4.8 + /quick/index + /quick/latest_index + ] + + super(app, options) + end + + def can_serve(path) + super(path) || gem_download_path(path) || path =~ %r{/quick/Marshal\.4\.8/.*\.gemspec.rz} + end + + def gem_download_path(path) + Regexp.last_match(1) if path =~ %r{/gems/(.*)\.gem} + end + + def call(env) + path = env["PATH_INFO"] + + return [302, { "Location" => "/gems/#{Regexp.last_match(1)}.gem" }, []] if path =~ %r{/downloads/(.*)\.gem} + + download_path = gem_download_path(path) + name = Version.rubygem_name_for(download_path) if download_path + if name + GemDownload.transaction do + GemDownload.bulk_update([[download_path, 1]]) + end + end + super + end + end +end diff --git a/lib/gemcutter/middleware/redirector.rb b/lib/gemcutter/middleware/redirector.rb new file mode 100644 index 00000000000..33df1ed2b83 --- /dev/null +++ b/lib/gemcutter/middleware/redirector.rb @@ -0,0 +1,28 @@ +module Gemcutter::Middleware + class Redirector + def initialize(app) + @app = app + end + + def call(env) + request = Rack::Request.new(env) + + allowed_hosts = [Gemcutter::HOST, "index.rubygems.org", "fastly.rubygems.org", "bundler.rubygems.org"] + + if !allowed_hosts.include?(request.host) && request.path !~ %r{^/api|^/internal} && request.host !~ /docs/ + fake_request = Rack::Request.new(env.merge("HTTP_HOST" => Gemcutter::HOST)) + redirect_to(fake_request.url) + elsif request.path =~ %r{^/(book|chapter|export|read|shelf|syndicate)} && request.host !~ /docs/ + redirect_to("https://docs.rubygems.org#{request.path}") + else + @app.call(env) + end + end + + private + + def redirect_to(url) + [301, { "Location" => url }, []] + end + end +end diff --git a/lib/middleware/hostess.rb b/lib/middleware/hostess.rb deleted file mode 100644 index 39963025759..00000000000 --- a/lib/middleware/hostess.rb +++ /dev/null @@ -1,49 +0,0 @@ -class Hostess < Rack::Static - def initialize(app, options = {}) - options[:root] = RubygemFs.instance.base_dir - - options[:urls] = %w[ - /specs.4.8.gz - /latest_specs.4.8.gz - /prerelease_specs.4.8.gz - /quick/rubygems-update-1.3.6.gemspec.rz - /yaml.Z - /yaml.z - /Marshal.4.8.Z - /quick/index.rz - /quick/latest_index.rz - /yaml - /Marshal.4.8 - /specs.4.8 - /latest_specs.4.8 - /prerelease_specs.4.8 - /quick/index - /quick/latest_index - ] - - super(app, options) - end - - def can_serve(path) - super(path) || gem_download_path(path) || path =~ %r{/quick/Marshal\.4\.8/.*\.gemspec.rz} - end - - def gem_download_path(path) - Regexp.last_match(1) if path =~ %r{/gems/(.*)\.gem} - end - - def call(env) - path = env["PATH_INFO"] - - return [302, { "Location" => "/gems/#{Regexp.last_match(1)}.gem" }, []] if path =~ %r{/downloads/(.*)\.gem} - - download_path = gem_download_path(path) - name = Version.rubygem_name_for(download_path) if download_path - if name - GemDownload.transaction do - GemDownload.bulk_update([[download_path, 1]]) - end - end - super - end -end diff --git a/lib/middleware/redirector.rb b/lib/middleware/redirector.rb deleted file mode 100644 index 3846377b738..00000000000 --- a/lib/middleware/redirector.rb +++ /dev/null @@ -1,26 +0,0 @@ -class Redirector - def initialize(app) - @app = app - end - - def call(env) - request = Rack::Request.new(env) - - allowed_hosts = [Gemcutter::HOST, "index.rubygems.org", "fastly.rubygems.org", "bundler.rubygems.org"] - - if !allowed_hosts.include?(request.host) && request.path !~ %r{^/api|^/internal} && request.host !~ /docs/ - fake_request = Rack::Request.new(env.merge("HTTP_HOST" => Gemcutter::HOST)) - redirect_to(fake_request.url) - elsif request.path =~ %r{^/(book|chapter|export|read|shelf|syndicate)} && request.host !~ /docs/ - redirect_to("https://docs.rubygems.org#{request.path}") - else - @app.call(env) - end - end - - private - - def redirect_to(url) - [301, { "Location" => url }, []] - end -end diff --git a/test/unit/hostess_test.rb b/test/unit/hostess_test.rb index eae27c4f6b4..105eef8e63c 100644 --- a/test/unit/hostess_test.rb +++ b/test/unit/hostess_test.rb @@ -1,5 +1,5 @@ require "test_helper" -require_relative "../../lib/middleware/hostess" +require_relative "../../lib/gemcutter/middleware/hostess" class HostessTest < ActiveSupport::TestCase include Rack::Test::Methods @@ -9,7 +9,7 @@ class HostessTest < ActiveSupport::TestCase end def app - Hostess.new(-> { [200, {}, ""] }) + Gemcutter::Middleware::Hostess.new(-> { [200, {}, ""] }) end def touch(path) diff --git a/test/unit/redirector_test.rb b/test/unit/redirector_test.rb index dfcbc21643b..a2d2d3e771d 100644 --- a/test/unit/redirector_test.rb +++ b/test/unit/redirector_test.rb @@ -5,7 +5,7 @@ class RedirectorTest < ActiveSupport::TestCase def app Rack::Builder.new do - use Redirector + use Gemcutter::Middleware::Redirector run ->(_) { [200, { "Content-Type" => "text/html" }, []] } end end From ec60e1d19fde82faf797d84de2d54fcaabc87e1b Mon Sep 17 00:00:00 2001 From: Aditya Prakash Date: Sun, 21 Mar 2021 16:29:27 +0530 Subject: [PATCH 2/2] Update nesting of unit tests for middleware --- test/unit/{ => gemcutter/middleware}/hostess_test.rb | 4 ++-- test/unit/{ => gemcutter/middleware}/redirector_test.rb | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) rename test/unit/{ => gemcutter/middleware}/hostess_test.rb (94%) rename test/unit/{ => gemcutter/middleware}/redirector_test.rb (96%) diff --git a/test/unit/hostess_test.rb b/test/unit/gemcutter/middleware/hostess_test.rb similarity index 94% rename from test/unit/hostess_test.rb rename to test/unit/gemcutter/middleware/hostess_test.rb index 105eef8e63c..8c8678930ba 100644 --- a/test/unit/hostess_test.rb +++ b/test/unit/gemcutter/middleware/hostess_test.rb @@ -1,7 +1,7 @@ require "test_helper" -require_relative "../../lib/gemcutter/middleware/hostess" +require_relative "../../../../lib/gemcutter/middleware/hostess" -class HostessTest < ActiveSupport::TestCase +class Gemcutter::Middleware::HostessTest < ActiveSupport::TestCase include Rack::Test::Methods setup do diff --git a/test/unit/redirector_test.rb b/test/unit/gemcutter/middleware/redirector_test.rb similarity index 96% rename from test/unit/redirector_test.rb rename to test/unit/gemcutter/middleware/redirector_test.rb index a2d2d3e771d..c6f99dc5b44 100644 --- a/test/unit/redirector_test.rb +++ b/test/unit/gemcutter/middleware/redirector_test.rb @@ -1,6 +1,6 @@ require "test_helper" -class RedirectorTest < ActiveSupport::TestCase +class Gemcutter::Middleware::RedirectorTest < ActiveSupport::TestCase include Rack::Test::Methods def app