diff --git a/Gemfile.lock b/Gemfile.lock index 1a2acf88..2318c5f7 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -46,7 +46,7 @@ GEM io-event (~> 1.11) metrics (~> 0.12) traces (~> 0.18) - async-http (0.95.0) + async-http (0.95.1) async (>= 2.10.2) async-pool (~> 0.11) io-endpoint (~> 0.14) @@ -71,7 +71,7 @@ GEM climate_control (1.2.0) concurrent-ruby (1.3.6) connection_pool (3.0.2) - console (1.34.3) + console (1.36.0) fiber-annotation fiber-local (~> 1.1) json @@ -83,8 +83,8 @@ GEM diff-lcs (1.6.2) docile (1.4.1) drb (2.2.3) - dry-configurable (1.3.0) - dry-core (~> 1.1) + dry-configurable (1.4.0) + dry-core (~> 1.0) zeitwerk (~> 2.6) dry-core (1.2.0) concurrent-ruby (~> 1.0) @@ -129,14 +129,14 @@ GEM faraday-gzip (3.1.0) faraday (>= 2.0, < 3) zlib (~> 3.0) - faraday-net_http (3.4.2) + faraday-net_http (3.4.4) net-http (~> 0.5) fiber-annotation (0.2.0) fiber-local (1.1.0) fiber-storage fiber-storage (1.0.1) hashdiff (1.2.1) - html2rss (0.20.0) + html2rss (0.20.1) addressable (~> 2.7) brotli dry-validation @@ -159,14 +159,14 @@ GEM concurrent-ruby (~> 1.0) io-console (0.8.2) io-endpoint (0.17.2) - io-event (1.15.1) + io-event (1.16.1) io-stream (0.13.0) irb (1.18.0) pp (>= 0.6.0) prism (>= 1.3.0) rdoc (>= 4.0.0) reline (>= 0.4.2) - json (2.19.5) + json (2.19.9) kramdown (2.5.2) rexml (>= 3.4.4) language_server-protocol (3.17.0.5) @@ -222,7 +222,7 @@ GEM protocol-http (~> 0.58) rack (>= 1.0) protocol-url (0.4.0) - protocol-websocket (0.21.0) + protocol-websocket (0.21.1) protocol-http (~> 0.2) psych (5.3.1) date @@ -288,7 +288,7 @@ GEM rails-dom-testing rspec-core rspec-support (3.13.7) - rss (0.3.2) + rss (0.3.3) rexml rubocop (1.86.1) json (~> 2.3) @@ -404,7 +404,7 @@ CHECKSUMS addressable (2.9.0) sha256=7fdf6ac3660f7f4e867a0838be3f6cf722ace541dd97767fa42bc6cfa980c7af ast (2.4.3) sha256=954615157c1d6a382bc27d690d973195e79db7f55e9765ac7c481c60bdb4d383 async (2.39.0) sha256=df18730073f2bbb45788077dfa20cb365ecc1b9453969f44de6796b5191a00aa - async-http (0.95.0) sha256=08128cab255a48e41d1e856bfa9cbda001f1c57c88bafa3fa3a545ad795754aa + async-http (0.95.1) sha256=0c3dd458c204c06d5c4b20b01bbec4794a1203db627fb2ce536e1799ec14786c async-pool (0.11.2) sha256=0a43a17b02b04d9c451b7d12fafa9a50e55dc6dd00d4369aca00433f16a7e3ed async-websocket (0.30.0) sha256=55739954528ad8f87f7792d0452e1268d1ef2aa5b3719f79400a05a1a6202cdf base64 (0.3.0) sha256=27337aeabad6ffae05c265c450490628ef3ebd4b67be58257393227588f5a97b @@ -414,14 +414,14 @@ CHECKSUMS climate_control (1.2.0) sha256=36b21896193fa8c8536fa1cd843a07cf8ddbd03aaba43665e26c53ec1bd70aa5 concurrent-ruby (1.3.6) sha256=6b56837e1e7e5292f9864f34b69c5a2cbc75c0cf5338f1ce9903d10fa762d5ab connection_pool (3.0.2) sha256=33fff5ba71a12d2aa26cb72b1db8bba2a1a01823559fb01d29eb74c286e62e0a - console (1.34.3) sha256=869fbd74697efc4c606f102d2812b0b008e4e7fd738a91c591e8577140ec0dcc + console (1.36.0) sha256=45599ea906cf80a73d8941f03abf873fe66a6a954e0bac5bc1c01e2cdc406f07 crack (1.0.1) sha256=ff4a10390cd31d66440b7524eb1841874db86201d5b70032028553130b6d4c7e crass (1.0.6) sha256=dc516022a56e7b3b156099abc81b6d2b08ea1ed12676ac7a5657617f012bd45d date (3.5.1) sha256=750d06384d7b9c15d562c76291407d89e368dda4d4fff957eb94962d325a0dc0 diff-lcs (1.6.2) sha256=9ae0d2cba7d4df3075fe8cd8602a8604993efc0dfa934cff568969efb1909962 docile (1.4.1) sha256=96159be799bfa73cdb721b840e9802126e4e03dfc26863db73647204c727f21e drb (2.2.3) sha256=0b00d6fdb50995fe4a45dea13663493c841112e4068656854646f418fda13373 - dry-configurable (1.3.0) sha256=882d862858567fc1210d2549d4c090f34370fc1bb7c5c1933de3fe792e18afa8 + dry-configurable (1.4.0) sha256=e35d1b5f3c081753ef361f564919db79000f32cfa6f20ee3a3ba5921b41b73ce dry-core (1.2.0) sha256=0cc5a7da88df397f153947eeeae42e876e999c1e30900f3c536fb173854e96a1 dry-inflector (1.3.1) sha256=7fb0c2bb04f67638f25c52e7ba39ab435d922a3a5c3cd196120f63accb682dcc dry-initializer (3.2.0) sha256=37d59798f912dc0a1efe14a4db4a9306989007b302dcd5f25d0a2a20c166c4e3 @@ -434,20 +434,20 @@ CHECKSUMS faraday (2.14.2) sha256=73ccb9994a9e8648f010e32eca2ae82e41c57860aa10932cda29418b9e0223ad faraday-follow_redirects (0.5.0) sha256=5cde93c894b30943a5d2b93c2fe9284216a6b756f7af406a1e55f211d97d10ad faraday-gzip (3.1.0) sha256=320783690be169f9b7ddde11598b77156951343753f66a9ab98b1f6694433ff8 - faraday-net_http (3.4.2) sha256=f147758260d3526939bf57ecf911682f94926a3666502e24c69992765875906c + faraday-net_http (3.4.4) sha256=0e78af151747ed1b00f33e25973b4bc220d7f16c00c39676817c8b12331eb588 fiber-annotation (0.2.0) sha256=7abfadf1d119f508867d4103bf231c0354d019cc39a5738945dec2edadaf6c03 fiber-local (1.1.0) sha256=c885f94f210fb9b05737de65d511136ea602e00c5105953748aa0f8793489f06 fiber-storage (1.0.1) sha256=f48e5b6d8b0be96dac486332b55cee82240057065dc761c1ea692b2e719240e1 hashdiff (1.2.1) sha256=9c079dbc513dfc8833ab59c0c2d8f230fa28499cc5efb4b8dd276cf931457cd1 - html2rss (0.20.0) sha256=88454f78ce125234f2934b969f18c4d2e3de1884d773a355c62e0b99ad2b7588 + html2rss (0.20.1) sha256=2badcdc409a95ea312470a77690b7579d0f1788ef9c817d0ba1b2ac5a121b46f html2rss-configs (0.2.0) i18n (1.14.8) sha256=285778639134865c5e0f6269e0b818256017e8cde89993fdfcbfb64d088824a5 io-console (0.8.2) sha256=d6e3ae7a7cc7574f4b8893b4fca2162e57a825b223a177b7afa236c5ef9814cc io-endpoint (0.17.2) sha256=3feaf766c116b35839c11fac68b6aaadc47887bb488902a57bf8e1d288fb3338 - io-event (1.15.1) sha256=c644cdcf48254015d63f558bf4492f35471f5bb204a42180ea49752be59b30cc + io-event (1.16.1) sha256=641686f1e919a4890f788b86393026f8ef1394ee4af4d2ab9c24c81e237736ed io-stream (0.13.0) sha256=ce24bccb302bdf3ecedef05e8669a687b461621a498d83622fdcab549c9c1636 irb (1.18.0) sha256=de9454a0703a54704b9811a5ef31a60c86949fbf4013fcf244fabc7c775248e3 - json (2.19.5) sha256=218a18553e4801d579ca7e0f5bc72bafd776d7397238a1fb4e74db5b0a812c59 + json (2.19.9) sha256=9b9025b7cdddafa38d316eca0b2358488e42d417045c1b90d216a9fefe46b79a kramdown (2.5.2) sha256=1ba542204c66b6f9111ff00dcc26075b95b220b07f2905d8261740c82f7f02fa language_server-protocol (3.17.0.5) sha256=fd1e39a51a28bf3eec959379985a72e296e9f9acfce46f6a79d31ca8760803cc lint_roller (1.1.0) sha256=2c0c845b632a7d172cb849cc90c1bce937a28c5c8ccccb50dfd46a485003cc87 @@ -478,7 +478,7 @@ CHECKSUMS protocol-http2 (0.26.0) sha256=bac89cd78082b241ccd0cf7246f5160e4bb0c9c975fb4bf7deef5f88cc317486 protocol-rack (0.22.1) sha256=1185d245927ef9849a603700d6991ca353bc89724fbf98efa4a4333ed62a9fc3 protocol-url (0.4.0) sha256=64d4c03b6b51ad815ac6fdaf77a1d91e5baf9220d26becb846c5459dacdea9e1 - protocol-websocket (0.21.0) sha256=6e2ccc2adf7de1895b0f6548fdfacf5f9735c0d4deb56cd2bac1ae38a1952e93 + protocol-websocket (0.21.1) sha256=34325e4325697f0956877e67784bcc838cfd51ebbf4f8e9e5201be292041ee61 psych (5.3.1) sha256=eb7a57cef10c9d70173ff74e739d843ac3b2c019a003de48447b2963d81b1974 public_suffix (7.0.5) sha256=1a8bb08f1bbea19228d3bed6e5ed908d1cb4f7c2726d18bd9cadf60bc676f623 puma (8.0.2) sha256=c8ed871dfbbe66448ea9ffd46692342d9804d4071522b52b5331b7b6e7b686fb @@ -506,7 +506,7 @@ CHECKSUMS rspec-mocks (3.13.8) sha256=086ad3d3d17533f4237643de0b5c42f04b66348c28bf6b9c2d3f4a3b01af1d47 rspec-openapi (0.25.1) sha256=ba3c4ac5e04f176131751c5b9e02cb8a49d59eafedddee7c779d66fbf8f29c6b rspec-support (3.13.7) sha256=0640e5570872aafefd79867901deeeeb40b0c9875a36b983d85f54fb7381c47c - rss (0.3.2) sha256=3bd0446d32d832cda00ba07f4b179401f903b52ea1fdaac0f1f08de61a501efa + rss (0.3.3) sha256=37ef1ec4d691d67edbe92159079a4e89a0965e6a6b32246009ae3d734d12d1ab rubocop (1.86.1) sha256=44415f3f01d01a21e01132248d2fd0867572475b566ca188a0a42133a08d4531 rubocop-ast (1.49.1) sha256=4412f3ee70f6fe4546cc489548e0f6fcf76cafcfa80fa03af67098ffed755035 rubocop-performance (1.26.1) sha256=cd19b936ff196df85829d264b522fd4f98b6c89ad271fa52744a8c11b8f71834 diff --git a/app/web/boot/setup.rb b/app/web/boot/setup.rb index f06718ac..55ac05b3 100644 --- a/app/web/boot/setup.rb +++ b/app/web/boot/setup.rb @@ -61,8 +61,12 @@ def configure_request_service! return unless Rack::Timeout.respond_to?(:service_timeout=) Rack::Timeout.service_timeout = - Html2rss::RequestService::Policy::DEFAULTS[:total_timeout_seconds] + - RACK_TIMEOUT_BUFFER_SECONDS + if ENV.key?('RACK_TIMEOUT_SERVICE_TIMEOUT') + Integer(ENV['RACK_TIMEOUT_SERVICE_TIMEOUT']) + else + Html2rss::RequestService::Policy::DEFAULTS[:total_timeout_seconds] + + RACK_TIMEOUT_BUFFER_SECONDS + end end # @return [void] diff --git a/docker-compose.yml b/docker-compose.yml index 21a94dad..5a8d4e57 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -19,6 +19,8 @@ services: HEALTH_CHECK_TOKEN: ${HEALTH_CHECK_TOKEN:?set HEALTH_CHECK_TOKEN} SENTRY_DSN: ${SENTRY_DSN:-} SENTRY_ENABLE_LOGS: ${SENTRY_ENABLE_LOGS:-false} + HTML2RSS_TOTAL_TIMEOUT_SECONDS: 25 + RACK_TIMEOUT_SERVICE_TIMEOUT: 30 BROWSERLESS_IO_WEBSOCKET_URL: ws://browserless:4002 BROWSERLESS_IO_API_TOKEN: ${BROWSERLESS_IO_API_TOKEN:?set BROWSERLESS_IO_API_TOKEN} # Trial runs use the image's bundled config/feeds.yml. diff --git a/spec/html2rss/web/boot/setup_spec.rb b/spec/html2rss/web/boot/setup_spec.rb index 5d0ffa3e..116b6081 100644 --- a/spec/html2rss/web/boot/setup_spec.rb +++ b/spec/html2rss/web/boot/setup_spec.rb @@ -46,6 +46,35 @@ expect(Rack::Timeout::Logger.logger).to be(Html2rss::Web::AppLogger.logger) end + describe 'Rack::Timeout service timeout' do + let(:timeout_holder) { { value: nil } } + + before do + stub_const('Rack::Timeout', Module.new) + Rack::Timeout.define_singleton_method(:service_timeout=) { |v| v } + allow(Rack::Timeout).to receive(:service_timeout=) { |v| timeout_holder[:value] = v } + stub_environment_validation + end + + it 'sets timeout from RACK_TIMEOUT_SERVICE_TIMEOUT if present' do + ClimateControl.modify(boot_env.merge('RACK_TIMEOUT_SERVICE_TIMEOUT' => '42')) do + described_class.call! + end + + expect(timeout_holder[:value]).to eq(42) + end + + it 'sets timeout from gem default + buffer if RACK_TIMEOUT_SERVICE_TIMEOUT is absent' do + ClimateControl.modify(boot_env.merge('RACK_TIMEOUT_SERVICE_TIMEOUT' => nil)) do + described_class.call! + end + + expected = Html2rss::RequestService::Policy::DEFAULTS[:total_timeout_seconds] + + described_class::RACK_TIMEOUT_BUFFER_SECONDS + expect(timeout_holder[:value]).to eq(expected) + end + end + it 'captures and scrubs sensitive env vars after validation', :aggregate_failures do expect_sensitive_env_during_validation