startback-websocket 0.14.0 → 0.14.1
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 +4 -4
- data/Gemfile +3 -2
- data/README.md +64 -9
- data/lib/startback/ext/context.rb +6 -0
- data/lib/startback/ext.rb +1 -2
- data/lib/startback/websocket/app.rb +82 -0
- data/lib/startback/websocket/hub/app.rb +28 -0
- data/lib/startback/websocket/hub/builder.rb +55 -0
- data/lib/startback/websocket/hub/errors.rb +9 -0
- data/lib/startback/websocket/hub/message.rb +29 -0
- data/lib/startback/websocket/hub/middleware/command_handler.rb +34 -0
- data/lib/startback/websocket/hub/middleware/room_handler.rb +30 -0
- data/lib/startback/websocket/hub/middleware.rb +12 -0
- data/lib/startback/websocket/hub/participant.rb +16 -0
- data/lib/startback/websocket/hub/room.rb +46 -0
- data/lib/startback/websocket/hub.rb +15 -0
- data/lib/startback/websocket.rb +8 -0
- data/spec/spec_helper.rb +21 -32
- data/spec/unit/hub/test_builder.rb +141 -0
- data/spec/unit/hub/test_room.rb +27 -0
- data/spec/unit/test_app.rb +35 -0
- data/tasks/test.rake +0 -1
- metadata +20 -91
- data/lib/startback/audit/prometheus.rb +0 -87
- data/lib/startback/audit/shared.rb +0 -17
- data/lib/startback/audit/trailer.rb +0 -129
- data/lib/startback/audit.rb +0 -3
- data/lib/startback/caching/entity_cache.rb +0 -157
- data/lib/startback/caching/no_store.rb +0 -28
- data/lib/startback/caching/store.rb +0 -34
- data/lib/startback/context/h_factory.rb +0 -43
- data/lib/startback/context/middleware.rb +0 -53
- data/lib/startback/context.rb +0 -122
- data/lib/startback/errors.rb +0 -197
- data/lib/startback/event/agent.rb +0 -84
- data/lib/startback/event/bus/bunny/async.rb +0 -162
- data/lib/startback/event/bus/bunny.rb +0 -1
- data/lib/startback/event/bus/memory/async.rb +0 -45
- data/lib/startback/event/bus/memory/sync.rb +0 -35
- data/lib/startback/event/bus/memory.rb +0 -2
- data/lib/startback/event/bus.rb +0 -100
- data/lib/startback/event/engine.rb +0 -94
- data/lib/startback/event/ext/context.rb +0 -5
- data/lib/startback/event/ext/operation.rb +0 -13
- data/lib/startback/event.rb +0 -47
- data/lib/startback/ext/date_time.rb +0 -9
- data/lib/startback/ext/time.rb +0 -9
- data/lib/startback/model.rb +0 -6
- data/lib/startback/operation/error_operation.rb +0 -19
- data/lib/startback/operation/multi_operation.rb +0 -28
- data/lib/startback/operation.rb +0 -78
- data/lib/startback/services.rb +0 -11
- data/lib/startback/support/data_object.rb +0 -71
- data/lib/startback/support/env.rb +0 -41
- data/lib/startback/support/fake_logger.rb +0 -18
- data/lib/startback/support/hooks.rb +0 -48
- data/lib/startback/support/log_formatter.rb +0 -34
- data/lib/startback/support/logger.rb +0 -34
- data/lib/startback/support/operation_runner.rb +0 -150
- data/lib/startback/support/robustness.rb +0 -157
- data/lib/startback/support/transaction_manager.rb +0 -25
- data/lib/startback/support/transaction_policy.rb +0 -33
- data/lib/startback/support/world.rb +0 -54
- data/lib/startback/support.rb +0 -26
- data/lib/startback/version.rb +0 -8
- data/lib/startback/web/api.rb +0 -99
- data/lib/startback/web/auto_caching.rb +0 -85
- data/lib/startback/web/catch_all.rb +0 -52
- data/lib/startback/web/cors_headers.rb +0 -80
- data/lib/startback/web/health_check.rb +0 -49
- data/lib/startback/web/magic_assets/ng_html_transformer.rb +0 -80
- data/lib/startback/web/magic_assets/rake_tasks.rb +0 -64
- data/lib/startback/web/magic_assets.rb +0 -98
- data/lib/startback/web/middleware.rb +0 -13
- data/lib/startback/web/prometheus.rb +0 -16
- data/lib/startback/web/shield.rb +0 -58
- data/lib/startback.rb +0 -43
- data/spec/unit/audit/test_prometheus.rb +0 -72
- data/spec/unit/audit/test_trailer.rb +0 -105
- data/spec/unit/caching/test_entity_cache.rb +0 -136
- data/spec/unit/context/test_abstraction_factory.rb +0 -64
- data/spec/unit/context/test_dup.rb +0 -42
- data/spec/unit/context/test_fork.rb +0 -37
- data/spec/unit/context/test_h_factory.rb +0 -31
- data/spec/unit/context/test_middleware.rb +0 -45
- data/spec/unit/context/test_with_world.rb +0 -20
- data/spec/unit/context/test_world.rb +0 -17
- data/spec/unit/event/bus/memory/test_async.rb +0 -43
- data/spec/unit/event/bus/memory/test_sync.rb +0 -43
- data/spec/unit/support/hooks/test_after_hook.rb +0 -54
- data/spec/unit/support/hooks/test_before_hook.rb +0 -54
- data/spec/unit/support/operation_runner/test_around_run.rb +0 -156
- data/spec/unit/support/operation_runner/test_before_after_call.rb +0 -48
- data/spec/unit/support/test_data_object.rb +0 -156
- data/spec/unit/support/test_env.rb +0 -75
- data/spec/unit/support/test_robusteness.rb +0 -229
- data/spec/unit/support/test_transaction_manager.rb +0 -64
- data/spec/unit/support/test_world.rb +0 -72
- data/spec/unit/test_event.rb +0 -62
- data/spec/unit/test_operation.rb +0 -55
- data/spec/unit/test_support.rb +0 -40
- data/spec/unit/web/fixtures/assets/app/hello.es6 +0 -4
- data/spec/unit/web/fixtures/assets/app/hello.html +0 -1
- data/spec/unit/web/fixtures/assets/index.es6 +0 -1
- data/spec/unit/web/test_api.rb +0 -82
- data/spec/unit/web/test_auto_caching.rb +0 -81
- data/spec/unit/web/test_catch_all.rb +0 -77
- data/spec/unit/web/test_cors_headers.rb +0 -88
- data/spec/unit/web/test_healthcheck.rb +0 -59
- data/spec/unit/web/test_magic_assets.rb +0 -82
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
module Startback
|
|
2
|
-
module Support
|
|
3
|
-
module TransactionPolicy
|
|
4
|
-
|
|
5
|
-
# Returns the operation's transaction policy
|
|
6
|
-
def transaction_policy
|
|
7
|
-
@transaction_policy || :before_call
|
|
8
|
-
end
|
|
9
|
-
|
|
10
|
-
# Sets the transaction policy to use. Valid values are:
|
|
11
|
-
# - before_call : the transaction is started by the operation
|
|
12
|
-
# runner, right before calling the #call method on operation
|
|
13
|
-
# instance
|
|
14
|
-
# - within_call: the transaction is started by the operation
|
|
15
|
-
# itself, as part of its internal logic.
|
|
16
|
-
def transaction_policy=(policy)
|
|
17
|
-
unless [:before_call, :within_call].include?(policy)
|
|
18
|
-
raise ArgumentError, "Unknown policy `#{policy}`"
|
|
19
|
-
end
|
|
20
|
-
@transaction_policy = policy
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
def after_commit(&bl)
|
|
24
|
-
after_call do
|
|
25
|
-
db.after_commit do
|
|
26
|
-
instance_exec(&bl)
|
|
27
|
-
end
|
|
28
|
-
end
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
end # module TransactionPolicy
|
|
32
|
-
end # module Support
|
|
33
|
-
end # module Startback
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
module Startback
|
|
2
|
-
module Support
|
|
3
|
-
class World
|
|
4
|
-
include DataObject
|
|
5
|
-
|
|
6
|
-
attr_accessor :_factory
|
|
7
|
-
protected :_factory=
|
|
8
|
-
|
|
9
|
-
def factory(who, &block)
|
|
10
|
-
dup.tap do |x|
|
|
11
|
-
x._factory = (self._factory || {}).merge(who => block)
|
|
12
|
-
end
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
attr_accessor :_scope
|
|
16
|
-
protected :_scope=
|
|
17
|
-
|
|
18
|
-
def with_scope(scope)
|
|
19
|
-
dup.tap do |x|
|
|
20
|
-
x._scope = scope
|
|
21
|
-
end
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
def with(hash)
|
|
25
|
-
dup.tap do |x|
|
|
26
|
-
x._data = to_data.merge(hash)
|
|
27
|
-
end
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
private
|
|
31
|
-
|
|
32
|
-
def _data_allow_camelize
|
|
33
|
-
false
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
def _data_allow_query
|
|
37
|
-
false
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
def _data_key_not_found(key)
|
|
41
|
-
raise Startback::Error, "Scope must be defined" unless s = _scope
|
|
42
|
-
|
|
43
|
-
block = (_factory || {})[key]
|
|
44
|
-
if block
|
|
45
|
-
factored = s.instance_exec(&block)
|
|
46
|
-
@_data = @_data.dup.merge(key => factored).freeze
|
|
47
|
-
[key, false]
|
|
48
|
-
else
|
|
49
|
-
nil
|
|
50
|
-
end
|
|
51
|
-
end
|
|
52
|
-
end # class World
|
|
53
|
-
end # module Support
|
|
54
|
-
end # module Startback
|
data/lib/startback/support.rb
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
module Startback
|
|
2
|
-
module Support
|
|
3
|
-
|
|
4
|
-
def logger
|
|
5
|
-
Startback::LOGGER
|
|
6
|
-
end
|
|
7
|
-
|
|
8
|
-
def deep_merge(h1, h2)
|
|
9
|
-
h1.merge(h2){|k,v1,v2|
|
|
10
|
-
v1.is_a?(Hash) && v2.is_a?(Hash) ? deep_merge(v1, v2) : v2
|
|
11
|
-
}
|
|
12
|
-
end
|
|
13
|
-
module_function :deep_merge
|
|
14
|
-
|
|
15
|
-
end # module Support
|
|
16
|
-
end # module Startback
|
|
17
|
-
require_relative 'support/env'
|
|
18
|
-
require_relative 'support/log_formatter'
|
|
19
|
-
require_relative 'support/logger'
|
|
20
|
-
require_relative 'support/robustness'
|
|
21
|
-
require_relative 'support/hooks'
|
|
22
|
-
require_relative 'support/operation_runner'
|
|
23
|
-
require_relative 'support/transaction_policy'
|
|
24
|
-
require_relative 'support/transaction_manager'
|
|
25
|
-
require_relative 'support/data_object'
|
|
26
|
-
require_relative 'support/world'
|
data/lib/startback/version.rb
DELETED
data/lib/startback/web/api.rb
DELETED
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
module Startback
|
|
2
|
-
module Web
|
|
3
|
-
class Api < Sinatra::Base
|
|
4
|
-
include Support
|
|
5
|
-
include Errors
|
|
6
|
-
|
|
7
|
-
set :raise_errors, true
|
|
8
|
-
set :show_exceptions, false
|
|
9
|
-
set :dump_errors, false
|
|
10
|
-
|
|
11
|
-
protected
|
|
12
|
-
|
|
13
|
-
###
|
|
14
|
-
### Facade over context
|
|
15
|
-
###
|
|
16
|
-
|
|
17
|
-
def context
|
|
18
|
-
env[Startback::Context::Middleware::RACK_ENV_KEY]
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
def with_context(ctx = nil)
|
|
22
|
-
old_context = self.context
|
|
23
|
-
new_context = ctx || self.context.dup
|
|
24
|
-
env[Startback::Context::Middleware::RACK_ENV_KEY] = new_context
|
|
25
|
-
result = ctx ? yield : yield(new_context)
|
|
26
|
-
env[Startback::Context::Middleware::RACK_ENV_KEY] = old_context
|
|
27
|
-
result
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
###
|
|
31
|
-
### Facade over third party tools
|
|
32
|
-
###
|
|
33
|
-
include Support::OperationRunner
|
|
34
|
-
|
|
35
|
-
def operation_world(op)
|
|
36
|
-
{ context: context }
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
###
|
|
40
|
-
### About the body / input
|
|
41
|
-
###
|
|
42
|
-
|
|
43
|
-
def loaded_body
|
|
44
|
-
@loaded_body ||= case ctype = request.content_type
|
|
45
|
-
when /json/
|
|
46
|
-
json_body
|
|
47
|
-
when /multipart\/form-data/
|
|
48
|
-
file = params[:file]
|
|
49
|
-
file_body file, Path(file[:filename]).extname
|
|
50
|
-
else
|
|
51
|
-
unsupported_media_type_error!(ctype)
|
|
52
|
-
end
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
def json_body(body = request.body.read)
|
|
56
|
-
JSON.load(body)
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
def file_body(file, ctype)
|
|
60
|
-
raise UnsupportedMediaTypeError, "Unable to use `#{ctype}` as input data"
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
###
|
|
64
|
-
### Various reusable responses
|
|
65
|
-
###
|
|
66
|
-
|
|
67
|
-
def serve_nothing
|
|
68
|
-
[ 204, {}, [] ]
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
def serve(entity_description, entity, ct = nil)
|
|
72
|
-
if entity.nil?
|
|
73
|
-
status 404
|
|
74
|
-
content_type :json
|
|
75
|
-
{ description: "#{entity_description} not found" }.to_json
|
|
76
|
-
elsif entity.respond_to?(:to_dto)
|
|
77
|
-
ct, body = entity.to_dto(context).to(env['HTTP_ACCEPT'], ct)
|
|
78
|
-
content_type ct
|
|
79
|
-
_serve(body)
|
|
80
|
-
elsif entity.is_a?(Path)
|
|
81
|
-
_serve(entity)
|
|
82
|
-
else
|
|
83
|
-
content_type ct || "application/json"
|
|
84
|
-
entity.to_json
|
|
85
|
-
end
|
|
86
|
-
end
|
|
87
|
-
|
|
88
|
-
def _serve(body)
|
|
89
|
-
case body
|
|
90
|
-
when Path
|
|
91
|
-
send_file(body)
|
|
92
|
-
else
|
|
93
|
-
body
|
|
94
|
-
end
|
|
95
|
-
end
|
|
96
|
-
|
|
97
|
-
end # class Api
|
|
98
|
-
end # module Web
|
|
99
|
-
end # module Startback
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
module Startback
|
|
2
|
-
module Web
|
|
3
|
-
#
|
|
4
|
-
# This rack middleware automatically mark response as non being cacheable
|
|
5
|
-
# in development, and being cacheble in production.
|
|
6
|
-
#
|
|
7
|
-
# The headers to set in development and production can be passed at
|
|
8
|
-
# construction, as well as whether the development environment must be
|
|
9
|
-
# forced. This class may also be configured through environment variables:
|
|
10
|
-
#
|
|
11
|
-
# - RACK_ENV: when "production" use the production headers, otherwise use
|
|
12
|
-
# the development ones
|
|
13
|
-
# - STARTBACK_AUTOCACHING_DEVELOPMENT_CACHE_CONTROL: Cache-Control header
|
|
14
|
-
# to use in development mode
|
|
15
|
-
# - STARTBACK_AUTOCACHING_PRODUCTION_CACHE_CONTROL: Cache-Control header
|
|
16
|
-
# to use in production mode
|
|
17
|
-
#
|
|
18
|
-
# Example:
|
|
19
|
-
#
|
|
20
|
-
# # Default configuration
|
|
21
|
-
# use Autocaching
|
|
22
|
-
#
|
|
23
|
-
# # Force development mode
|
|
24
|
-
# use Autocaching, true
|
|
25
|
-
#
|
|
26
|
-
# # Force production mode
|
|
27
|
-
# use Autocaching, false
|
|
28
|
-
#
|
|
29
|
-
# # Set production headers manually
|
|
30
|
-
# use Autocaching, { :production => "public, no-cache, no-store" }
|
|
31
|
-
#
|
|
32
|
-
class AutoCaching
|
|
33
|
-
|
|
34
|
-
# Cache-Control header to use in development mode
|
|
35
|
-
DEVELOPMENT_CACHE_CONTROL = ENV['STARTBACK_AUTOCACHING_DEVELOPMENT_CACHE_CONTROL'] || \
|
|
36
|
-
"no-cache, no-store, max-age=0, must-revalidate"
|
|
37
|
-
|
|
38
|
-
# Cache-Control header to use in produdction mode
|
|
39
|
-
PRODUCTION_CACHE_CONTROL = ENV['STARTBACK_AUTOCACHING_PRODUCTION_CACHE_CONTROL'] ||\
|
|
40
|
-
"public, must-revalidate, max-age=3600, s-max-age=3600"
|
|
41
|
-
|
|
42
|
-
def initialize(app, development = nil, cache_headers = {})
|
|
43
|
-
development, cache_headers = nil, development if development.is_a?(Hash)
|
|
44
|
-
@app = app
|
|
45
|
-
@development = development.nil? ? infer_is_development : development
|
|
46
|
-
@cache_headers = default_headers.merge(normalize_headers(cache_headers))
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
def call(env)
|
|
50
|
-
status, headers, body = @app.call(env)
|
|
51
|
-
[status, patch_response_headers(headers), body]
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
protected
|
|
55
|
-
|
|
56
|
-
def patch_response_headers(hs)
|
|
57
|
-
(development? ? @cache_headers[:development] : @cache_headers[:production]).merge(hs)
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
def development?
|
|
61
|
-
!!@development
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
def infer_is_development
|
|
65
|
-
ENV['RACK_ENV'] != "production"
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
def default_headers
|
|
69
|
-
{
|
|
70
|
-
development: {
|
|
71
|
-
"Cache-Control" => DEVELOPMENT_CACHE_CONTROL
|
|
72
|
-
},
|
|
73
|
-
production: {
|
|
74
|
-
"Cache-Control" => PRODUCTION_CACHE_CONTROL
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
end
|
|
78
|
-
|
|
79
|
-
def normalize_headers(h)
|
|
80
|
-
Hash[h.map{|k,v| [k, v.is_a?(Hash) ? v : {"Cache-Control" => v} ] }]
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
end # class AutoCaching
|
|
84
|
-
end # module Web
|
|
85
|
-
end # module Startback
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
module Startback
|
|
2
|
-
module Web
|
|
3
|
-
#
|
|
4
|
-
# This Rack middleware catches all exceptions that are raised by sublayers
|
|
5
|
-
# in the Rack chain. It converts them to correct 500 Errors, with a generic
|
|
6
|
-
# exception message encoded in json.
|
|
7
|
-
#
|
|
8
|
-
# This class aims at being used as top level of a Rack chain. It is not
|
|
9
|
-
# aimed at being subclassed.
|
|
10
|
-
#
|
|
11
|
-
# Fatal error cached are also sent as a `fatal` messange, on the error
|
|
12
|
-
# handler provided on Context#error_handler.fatal, if any.
|
|
13
|
-
#
|
|
14
|
-
# Examples:
|
|
15
|
-
#
|
|
16
|
-
# Rack::Builder.new do
|
|
17
|
-
# use Startback::Web::CatchAll
|
|
18
|
-
# end
|
|
19
|
-
#
|
|
20
|
-
class CatchAll < Rack::Robustness
|
|
21
|
-
include Errors
|
|
22
|
-
include Support::Robustness
|
|
23
|
-
|
|
24
|
-
FATAL_ERROR = {
|
|
25
|
-
code: "Startback::Errors::InternalServerError",
|
|
26
|
-
description: "An error occured, sorry"
|
|
27
|
-
}.to_json
|
|
28
|
-
|
|
29
|
-
self.catch_all
|
|
30
|
-
self.on(Exception)
|
|
31
|
-
self.status 500
|
|
32
|
-
self.content_type 'application/json'
|
|
33
|
-
self.body FATAL_ERROR
|
|
34
|
-
|
|
35
|
-
self.ensure(true) do |ex|
|
|
36
|
-
context = env[Context::Middleware::RACK_ENV_KEY]
|
|
37
|
-
begin
|
|
38
|
-
if context && context.respond_to?(:error_handler, true) && context.error_handler
|
|
39
|
-
context.error_handler.fatal(ex)
|
|
40
|
-
else
|
|
41
|
-
log(:fatal, self, "ensure", context, error: ex)
|
|
42
|
-
end
|
|
43
|
-
rescue => ex2
|
|
44
|
-
STDERR.puts(ex2.message)
|
|
45
|
-
STDERR.puts(ex2.backtrace[0..10].join("\n"))
|
|
46
|
-
raise
|
|
47
|
-
end
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
end # class CatchAll
|
|
51
|
-
end # class Web
|
|
52
|
-
end # module Startback
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
module Startback
|
|
2
|
-
module Web
|
|
3
|
-
#
|
|
4
|
-
# Sets Cross-Origin Response Headers on requests specifying an Origin
|
|
5
|
-
# HTTP header, according configuration passed at construction and/or
|
|
6
|
-
# environment variables.
|
|
7
|
-
#
|
|
8
|
-
# Example:
|
|
9
|
-
#
|
|
10
|
-
# # Default configuration, using environment variables when set
|
|
11
|
-
# use CorsHeaders
|
|
12
|
-
#
|
|
13
|
-
# # Force a bouncing of the origin, using the Origin request header
|
|
14
|
-
# # as Access-Control-Allow-Origin response header
|
|
15
|
-
# use CorsHeaders, bounce: true
|
|
16
|
-
#
|
|
17
|
-
# # Overrides a specific header
|
|
18
|
-
# use CorsHeaders, headers: { 'Access-Control-Allow-Methods' => 'POST' }
|
|
19
|
-
#
|
|
20
|
-
class CorsHeaders
|
|
21
|
-
|
|
22
|
-
ALLOW_ORIGIN = ENV['STARTBACK_CORS_ALLOW_ORIGIN'] || '*'
|
|
23
|
-
|
|
24
|
-
ALLOW_METHODS = ENV['STARTBACK_CORS_ALLOW_METHODS'] || 'OPTIONS, HEAD, GET, POST, PUT, PATCH, DELETE'
|
|
25
|
-
|
|
26
|
-
ALLOW_CREDENTIALS = ENV['STARTBACK_CORS_ALLOW_CREDENTIALS'] || 'true'
|
|
27
|
-
|
|
28
|
-
MAX_AGE = ENV['STARTBACK_CORS_MAX_AGE'] || '1728000'
|
|
29
|
-
|
|
30
|
-
ALLOW_HEADERS = ENV['STARTBACK_CORS_ALLOW_HEADERS'] || 'Authorization, Content-Type, Origin, Accept, If-Modified-Since, If-Match, If-None-Match'
|
|
31
|
-
|
|
32
|
-
EXPOSE_HEADERS = ENV['STARTBACK_CORS_EXPOSE_HEADERS'] || 'Location, ETag, Last-Modified, Content-Type'
|
|
33
|
-
|
|
34
|
-
DEFAULT_CORS_HEADERS = {
|
|
35
|
-
'Access-Control-Allow-Origin' => ALLOW_ORIGIN,
|
|
36
|
-
'Access-Control-Allow-Methods' => ALLOW_METHODS,
|
|
37
|
-
'Access-Control-Allow-Credentials' => ALLOW_CREDENTIALS,
|
|
38
|
-
'Access-Control-Max-Age' => MAX_AGE,
|
|
39
|
-
'Access-Control-Allow-Headers' => ALLOW_HEADERS,
|
|
40
|
-
'Access-Control-Expose-Headers' => EXPOSE_HEADERS
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
DEFAULT_OPTIONS = {
|
|
44
|
-
:headers => DEFAULT_CORS_HEADERS
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
def initialize(app, options = {})
|
|
48
|
-
@app = app
|
|
49
|
-
@options = Startback::Support.deep_merge(DEFAULT_OPTIONS, options)
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
def call(env)
|
|
53
|
-
status, headers, body = @app.call(env)
|
|
54
|
-
if origin = env['HTTP_ORIGIN']
|
|
55
|
-
headers = cors_headers(origin).merge(headers)
|
|
56
|
-
end
|
|
57
|
-
if env['REQUEST_METHOD'] == 'OPTIONS'
|
|
58
|
-
headers['Content-Length'] = '0'
|
|
59
|
-
status, headers, body = [204, headers, []]
|
|
60
|
-
end
|
|
61
|
-
[status, headers, body]
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
private
|
|
65
|
-
|
|
66
|
-
def cors_headers(origin)
|
|
67
|
-
headers = @options[:headers].dup
|
|
68
|
-
if bounce?
|
|
69
|
-
headers['Access-Control-Allow-Origin'] = origin
|
|
70
|
-
end
|
|
71
|
-
headers
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
def bounce?
|
|
75
|
-
@options[:bounce]
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
end # class AllowCors
|
|
79
|
-
end # class CorsHeaders
|
|
80
|
-
end # module Samback
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
module Startback
|
|
2
|
-
module Web
|
|
3
|
-
#
|
|
4
|
-
# Can be used to easily implement a HealthCheck web service inside a Startback
|
|
5
|
-
# application.
|
|
6
|
-
#
|
|
7
|
-
# Examples:
|
|
8
|
-
#
|
|
9
|
-
# # Returns a 204 with no body
|
|
10
|
-
# run Startback::Web::HealthCheck.new
|
|
11
|
-
#
|
|
12
|
-
# # Returns a 204 with no body
|
|
13
|
-
# run Startback::Web::HealthCheck.new { nil }
|
|
14
|
-
#
|
|
15
|
-
# # Returns a 200 with Ok in plain text
|
|
16
|
-
# run Startback::Web::HealthCheck.new { "Ok" }
|
|
17
|
-
#
|
|
18
|
-
# # Re-raises the exception
|
|
19
|
-
# run Startback::Web::HealthCheck.new { raise "Something bad" }
|
|
20
|
-
#
|
|
21
|
-
# Please note that this rack app is not 100% Rack compliant, since it raises
|
|
22
|
-
# any error that the block itself raises. This class aims at being backed up
|
|
23
|
-
# by a Shield and/or CatchAll middleware.
|
|
24
|
-
#
|
|
25
|
-
# This class is not aimed at being subclassed.
|
|
26
|
-
#
|
|
27
|
-
class HealthCheck
|
|
28
|
-
|
|
29
|
-
def initialize(&bl)
|
|
30
|
-
@checker = bl
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
def call(env)
|
|
34
|
-
if debug_msg = check!(env)
|
|
35
|
-
[ 200, { "Content-Type" => "text/plain" }, Array(debug_msg) ]
|
|
36
|
-
else
|
|
37
|
-
[ 204, {}, [] ]
|
|
38
|
-
end
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
protected
|
|
42
|
-
|
|
43
|
-
def check!(env)
|
|
44
|
-
@checker.call if @checker
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
end # class HealthCheck
|
|
48
|
-
end # module Web
|
|
49
|
-
end # module Startback
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
module Startback
|
|
2
|
-
module Web
|
|
3
|
-
class MagicAssets
|
|
4
|
-
#
|
|
5
|
-
# Plugin for MagicAssets that compiles .html angular templates in the
|
|
6
|
-
# assets structure to javascript files filling angular's template cache.
|
|
7
|
-
#
|
|
8
|
-
# Heavily inspired, yet over-simplified version, of angular-rails-templates
|
|
9
|
-
# See https://github.com/pitr/angular-rails-templates, licensed under MIT
|
|
10
|
-
#
|
|
11
|
-
# Example:
|
|
12
|
-
#
|
|
13
|
-
# use Startback::Web::MagicAssets, {
|
|
14
|
-
# plugins: [Startback::Web::MagicAssets::NgHtmlTransfomer.new]
|
|
15
|
-
# }
|
|
16
|
-
#
|
|
17
|
-
class NgHtmlTransformer
|
|
18
|
-
|
|
19
|
-
DEFAULT_OPTIONS = {
|
|
20
|
-
:path => '/assets',
|
|
21
|
-
:ng_module => 'templates',
|
|
22
|
-
:mime_type => 'text/ng-html',
|
|
23
|
-
:extensions => [".html"]
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
def initialize(options = {})
|
|
27
|
-
@options = DEFAULT_OPTIONS.merge(options)
|
|
28
|
-
end
|
|
29
|
-
attr_reader :options
|
|
30
|
-
|
|
31
|
-
def install(sprockets)
|
|
32
|
-
sprockets.register_mime_type options[:mime_type], extensions: options[:extensions]
|
|
33
|
-
sprockets.register_transformer options[:mime_type], 'application/javascript', self
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
TPL = <<-EOF
|
|
37
|
-
angular.module("<%= ng_module %>").run(["$templateCache", function($templateCache) {
|
|
38
|
-
$templateCache.put("<%= angular_template_name %>", <%= html %>)
|
|
39
|
-
}]);
|
|
40
|
-
EOF
|
|
41
|
-
|
|
42
|
-
# inspired by Rails' action_view/helpers/javascript_helper.rb
|
|
43
|
-
JS_ESCAPE_MAP = {
|
|
44
|
-
'\\' => '\\\\',
|
|
45
|
-
"\r\n" => '\n',
|
|
46
|
-
"\n" => '\n',
|
|
47
|
-
"\r" => '\n',
|
|
48
|
-
'"' => '\\"',
|
|
49
|
-
"'" => "\\'"
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
# We want to deliver the shortist valid javascript escaped string
|
|
53
|
-
# Count the number of " vs '
|
|
54
|
-
# If more ', escape "
|
|
55
|
-
# If more ", escape '
|
|
56
|
-
# If equal, prefer to escape "
|
|
57
|
-
|
|
58
|
-
def escape_javascript(raw)
|
|
59
|
-
if raw
|
|
60
|
-
quote = raw.count(%{'}) >= raw.count(%{"}) ? %{"} : %{'}
|
|
61
|
-
escaped = raw.gsub(/(\\|\r\n|[\n\r#{quote}])/u) {|match| JS_ESCAPE_MAP[match] }
|
|
62
|
-
"#{quote}#{escaped}#{quote}"
|
|
63
|
-
else
|
|
64
|
-
'""'
|
|
65
|
-
end
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
def call(input)
|
|
69
|
-
file_path = input[:filename]
|
|
70
|
-
angular_template_name = "#{options[:path]}/#{input[:name]}.html"
|
|
71
|
-
source_file = file_path
|
|
72
|
-
ng_module = options[:ng_module]
|
|
73
|
-
html = escape_javascript(input[:data].chomp)
|
|
74
|
-
ERB.new(TPL).result(binding)
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
end # class NgHtmlTransformer
|
|
78
|
-
end # class MagicAssets
|
|
79
|
-
end # module Web
|
|
80
|
-
end # module Startback
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
module Startback
|
|
2
|
-
module Web
|
|
3
|
-
class MagicAssets
|
|
4
|
-
class RakeTasks
|
|
5
|
-
|
|
6
|
-
DEFAULT_OPTIONS = {
|
|
7
|
-
:namespace => :assets
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
def initialize(rake, options)
|
|
11
|
-
@rake = rake
|
|
12
|
-
@options = DEFAULT_OPTIONS.merge(options)
|
|
13
|
-
install
|
|
14
|
-
end
|
|
15
|
-
attr_reader :rake, :options
|
|
16
|
-
|
|
17
|
-
private
|
|
18
|
-
|
|
19
|
-
def install
|
|
20
|
-
require 'securerandom'
|
|
21
|
-
|
|
22
|
-
ns = options[:namespace]
|
|
23
|
-
target_folder = options[:target]
|
|
24
|
-
assets = options[:assets]
|
|
25
|
-
assets = MagicAssets.new(assets) if assets.is_a?(Hash)
|
|
26
|
-
version = SecureRandom.urlsafe_base64
|
|
27
|
-
|
|
28
|
-
rake.instance_exec do
|
|
29
|
-
namespace(ns) do
|
|
30
|
-
|
|
31
|
-
desc 'Cleans generated assets'
|
|
32
|
-
task :clean do
|
|
33
|
-
FileUtils.rm_rf target_folder
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
task :prepare do
|
|
37
|
-
FileUtils.mkdir_p target_folder
|
|
38
|
-
(target_folder/"VERSION").write(version)
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
desc 'compile javascript assets'
|
|
42
|
-
task :compile_js do
|
|
43
|
-
assets['vendor.js'].write_to(target_folder/"vendor-#{version}.min.js")
|
|
44
|
-
assets['app.js'].write_to(target_folder/"app-#{version}.min.js")
|
|
45
|
-
puts "successfully compiled js assets"
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
desc 'compile css assets'
|
|
49
|
-
task :compile_css do
|
|
50
|
-
assets['vendor.css'].write_to(target_folder/"vendor-#{version}.min.css")
|
|
51
|
-
assets['app.css'].write_to(target_folder/"app-#{version}.min.css")
|
|
52
|
-
puts "successfully compiled css assets"
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
desc 'compile assets'
|
|
56
|
-
task :compile => [:clean, :prepare, :compile_js, :compile_css]
|
|
57
|
-
end
|
|
58
|
-
end
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
end
|
|
62
|
-
end # class MagicAssets
|
|
63
|
-
end # module Web
|
|
64
|
-
end # module Startback
|