Class: Capsium::Reactor
- Inherits:
-
Object
- Object
- Capsium::Reactor
- Defined in:
- sig/capsium/reactor.rbs,
lib/capsium/reactor.rb,
lib/capsium/reactor/mount.rb,
lib/capsium/reactor/deploy.rb,
lib/capsium/reactor/oauth2.rb,
lib/capsium/reactor/metrics.rb,
lib/capsium/reactor/overlay.rb,
lib/capsium/reactor/serving.rb,
lib/capsium/reactor/session.rb,
lib/capsium/reactor/data_api.rb,
lib/capsium/reactor/htpasswd.rb,
lib/capsium/reactor/endpoints.rb,
lib/capsium/reactor/responses.rb,
lib/capsium/reactor/content_api.rb,
lib/capsium/reactor/graphql_api.rb,
lib/capsium/reactor/authenticator.rb,
lib/capsium/reactor/introspection.rb,
lib/capsium/reactor/package_saver.rb,
lib/capsium/reactor/graphql_schema.rb,
sig/capsium/reactor/mount.rbs,
sig/capsium/reactor/deploy.rbs,
sig/capsium/reactor/oauth2.rbs,
sig/capsium/reactor/metrics.rbs,
sig/capsium/reactor/overlay.rbs,
sig/capsium/reactor/serving.rbs,
sig/capsium/reactor/session.rbs,
sig/capsium/reactor/data_api.rbs,
sig/capsium/reactor/htpasswd.rbs,
sig/capsium/reactor/endpoints.rbs,
sig/capsium/reactor/responses.rbs,
sig/capsium/reactor/content_api.rbs,
sig/capsium/reactor/graphql_api.rbs,
sig/capsium/reactor/authenticator.rbs,
sig/capsium/reactor/introspection.rbs,
sig/capsium/reactor/package_saver.rbs,
sig/capsium/reactor/graphql_schema.rbs
Overview
Rack-free WEBrick reactor: serves the package routes plus the Monitoring HTTP API (ARCHITECTURE.md section 7) and reloads the package on filesystem changes.
Defined Under Namespace
Modules: Endpoints, Responses, Serving Classes: Authenticator, ContentApi, DataApi, Deploy, GraphqlApi, GraphqlSchema, Htpasswd, Introspection, Metrics, Mount, MountConflictError, OAuth2, Overlay, PackageSaver, Session
Constant Summary collapse
- DEFAULT_PORT =
8864- DEFAULT_CACHE_CONTROL =
"public, max-age=31536000"- PACKAGE_SAVE_PATTERN =
%r{\A/package/(?<name>[^/]+)/save\z}
Instance Attribute Summary collapse
-
#authenticator ⇒ Authenticator
readonly
Returns the value of attribute authenticator.
-
#cache_control ⇒ String?
readonly
Returns the value of attribute cache_control.
-
#introspection ⇒ Introspection
readonly
Returns the value of attribute introspection.
-
#log_buffer ⇒ Capsium::LogBuffer
readonly
Returns the value of attribute log_buffer.
-
#metrics ⇒ Metrics
readonly
Returns the value of attribute metrics.
-
#mounts ⇒ Array[Mount]
readonly
Returns the value of attribute mounts.
-
#package ⇒ Package
readonly
Returns the value of attribute package.
-
#package_path ⇒ String
readonly
Returns the value of attribute package_path.
-
#port ⇒ Integer
readonly
Returns the value of attribute port.
-
#registry ⇒ Capsium::Registry, ...
readonly
Returns the value of attribute registry.
-
#routes ⇒ Package::Routes
readonly
Returns the value of attribute routes.
-
#server ⇒ Object
readonly
Returns the value of attribute server.
-
#server_thread ⇒ Thread?
readonly
Returns the value of attribute server_thread.
-
#started_at ⇒ Time
readonly
Returns the value of attribute started_at.
-
#store ⇒ Package::Store, ...
readonly
Returns the value of attribute store.
-
#workdir ⇒ String
readonly
Returns the value of attribute workdir.
Class Method Summary collapse
-
.secure_compare(own, theirs) ⇒ Boolean
Constant-time string comparison (length-check first).
Instance Method Summary collapse
-
#cleanup ⇒ void
Cleans up every mounted package (Package#cleanup for all) and the workdir when the reactor created it.
-
#handle_request(request, response) ⇒ Object
Entry point for every mounted path: dispatches the request, then records it in the request metrics and the log buffer.
-
#initialize(package: nil, mounts: nil, port: DEFAULT_PORT, cache_control: DEFAULT_CACHE_CONTROL, do_not_listen: false, store: nil, deploy: nil, registry: nil, workdir: nil) ⇒ Reactor
constructor
Serves one or more packages: either a single
package(directory, .cap file or Package, mounted at "/") or a list ofmounts(Reactor::Mount) resolved by longest-prefix matching. - #mount_routes ⇒ void
- #restart_server ⇒ Thread
- #serve ⇒ Object
Methods included from Serving
#authorized?, #content_type_for, #headers_for, #inherited_processing, #mounts_by_length, #record_request, #resolve_mount, #root_mount, #serve_content_api, #serve_data_api, #serve_dataset, #serve_file, #serve_mounted_request, #serve_route
Methods included from Responses
#respond_error, #respond_forbidden, #respond_json, #respond_method_not_allowed, #respond_not_found, #respond_not_implemented, #respond_text
Methods included from Endpoints
#serve_introspection, #serve_package_save
Constructor Details
#initialize(package: nil, mounts: nil, port: DEFAULT_PORT, cache_control: DEFAULT_CACHE_CONTROL, do_not_listen: false, store: nil, deploy: nil, registry: nil, workdir: nil) ⇒ Reactor
Serves one or more packages: either a single package (directory,
.cap file or Package, mounted at "/") or a list of mounts
(Reactor::Mount) resolved by longest-prefix matching. workdir
holds the writable overlays (ARCHITECTURE.md section 5a) and
saved packages; it defaults to a temporary directory the reactor
removes on cleanup.
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
# File 'lib/capsium/reactor.rb', line 63 def initialize(package: nil, mounts: nil, port: DEFAULT_PORT, cache_control: DEFAULT_CACHE_CONTROL, do_not_listen: false, store: nil, deploy: nil, registry: nil, workdir: nil) @store = store @registry = registry @workdir = workdir || Dir.mktmpdir("capsium-reactor-") @own_workdir = workdir.nil? @mounts = mounts || [Mount.new(path: Mount::ROOT_PATH, package: package, store: store, registry: registry)] @mounts.each { |mount| mount.attach_workdir(@workdir) } @port = port @cache_control = cache_control @started_at = Time.now @metrics = Metrics.new @log_buffer = Capsium::LogBuffer.new @deploy_config = Deploy.load(deploy) setup_server(do_not_listen) load_state mount_routes @log_buffer.add("reactor started: " \ "#{@mounts.map(&:summary).join(', ')} on port #{@port}") end |
Instance Attribute Details
#authenticator ⇒ Authenticator (readonly)
Returns the value of attribute authenticator.
52 53 54 |
# File 'lib/capsium/reactor.rb', line 52 def authenticator @authenticator end |
#cache_control ⇒ String? (readonly)
Returns the value of attribute cache_control.
52 53 54 |
# File 'lib/capsium/reactor.rb', line 52 def cache_control @cache_control end |
#introspection ⇒ Introspection (readonly)
Returns the value of attribute introspection.
52 53 54 |
# File 'lib/capsium/reactor.rb', line 52 def introspection @introspection end |
#log_buffer ⇒ Capsium::LogBuffer (readonly)
Returns the value of attribute log_buffer.
52 53 54 |
# File 'lib/capsium/reactor.rb', line 52 def log_buffer @log_buffer end |
#metrics ⇒ Metrics (readonly)
Returns the value of attribute metrics.
52 53 54 |
# File 'lib/capsium/reactor.rb', line 52 def metrics @metrics end |
#mounts ⇒ Array[Mount] (readonly)
Returns the value of attribute mounts.
52 53 54 |
# File 'lib/capsium/reactor.rb', line 52 def mounts @mounts end |
#package ⇒ Package (readonly)
Returns the value of attribute package.
52 53 54 |
# File 'lib/capsium/reactor.rb', line 52 def package @package end |
#package_path ⇒ String (readonly)
Returns the value of attribute package_path.
52 53 54 |
# File 'lib/capsium/reactor.rb', line 52 def package_path @package_path end |
#port ⇒ Integer (readonly)
Returns the value of attribute port.
52 53 54 |
# File 'lib/capsium/reactor.rb', line 52 def port @port end |
#registry ⇒ Capsium::Registry, ... (readonly)
Returns the value of attribute registry.
52 53 54 |
# File 'lib/capsium/reactor.rb', line 52 def registry @registry end |
#routes ⇒ Package::Routes (readonly)
Returns the value of attribute routes.
52 53 54 |
# File 'lib/capsium/reactor.rb', line 52 def routes @routes end |
#server ⇒ Object (readonly)
Returns the value of attribute server.
52 53 54 |
# File 'lib/capsium/reactor.rb', line 52 def server @server end |
#server_thread ⇒ Thread? (readonly)
Returns the value of attribute server_thread.
52 53 54 |
# File 'lib/capsium/reactor.rb', line 52 def server_thread @server_thread end |
#started_at ⇒ Time (readonly)
Returns the value of attribute started_at.
52 53 54 |
# File 'lib/capsium/reactor.rb', line 52 def started_at @started_at end |
#store ⇒ Package::Store, ... (readonly)
Returns the value of attribute store.
52 53 54 |
# File 'lib/capsium/reactor.rb', line 52 def store @store end |
#workdir ⇒ String (readonly)
Returns the value of attribute workdir.
52 53 54 |
# File 'lib/capsium/reactor.rb', line 52 def workdir @workdir end |
Class Method Details
.secure_compare(own, theirs) ⇒ Boolean
Constant-time string comparison (length-check first).
149 150 151 152 |
# File 'lib/capsium/reactor/htpasswd.rb', line 149 def self.secure_compare(own, theirs) own.bytesize == theirs.bytesize && OpenSSL.fixed_length_secure_compare(own, theirs) end |
Instance Method Details
#cleanup ⇒ void
This method returns an undefined value.
Cleans up every mounted package (Package#cleanup for all) and the workdir when the reactor created it.
124 125 126 127 |
# File 'lib/capsium/reactor.rb', line 124 def cleanup @mounts.each { |mount| mount.package.cleanup } FileUtils.remove_entry(@workdir) if @own_workdir && File.directory?(@workdir) end |
#handle_request(request, response) ⇒ Object
Entry point for every mounted path: dispatches the request, then records it in the request metrics and the log buffer.
94 95 96 97 98 |
# File 'lib/capsium/reactor.rb', line 94 def handle_request(request, response) dispatch_request(request, response) ensure record_request(request, response) end |
#mount_routes ⇒ void
This method returns an undefined value.
100 101 102 103 104 105 106 107 108 109 110 111 |
# File 'lib/capsium/reactor.rb', line 100 def mount_routes paths = Introspection::PATHS + Introspection::REACTOR_PATHS + @authenticator.endpoints paths.concat(@mounts.flat_map(&:server_paths)) paths.each do |path| @server.mount_proc(path.to_s) { |req, res| handle_request(req, res) } end # WEBrick longest-prefix matching: catches every "/package/...". @server.mount_proc(Introspection::PACKAGE_MOUNT) do |req, res| handle_request(req, res) end end |
#restart_server ⇒ Thread
113 114 115 116 117 118 119 120 |
# File 'lib/capsium/reactor.rb', line 113 def restart_server @server.shutdown @server_thread&.join load_packages setup_server(false) mount_routes @server_thread = start_server end |
#serve ⇒ Object
86 87 88 89 90 |
# File 'lib/capsium/reactor.rb', line 86 def serve trap("INT") { shutdown_server } @server_thread = start_server start_listener end |