read-only-mode 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 789458ccf4c3a3659e0f5ff50b69f5ce25dec31eedf1d6828b58b57bbb14c3eb
4
+ data.tar.gz: 33b10e31a9daf2d6a5d02ff77672781adb199571149d44b0ad3c7f3327bca895
5
+ SHA512:
6
+ metadata.gz: 05e8f74a2c93cbf9e4c907e80b24c4c2f81644adf166642d419f77d27fb765595c2fc22a8009b32e3eaf841adba5e0eefef0ce0e6ae0e3942f699862c64f57ae
7
+ data.tar.gz: c8dcc9577f73b9652f77f7dd9efe348926dca038b71eaad7a56fc988b8af23fe0342157f73f166148f79b92299c47e766856f177388992461217e0e1aa14f9e6
data/CHANGELOG.md ADDED
@@ -0,0 +1,5 @@
1
+ # Changelog
2
+
3
+ ## 0.1.0
4
+
5
+ - Initial release
data/README.md ADDED
@@ -0,0 +1,42 @@
1
+ # Read Only Mode
2
+
3
+ A simple ruby gem for adding read only maintenance mode to your Rails / Rack applications.
4
+
5
+ When read only mode is enabled, all non GET / HEAD requests will be rejected with a 503 Service Unavailable response. Additionally the 503 response will be given in case a GET request would raise a `PG::ReadOnlySqlTransaction` error.
6
+
7
+ ## Installation
8
+
9
+ Add the line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem "read_only_mode"
13
+ ```
14
+
15
+ ## Usage
16
+
17
+ Read only mode is enabled via environment variables. There are two options, either:
18
+
19
+ Set `READ_ONLY_MODE=true`
20
+
21
+ Or...
22
+
23
+ Set `PGOPTIONS="-c default_transaction_read_only=on"` (or any other string containing `default_transaction_read_only=on`).
24
+
25
+ The `PGOPTIONS` approach is recommended for applications using Postgres as this will prevent any write queries from being executed.
26
+
27
+ ### Rack integration
28
+
29
+ Rails applications will automatically use the middleware via a Railtie. For other Rack applications, you can add the middleware manually:
30
+
31
+ ```ruby
32
+ use ReadOnlyMode::Middleware if ReadOnlyMode.enabled?
33
+ ```
34
+
35
+ ## Configuration
36
+
37
+ You can customize the HTML / JSON responses returned when read only mode is enabled via some simple setters:
38
+
39
+ ```ruby
40
+ ReadOnlyMode.html_response = File.read("path/to/your/read_only.html")
41
+ ReadOnlyMode.json_response = { error: "Maintenance in progress" }.to_json
42
+ ```
data/lib/middleware.rb ADDED
@@ -0,0 +1,28 @@
1
+ module ReadOnlyMode
2
+ class Middleware
3
+ def initialize(app)
4
+ @app = app
5
+ end
6
+
7
+ def call(env)
8
+ if env["REQUEST_METHOD"] == "GET" || env["REQUEST_METHOD"] == "HEAD"
9
+ @app.call(env)
10
+ else
11
+ render_503(env)
12
+ end
13
+ rescue PG::ReadOnlySqlTransaction
14
+ render_503(env)
15
+ end
16
+
17
+ private
18
+
19
+ # 503 Service Unavailable with HTML or JSON depending on accept header
20
+ def render_503(env)
21
+ if env["HTTP_ACCEPT"] == "application/json"
22
+ [503, { "content-type" => "application/json; charset=utf-8" }, [ReadOnlyMode.json_response]]
23
+ else
24
+ [503, { "content-type" => "text/html; charset=utf-8" }, [ReadOnlyMode.html_response]]
25
+ end
26
+ end
27
+ end
28
+ end
data/lib/railtie.rb ADDED
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ReadOnlyMode
4
+ class Railtie < Rails::Railtie
5
+ initializer "read-only-mode.configure_rails_initialization" do |app|
6
+ app.middleware.insert_before 0, ReadOnlyMode::Middleware if ReadOnlyMode.enabled?
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,14 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Read-only maintenance in progress</title>
5
+ </head>
6
+ <body style="height: 100vh; background: linear-gradient(198deg, rgba(242,242,242,1) 0%, rgba(239,251,255,1) 100%); font-family: sans-serif; text-align: center;">
7
+ <div style="display: flex; height: 100vh">
8
+ <div style="margin: auto; height: 250px;">
9
+ <h1 style="font-weight: 200; color: #2c3647">Maintenance in progress</h1>
10
+ <p style="line-height: 1.8rem; color: #555a64">This app is undergoing maintenance right now.<br>Some actions are unavailable.<br>Please check back later 🙏</p>
11
+ </div>
12
+ </div>
13
+ </body>
14
+ </html>
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "json"
4
+
5
+ module ReadOnlyMode
6
+ DEFALT_HTML_RESPONSE = File.read(File.expand_path("read-only-mode.html", __dir__))
7
+ DEFAULT_JSON_RESPONSE = { error: "Application is in read-only maintenance mode. Please try again later." }.to_json
8
+
9
+ def self.enabled?
10
+ ENV["READ_ONLY_MODE"] == "true" || ENV["PGOPTIONS"]&.include?("default_transaction_read_only=on")
11
+ end
12
+
13
+ def self.html_response=(html_response)
14
+ @html_response = html_response
15
+ end
16
+
17
+ def self.html_response
18
+ @html_response ||= DEFALT_HTML_RESPONSE
19
+ end
20
+
21
+ def self.json_response=(json_response)
22
+ @json_response = json_response
23
+ end
24
+
25
+ def self.json_response
26
+ @json_response ||= DEFAULT_JSON_RESPONSE
27
+ end
28
+ end
29
+
30
+ require_relative "middleware"
31
+ require_relative "railtie" if defined? Rails::Railtie
@@ -0,0 +1,17 @@
1
+ Gem::Specification.new do |spec|
2
+ spec.name = "read-only-mode"
3
+ spec.version = "0.1.0"
4
+ spec.authors = ["David Backeus"]
5
+ spec.email = ["david.backeus@mynewsdesk.com"]
6
+ spec.summary = "Simple read-only maintenance mode for Rails and Rack based web applications"
7
+ spec.homepage = "https://github.com/reclaim-the-stack/read-only-mode"
8
+ spec.license = "MIT"
9
+ spec.metadata = {
10
+ "homepage_uri" => spec.homepage,
11
+ "source_code_uri" => spec.homepage,
12
+ "changelog_uri" => "#{spec.homepage}/blob/master/CHANGELOG.md"
13
+ }
14
+ spec.files = %w[README.md CHANGELOG.md read-only-mode.gemspec] + Dir["lib/**/*"]
15
+
16
+ spec.required_ruby_version = ">= 2.7.0"
17
+ end
metadata ADDED
@@ -0,0 +1,53 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: read-only-mode
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - David Backeus
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2024-02-06 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description:
14
+ email:
15
+ - david.backeus@mynewsdesk.com
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - CHANGELOG.md
21
+ - README.md
22
+ - lib/middleware.rb
23
+ - lib/railtie.rb
24
+ - lib/read-only-mode.html
25
+ - lib/read-only-mode.rb
26
+ - read-only-mode.gemspec
27
+ homepage: https://github.com/reclaim-the-stack/read-only-mode
28
+ licenses:
29
+ - MIT
30
+ metadata:
31
+ homepage_uri: https://github.com/reclaim-the-stack/read-only-mode
32
+ source_code_uri: https://github.com/reclaim-the-stack/read-only-mode
33
+ changelog_uri: https://github.com/reclaim-the-stack/read-only-mode/blob/master/CHANGELOG.md
34
+ post_install_message:
35
+ rdoc_options: []
36
+ require_paths:
37
+ - lib
38
+ required_ruby_version: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: 2.7.0
43
+ required_rubygems_version: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ requirements: []
49
+ rubygems_version: 3.5.0.dev
50
+ signing_key:
51
+ specification_version: 4
52
+ summary: Simple read-only maintenance mode for Rails and Rack based web applications
53
+ test_files: []