From e6e3644bea6b21aeb38a5ba8ba492c8d3c453edd Mon Sep 17 00:00:00 2001 From: Sean Rankine Date: Wed, 31 Aug 2022 18:28:54 +0100 Subject: [PATCH 1/6] Add rack-proxy gem dependency This is library allows us to add rack middleware to proxy requests. --- govuk_app_config.gemspec | 1 + 1 file changed, 1 insertion(+) diff --git a/govuk_app_config.gemspec b/govuk_app_config.gemspec index b35b23d5..c3a784dd 100644 --- a/govuk_app_config.gemspec +++ b/govuk_app_config.gemspec @@ -23,6 +23,7 @@ Gem::Specification.new do |spec| spec.add_dependency "logstasher", "~> 2.1" spec.add_dependency "prometheus_exporter", "~> 2.0" spec.add_dependency "puma", "~> 5.6" + spec.add_dependency "rack-proxy", "~> 0.7" spec.add_dependency "sentry-rails", "~> 5.3" spec.add_dependency "sentry-ruby", "~> 5.3" spec.add_dependency "statsd-ruby", "~> 1.5" From 8f2d3bbe389d201b56fe758b95ef0ad543949376 Mon Sep 17 00:00:00 2001 From: Sean Rankine Date: Wed, 31 Aug 2022 18:30:51 +0100 Subject: [PATCH 2/6] Add GovukProxy::StaticProxy class This class can be loaded as Rack middleware and will proxy any requests with the path prefix of `/assets/static` to backend specified. This is useful as it enables Static to use relative paths and the dependent frontend application can forward those requests. This allows us to switch Static to use relative path and allow us to have development environment and not run Static locally (i.e. forward request to production version of Static). --- lib/govuk_app_config.rb | 1 + .../govuk_proxy/static_proxy.rb | 19 +++++++++ spec/lib/govuk_proxy/static_proxy_spec.rb | 40 +++++++++++++++++++ 3 files changed, 60 insertions(+) create mode 100644 lib/govuk_app_config/govuk_proxy/static_proxy.rb create mode 100644 spec/lib/govuk_proxy/static_proxy_spec.rb diff --git a/lib/govuk_app_config.rb b/lib/govuk_app_config.rb index 1b3c653e..c1062c8c 100644 --- a/lib/govuk_app_config.rb +++ b/lib/govuk_app_config.rb @@ -1,6 +1,7 @@ require "govuk_app_config/version" require "govuk_app_config/govuk_statsd" require "govuk_app_config/govuk_error" +require "govuk_app_config/govuk_proxy/static_proxy" require "govuk_app_config/govuk_healthcheck" require "govuk_app_config/govuk_i18n" # This require is deprecated and should be removed on next major version bump diff --git a/lib/govuk_app_config/govuk_proxy/static_proxy.rb b/lib/govuk_app_config/govuk_proxy/static_proxy.rb new file mode 100644 index 00000000..39537533 --- /dev/null +++ b/lib/govuk_app_config/govuk_proxy/static_proxy.rb @@ -0,0 +1,19 @@ +require "rack-proxy" + +module GovukProxy + class StaticProxy < Rack::Proxy + def perform_request(env) + request = Rack::Request.new(env) + + # use rack proxy to forward any requests for /assets/static/* + # this regex needs to match the path set for `Rails.application.config.assets.prefix` in Static + # https://github.com/alphagov/static/blob/main/config/initializers/assets.rb + if request.path =~ %r{^/assets/static/} + env["HTTP_HOST"] = @backend.host + super(env) + else + @app.call(env) + end + end + end +end diff --git a/spec/lib/govuk_proxy/static_proxy_spec.rb b/spec/lib/govuk_proxy/static_proxy_spec.rb new file mode 100644 index 00000000..49e977fd --- /dev/null +++ b/spec/lib/govuk_proxy/static_proxy_spec.rb @@ -0,0 +1,40 @@ +require "spec_helper" +require "govuk_app_config/govuk_proxy/static_proxy" +require "rack/mock" + +RSpec.describe GovukProxy::StaticProxy do + def test_request(path, proxied) + dest_host = (proxied ? static_domain : app_domain) + + stub_request(:get, "https://#{dest_host}#{path}") + .with(headers: { "Host" => dest_host }) + .to_return(status: 200, body: "", headers: {}) + + env = Rack::MockRequest.env_for("http://#{app_domain}#{path}") + status, _headers, _response = proxy.call(env) + expect(status.to_i).to eq(200) + end + + # dummy app to validate success + let(:app) { ->(_env) { [200, {}, "success"] } } + let(:app_domain) { "app.domain" } + let(:static_domain) { "static.domain" } + + let(:proxy) { GovukProxy::StaticProxy.new(app, backend: "https://static.domain", streaming: false) } + + it "redirects the request if path begins with /asset/static" do + test_request("/assets/static/a.css", true) + end + + it "ignores requests not with path prefix /asset/static" do + test_request("/assets/app/a.css", false) + end + + it "ignores requests where /asset/static isn't a prefix" do + test_request("/another/prefix/assets/static/a.css", false) + end + + it "ignores requests with no path" do + test_request("/", false) + end +end From b664516deb7e173a3a4014b8ba4db3ef89e7c0aa Mon Sep 17 00:00:00 2001 From: Sean Rankine Date: Thu, 1 Sep 2022 15:26:18 +0100 Subject: [PATCH 3/6] Add Plek dependency This is library allows us to resolve the URL for Static. --- govuk_app_config.gemspec | 1 + 1 file changed, 1 insertion(+) diff --git a/govuk_app_config.gemspec b/govuk_app_config.gemspec index c3a784dd..b529844d 100644 --- a/govuk_app_config.gemspec +++ b/govuk_app_config.gemspec @@ -21,6 +21,7 @@ Gem::Specification.new do |spec| spec.require_paths = %w[lib] spec.add_dependency "logstasher", "~> 2.1" + spec.add_dependency "plek", "~> 4" spec.add_dependency "prometheus_exporter", "~> 2.0" spec.add_dependency "puma", "~> 5.6" spec.add_dependency "rack-proxy", "~> 0.7" From 511a0b27aa0edb18356e5470b3e49ee9a07b7e34 Mon Sep 17 00:00:00 2001 From: Sean Rankine Date: Wed, 31 Aug 2022 18:36:42 +0100 Subject: [PATCH 4/6] Enable Static proxy behaviour via GOVUK_PROXY_STATIC_ENABLED This adds a railtie to initialise the proxy middleware with backend set to the URL resolved by Plek for Static. This allows frontend apps to enable the proxying behavior in development by simply setting the env var GOVUK_PROXY_STATIC_ENABLED to "true". --- lib/govuk_app_config/railtie.rb | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/lib/govuk_app_config/railtie.rb b/lib/govuk_app_config/railtie.rb index 16b2dbde..6252c4e7 100644 --- a/lib/govuk_app_config/railtie.rb +++ b/lib/govuk_app_config/railtie.rb @@ -1,5 +1,14 @@ +require "plek" + module GovukAppConfig class Railtie < Rails::Railtie + initializer "govuk_app_config.configure_govuk_proxy" do |app| + if ENV["GOVUK_PROXY_STATIC_ENABLED"] == "true" + static_url = Plek.new.find("static") + app.middleware.use GovukProxy::StaticProxy, backend: static_url + end + end + config.before_initialize do GovukLogging.configure if Rails.env.production? end From ef546c39ebccd985227be8e5f43403ef8b826450 Mon Sep 17 00:00:00 2001 From: Sean Rankine Date: Thu, 1 Sep 2022 10:21:26 +0100 Subject: [PATCH 5/6] Update changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b5aaa1ad..2071535b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +# Unreleased + +- Add GovukProxy::StaticProxy to forward Static asset requests by setting `GOVUK_PROXY_STATIC_ENABLED=true`.([#261](https://github.com/alphagov/govuk_app_config/pull/261)) + # 4.8.0 - Enables Sentry environment names for EKS versions of integration, staging and production.([#260](https://github.com/alphagov/govuk_app_config/pull/260)) From a3495bc9409915068f3c78479a74ce26fa9c13d5 Mon Sep 17 00:00:00 2001 From: Sean Rankine Date: Mon, 5 Sep 2022 09:16:26 +0000 Subject: [PATCH 6/6] Bump version to 4.9.0 --- CHANGELOG.md | 2 +- lib/govuk_app_config/version.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2071535b..58f5d48e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -# Unreleased +# 4.9.0 - Add GovukProxy::StaticProxy to forward Static asset requests by setting `GOVUK_PROXY_STATIC_ENABLED=true`.([#261](https://github.com/alphagov/govuk_app_config/pull/261)) diff --git a/lib/govuk_app_config/version.rb b/lib/govuk_app_config/version.rb index c425b603..2093e64c 100644 --- a/lib/govuk_app_config/version.rb +++ b/lib/govuk_app_config/version.rb @@ -1,3 +1,3 @@ module GovukAppConfig - VERSION = "4.8.0".freeze + VERSION = "4.9.0".freeze end