Class: Capsium::Reactor

Inherits:
Object
  • Object
show all
Includes:
Serving
Defined in:
sig/capsium/reactor.rbs,
lib/capsium/reactor.rb,
lib/capsium/reactor/deploy.rb,
lib/capsium/reactor/oauth2.rb,
lib/capsium/reactor/serving.rb,
lib/capsium/reactor/session.rb,
lib/capsium/reactor/htpasswd.rb,
lib/capsium/reactor/authenticator.rb,
lib/capsium/reactor/introspection.rb,
sig/capsium/reactor/deploy.rbs,
sig/capsium/reactor/oauth2.rbs,
sig/capsium/reactor/serving.rbs,
sig/capsium/reactor/session.rbs,
sig/capsium/reactor/htpasswd.rbs,
sig/capsium/reactor/authenticator.rbs,
sig/capsium/reactor/introspection.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: Serving Classes: Authenticator, Deploy, Htpasswd, Introspection, OAuth2, Session

Constant Summary collapse

DEFAULT_PORT =

Returns:

  • (Integer)
8864
DEFAULT_CACHE_CONTROL =

Returns:

  • (String)
"public, max-age=31536000"

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Serving

#content_type_for, #headers_for, #inherited_processing, #serve_dataset, #serve_file, #serve_route

Constructor Details

#initialize(package:, port: DEFAULT_PORT, cache_control: DEFAULT_CACHE_CONTROL, do_not_listen: false, store: nil, deploy: nil) ⇒ Reactor

Returns a new instance of Reactor.



26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/capsium/reactor.rb', line 26

def initialize(package:, port: DEFAULT_PORT,
               cache_control: DEFAULT_CACHE_CONTROL, do_not_listen: false,
               store: nil, deploy: nil)
  @package = package.is_a?(String) ? Package.new(package, store: store) : package
  @package_path = @package.path
  @store = store
  @port = port
  @cache_control = cache_control
  @deploy_config = Deploy.load(deploy)
  setup_server(do_not_listen)
  load_state
  mount_routes
end

Instance Attribute Details

#authenticatorAuthenticator (readonly)

Returns the value of attribute authenticator.

Returns:



23
24
25
# File 'lib/capsium/reactor.rb', line 23

def authenticator
  @authenticator
end

#cache_controlString? (readonly)

Returns the value of attribute cache_control.

Returns:

  • (String, nil)


23
24
25
# File 'lib/capsium/reactor.rb', line 23

def cache_control
  @cache_control
end

#introspectionIntrospection (readonly)

Returns the value of attribute introspection.

Returns:



23
24
25
# File 'lib/capsium/reactor.rb', line 23

def introspection
  @introspection
end

#packagePackage (readonly)

Returns the value of attribute package.

Returns:



23
24
25
# File 'lib/capsium/reactor.rb', line 23

def package
  @package
end

#package_pathString (readonly)

Returns the value of attribute package_path.

Returns:

  • (String)


23
24
25
# File 'lib/capsium/reactor.rb', line 23

def package_path
  @package_path
end

#portInteger (readonly)

Returns the value of attribute port.

Returns:

  • (Integer)


23
24
25
# File 'lib/capsium/reactor.rb', line 23

def port
  @port
end

#routesPackage::Routes (readonly)

Returns the value of attribute routes.

Returns:



23
24
25
# File 'lib/capsium/reactor.rb', line 23

def routes
  @routes
end

#serverObject (readonly)

Returns the value of attribute server.

Returns:

  • (Object)


23
24
25
# File 'lib/capsium/reactor.rb', line 23

def server
  @server
end

#server_threadThread? (readonly)

Returns the value of attribute server_thread.

Returns:

  • (Thread, nil)


23
24
25
# File 'lib/capsium/reactor.rb', line 23

def server_thread
  @server_thread
end

Class Method Details

.secure_compare(own, theirs) ⇒ Boolean

Constant-time string comparison (length-check first).

Parameters:

  • own (String)
  • theirs (String)

Returns:

  • (Boolean)


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

#handle_request(request, response) ⇒ Object

Parameters:

  • request (Object)
  • response (Object)

Returns:

  • (Object)


46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/capsium/reactor.rb', line 46

def handle_request(request, response)
  if @authenticator.endpoint?(request.path)
    @authenticator.serve_endpoint(request, response)
    return
  end

  identity = @authenticator.authenticate(request)
  return @authenticator.challenge(response) if @authenticator.enabled? && identity.nil?
  return serve_introspection(request, response) if @introspection.endpoint?(request.path)

  route = @routes.resolve(request.path)
  return respond_not_found(response) unless route

  case @authenticator.authorize(identity, route.access_control)
  when :unauthenticated then return @authenticator.challenge(response)
  when :forbidden then return respond_forbidden(response)
  end

  serve_route(route, response)
end

#mount_routesvoid

This method returns an undefined value.



67
68
69
70
71
72
73
# File 'lib/capsium/reactor.rb', line 67

def mount_routes
  paths = @routes.config.routes.map(&:serving_path) +
          Introspection::PATHS + @authenticator.endpoints
  paths.each do |path|
    @server.mount_proc(path.to_s) { |req, res| handle_request(req, res) }
  end
end

#restart_serverThread

Returns:

  • (Thread)


75
76
77
78
79
80
81
82
# File 'lib/capsium/reactor.rb', line 75

def restart_server
  @server.shutdown
  @server_thread&.join
  load_package
  setup_server(false)
  mount_routes
  @server_thread = start_server
end

#serveObject

Returns:

  • (Object)


40
41
42
43
44
# File 'lib/capsium/reactor.rb', line 40

def serve
  trap("INT") { shutdown_server }
  @server_thread = start_server
  start_listener
end