dzl 1.0.0.beta0
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.
- data/.gitignore +6 -0
- data/.rspec +1 -0
- data/.rvmrc +1 -0
- data/Gemfile +9 -0
- data/README.md +44 -0
- data/Rakefile +15 -0
- data/config.ru +41 -0
- data/dzl.gemspec +21 -0
- data/lib/dzl/doc/endpoint_doc.rb +70 -0
- data/lib/dzl/doc/router_doc.rb +26 -0
- data/lib/dzl/doc/task.rb +5 -0
- data/lib/dzl/doc/templates/endpoint.erb +55 -0
- data/lib/dzl/doc/templates/home.erb +8 -0
- data/lib/dzl/doc.rb +58 -0
- data/lib/dzl/dsl_proxies/defaults.rb +10 -0
- data/lib/dzl/dsl_proxies/endpoint.rb +30 -0
- data/lib/dzl/dsl_proxies/parameter.rb +75 -0
- data/lib/dzl/dsl_proxies/parameter_block.rb +61 -0
- data/lib/dzl/dsl_proxies/protection.rb +6 -0
- data/lib/dzl/dsl_proxies/router.rb +62 -0
- data/lib/dzl/dsl_proxy.rb +8 -0
- data/lib/dzl/dsl_subject.rb +15 -0
- data/lib/dzl/dsl_subjects/defaults.rb +12 -0
- data/lib/dzl/dsl_subjects/endpoint.rb +79 -0
- data/lib/dzl/dsl_subjects/parameter/allowed_values.rb +60 -0
- data/lib/dzl/dsl_subjects/parameter/type_conversion.rb +59 -0
- data/lib/dzl/dsl_subjects/parameter.rb +100 -0
- data/lib/dzl/dsl_subjects/parameter_block.rb +64 -0
- data/lib/dzl/dsl_subjects/protection.rb +31 -0
- data/lib/dzl/dsl_subjects/router.rb +87 -0
- data/lib/dzl/errors.rb +33 -0
- data/lib/dzl/examples/base.rb +9 -0
- data/lib/dzl/examples/fun_with_handlers.rb +33 -0
- data/lib/dzl/examples/fun_with_hooks.rb +65 -0
- data/lib/dzl/examples/fun_with_params.rb +71 -0
- data/lib/dzl/examples/fun_with_requests.rb +47 -0
- data/lib/dzl/examples/route_profile.rb +158 -0
- data/lib/dzl/examples/trey.rb +97 -0
- data/lib/dzl/logger.rb +65 -0
- data/lib/dzl/rack_interface.rb +95 -0
- data/lib/dzl/request.rb +54 -0
- data/lib/dzl/response_context/request_helpers.rb +11 -0
- data/lib/dzl/response_context.rb +47 -0
- data/lib/dzl/validator.rb +10 -0
- data/lib/dzl/validators/size.rb +32 -0
- data/lib/dzl/validators/value.rb +30 -0
- data/lib/dzl/value_or_error.rb +32 -0
- data/lib/dzl/version.rb +3 -0
- data/lib/dzl.rb +96 -0
- data/spec/dsl_subject_spec.rb +14 -0
- data/spec/endpoint_doc_spec.rb +25 -0
- data/spec/fun_with_handlers_spec.rb +37 -0
- data/spec/fun_with_hooks_spec.rb +61 -0
- data/spec/fun_with_params_spec.rb +197 -0
- data/spec/fun_with_requests_spec.rb +101 -0
- data/spec/logger_spec.rb +48 -0
- data/spec/route_params_spec.rb +13 -0
- data/spec/router_doc_spec.rb +32 -0
- data/spec/spec_helper.rb +8 -0
- data/spec/trey_spec.rb +135 -0
- data/spec/value_or_error_spec.rb +44 -0
- metadata +142 -0
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'dzl/examples/base'
|
2
|
+
|
3
|
+
class Dzl::Examples::FunWithRequests < Dzl::Examples::Base
|
4
|
+
endpoint '/foo' do
|
5
|
+
handle do
|
6
|
+
'get'
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
endpoint '/post_op', :post do
|
11
|
+
handle do
|
12
|
+
'post'
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
endpoint '/multi_op', :post, :put do
|
17
|
+
handle do
|
18
|
+
request.request_method.downcase
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
get '/get_only'
|
23
|
+
delete '/delete_only'
|
24
|
+
get '/get_and_post', :post
|
25
|
+
|
26
|
+
get '/validated_header' do
|
27
|
+
required_header :key do
|
28
|
+
validate_with { |k| k == 'hello' }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
get '/ambiguous' do
|
33
|
+
required :foo
|
34
|
+
|
35
|
+
handle do
|
36
|
+
params[:foo]
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
get '/ambiguous' do
|
41
|
+
required :bar
|
42
|
+
|
43
|
+
handle do
|
44
|
+
params[:bar]
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,158 @@
|
|
1
|
+
require 'dzl/examples/base'
|
2
|
+
|
3
|
+
class Dzl::Examples::RouteProfile < Dzl::Examples::base
|
4
|
+
global_pblock do end
|
5
|
+
|
6
|
+
#150 routes
|
7
|
+
endpoint '/Lorem' do end
|
8
|
+
endpoint '/ipsum' do end
|
9
|
+
endpoint '/dolor' do end
|
10
|
+
endpoint '/sit' do end
|
11
|
+
endpoint '/amet' do end
|
12
|
+
endpoint '/consectetur' do end
|
13
|
+
endpoint '/adipiscing' do end
|
14
|
+
endpoint '/elit' do end
|
15
|
+
endpoint '/Aenean' do end
|
16
|
+
endpoint '/pulvinar' do end
|
17
|
+
endpoint '/ante' do end
|
18
|
+
endpoint '/id' do end
|
19
|
+
endpoint '/venenatis' do end
|
20
|
+
endpoint '/eleifend' do end
|
21
|
+
endpoint '/Vivamus' do end
|
22
|
+
endpoint '/mattis' do end
|
23
|
+
endpoint '/tempor' do end
|
24
|
+
endpoint '/bibendum' do end
|
25
|
+
endpoint '/nulla' do end
|
26
|
+
endpoint '/lobortis' do end
|
27
|
+
endpoint '/vitae' do end
|
28
|
+
endpoint '/Vestibulum' do end
|
29
|
+
endpoint '/primis' do end
|
30
|
+
endpoint '/in' do end
|
31
|
+
endpoint '/faucibus' do end
|
32
|
+
endpoint '/orci' do end
|
33
|
+
endpoint '/luctus' do end
|
34
|
+
endpoint '/et' do end
|
35
|
+
endpoint '/ultrices' do end
|
36
|
+
endpoint '/posuere' do end
|
37
|
+
endpoint '/cubilia' do end
|
38
|
+
endpoint '/Curae;' do end
|
39
|
+
endpoint '/Proin' do end
|
40
|
+
endpoint '/nisi' do end
|
41
|
+
endpoint '/malesuada' do end
|
42
|
+
endpoint '/eu' do end
|
43
|
+
endpoint '/scelerisque' do end
|
44
|
+
endpoint '/ut' do end
|
45
|
+
endpoint '/eget' do end
|
46
|
+
endpoint '/augue' do end
|
47
|
+
endpoint '/Aliquam' do end
|
48
|
+
endpoint '/erat' do end
|
49
|
+
endpoint '/volutpat' do end
|
50
|
+
endpoint '/Praesent' do end
|
51
|
+
endpoint '/leo' do end
|
52
|
+
endpoint '/commodo' do end
|
53
|
+
endpoint '/ac' do end
|
54
|
+
endpoint '/suscipit' do end
|
55
|
+
endpoint '/sed' do end
|
56
|
+
endpoint '/magna' do end
|
57
|
+
endpoint '/Fusce' do end
|
58
|
+
endpoint '/lacinia' do end
|
59
|
+
endpoint '/lorem' do end
|
60
|
+
endpoint '/felis' do end
|
61
|
+
endpoint '/fermentum' do end
|
62
|
+
endpoint '/non' do end
|
63
|
+
endpoint '/molestie' do end
|
64
|
+
endpoint '/ligula' do end
|
65
|
+
endpoint '/sollicitudin' do end
|
66
|
+
endpoint '/Cras' do end
|
67
|
+
endpoint '/auctor' do end
|
68
|
+
endpoint '/mi' do end
|
69
|
+
endpoint '/eros' do end
|
70
|
+
endpoint '/quis' do end
|
71
|
+
endpoint '/velit' do end
|
72
|
+
endpoint '/facilisis' do end
|
73
|
+
endpoint '/a' do end
|
74
|
+
endpoint '/metus' do end
|
75
|
+
endpoint '/Ut' do end
|
76
|
+
endpoint '/enim' do end
|
77
|
+
endpoint '/aliquam' do end
|
78
|
+
endpoint '/cursus' do end
|
79
|
+
endpoint '/Etiam' do end
|
80
|
+
endpoint '/imperdiet' do end
|
81
|
+
endpoint '/rhoncus' do end
|
82
|
+
endpoint '/nibh' do end
|
83
|
+
endpoint '/tincidunt' do end
|
84
|
+
endpoint '/ullamcorper' do end
|
85
|
+
endpoint '/Nulla' do end
|
86
|
+
endpoint '/dapibus' do end
|
87
|
+
endpoint '/nunc' do end
|
88
|
+
endpoint '/at' do end
|
89
|
+
endpoint '/vestibulum' do end
|
90
|
+
endpoint '/tortor' do end
|
91
|
+
endpoint '/pharetra' do end
|
92
|
+
endpoint '/vulputate' do end
|
93
|
+
endpoint '/accumsan' do end
|
94
|
+
endpoint '/Pellentesque' do end
|
95
|
+
endpoint '/Nam' do end
|
96
|
+
endpoint '/elementum' do end
|
97
|
+
endpoint '/ultricies' do end
|
98
|
+
endpoint '/Morbi' do end
|
99
|
+
endpoint '/varius' do end
|
100
|
+
endpoint '/lacus' do end
|
101
|
+
endpoint '/mollis' do end
|
102
|
+
endpoint '/Quisque' do end
|
103
|
+
endpoint '/porttitor' do end
|
104
|
+
endpoint '/arcu' do end
|
105
|
+
endpoint '/mauris' do end
|
106
|
+
endpoint '/hendrerit' do end
|
107
|
+
endpoint '/pretium' do end
|
108
|
+
endpoint '/placerat' do end
|
109
|
+
endpoint '/quam' do end
|
110
|
+
endpoint '/feugiat' do end
|
111
|
+
endpoint '/diam' do end
|
112
|
+
endpoint '/aliquet' do end
|
113
|
+
endpoint '/convallis' do end
|
114
|
+
endpoint '/Donec' do end
|
115
|
+
endpoint '/dignissim' do end
|
116
|
+
endpoint '/lectus' do end
|
117
|
+
endpoint '/rutrum' do end
|
118
|
+
endpoint '/nisl' do end
|
119
|
+
endpoint '/ornare' do end
|
120
|
+
endpoint '/tristique' do end
|
121
|
+
endpoint '/sapien' do end
|
122
|
+
endpoint '/euismod' do end
|
123
|
+
endpoint '/vel' do end
|
124
|
+
endpoint '/massa' do end
|
125
|
+
endpoint '/porta' do end
|
126
|
+
endpoint '/nec' do end
|
127
|
+
endpoint '/habitant' do end
|
128
|
+
endpoint '/morbi' do end
|
129
|
+
endpoint '/senectus' do end
|
130
|
+
endpoint '/netus' do end
|
131
|
+
endpoint '/fames' do end
|
132
|
+
endpoint '/turpis' do end
|
133
|
+
endpoint '/egestas' do end
|
134
|
+
endpoint '/Curabitur' do end
|
135
|
+
endpoint '/pellentesque' do end
|
136
|
+
endpoint '/libero' do end
|
137
|
+
endpoint '/Duis' do end
|
138
|
+
endpoint '/congue' do end
|
139
|
+
endpoint '/iaculis' do end
|
140
|
+
endpoint '/In' do end
|
141
|
+
endpoint '/Nunc' do end
|
142
|
+
endpoint '/Sed' do end
|
143
|
+
endpoint '/blandit' do end
|
144
|
+
endpoint '/tempus' do end
|
145
|
+
endpoint '/tellus' do end
|
146
|
+
endpoint '/condimentum' do end
|
147
|
+
endpoint '/interdum' do end
|
148
|
+
endpoint '/fringilla' do end
|
149
|
+
endpoint '/viverra' do end
|
150
|
+
endpoint '/justo' do end
|
151
|
+
endpoint '/consequat' do end
|
152
|
+
endpoint '/gravida' do end
|
153
|
+
endpoint '/risus' do end
|
154
|
+
endpoint '/urna' do end
|
155
|
+
endpoint '/semper' do end
|
156
|
+
endpoint '/dui' do end
|
157
|
+
|
158
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
require 'dzl/examples/base'
|
2
|
+
|
3
|
+
class Dzl::Examples::Trey < Dzl::Examples::Base
|
4
|
+
METRIC_NAMES_OR_WHATEVER ||= %w{m1 m2 m3 m4 m5 m6}
|
5
|
+
|
6
|
+
# this could be handy
|
7
|
+
# defaults do
|
8
|
+
# type Array do
|
9
|
+
# unique
|
10
|
+
# separator ' '
|
11
|
+
# end
|
12
|
+
# end
|
13
|
+
|
14
|
+
# global parameter block applies to all routes
|
15
|
+
# each route gets it's own copy, so, they can
|
16
|
+
# mess with the predefined parameters as much as
|
17
|
+
# they'd like
|
18
|
+
global_pblock do
|
19
|
+
# required_header :api_key do
|
20
|
+
# validate_with { |key| key == 'open sesame' }
|
21
|
+
# end
|
22
|
+
|
23
|
+
param :page_ids do
|
24
|
+
type Array
|
25
|
+
size <= 5
|
26
|
+
end
|
27
|
+
|
28
|
+
param :post_ids do
|
29
|
+
type Array
|
30
|
+
size <= 100
|
31
|
+
end
|
32
|
+
|
33
|
+
param :metrics do
|
34
|
+
type Array
|
35
|
+
allowed_values METRIC_NAMES_OR_WHATEVER
|
36
|
+
end
|
37
|
+
|
38
|
+
param :since, :until do
|
39
|
+
type Date
|
40
|
+
end
|
41
|
+
|
42
|
+
param :interval do
|
43
|
+
allowed_values %w{day week month}
|
44
|
+
default 'day'
|
45
|
+
end
|
46
|
+
|
47
|
+
param :limit do
|
48
|
+
type Fixnum
|
49
|
+
allowed_values 1..250
|
50
|
+
default 250
|
51
|
+
end
|
52
|
+
|
53
|
+
param :sort do
|
54
|
+
default 'created_time'
|
55
|
+
end
|
56
|
+
|
57
|
+
param :order do
|
58
|
+
prevalidate_transform do |input|
|
59
|
+
input.downcase
|
60
|
+
end
|
61
|
+
allowed_values ['asc', 'desc', 'ascending', 'descending']
|
62
|
+
default :desc
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
endpoint '/page_insights' do
|
67
|
+
required :page_ids, :metrics, :since, :until
|
68
|
+
optional :interval
|
69
|
+
forbid :post_ids, :limit, :sort, :order
|
70
|
+
end
|
71
|
+
|
72
|
+
endpoint '/post_insights' do
|
73
|
+
required :post_ids, :metrics
|
74
|
+
forbid :page_ids, :since, :until, :interval, :limit, :sort, :order
|
75
|
+
end
|
76
|
+
|
77
|
+
# endpoint '/post_insights' do
|
78
|
+
# required :page_ids do
|
79
|
+
# size <= 5
|
80
|
+
# end
|
81
|
+
|
82
|
+
# required :metrics, :since, :until
|
83
|
+
# forbid :post_ids, :interval, :limit, :sort, :order
|
84
|
+
# end
|
85
|
+
|
86
|
+
endpoint '/posts' do
|
87
|
+
required :page_ids, :metrics
|
88
|
+
optional :since, :until, :limit, :sort, :order
|
89
|
+
forbid :post_ids
|
90
|
+
end
|
91
|
+
|
92
|
+
# endpoint '/posts' do
|
93
|
+
# required :post_ids, :metrics
|
94
|
+
# optional :since, :until, :limit, :sort, :order
|
95
|
+
# forbid :page_ids
|
96
|
+
# end
|
97
|
+
end
|
data/lib/dzl/logger.rb
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
class ActiveSupport::BufferedLogger
|
2
|
+
def self.timestamp
|
3
|
+
DateTime.now.strftime("[%Y-%m-%d %H:%M:%S] - ")
|
4
|
+
end
|
5
|
+
|
6
|
+
alias_method :orig_add, :add
|
7
|
+
def add(severity, message = nil, progname = nil, &block)
|
8
|
+
message = "#{ActiveSupport::BufferedLogger.timestamp}#{message}"
|
9
|
+
orig_add(severity, message, progname, &block)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
module Dzl
|
14
|
+
class Logger
|
15
|
+
LOG_METHODS = [:debug, :info, :warn, :error, :fatal]
|
16
|
+
def initialize(app_root)
|
17
|
+
@app_root = app_root
|
18
|
+
@loggers = {
|
19
|
+
default: create_logger # log/[environment].log
|
20
|
+
}
|
21
|
+
end
|
22
|
+
|
23
|
+
# Get the standard logger methods defined
|
24
|
+
LOG_METHODS.each do |severity|
|
25
|
+
define_method(severity) do |msg|
|
26
|
+
log(severity, msg)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
############
|
31
|
+
# Receives all the default log methods on AppClass.logger
|
32
|
+
# and forwards to the default logger
|
33
|
+
############
|
34
|
+
def log(severity, msg)
|
35
|
+
@loggers[:default].send(severity, msg)
|
36
|
+
end
|
37
|
+
|
38
|
+
############
|
39
|
+
# The idea here is that you can call
|
40
|
+
# AppClass.logger.tidy.debug("Something")
|
41
|
+
# and we'll write your log message to tidy.environment.log
|
42
|
+
############
|
43
|
+
def method_missing(m, *args, &block)
|
44
|
+
if @loggers[:default].respond_to?(m)
|
45
|
+
# Don't create things like flush.development.log (-:
|
46
|
+
@loggers[:default].send(m, *args, &block)
|
47
|
+
else
|
48
|
+
@loggers[m] ||= create_logger(m.to_s)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
def create_logger(name = nil)
|
54
|
+
logfile = name ? "#{name}.#{Dzl.env}.log" : "#{Dzl.env}.log"
|
55
|
+
ActiveSupport::BufferedLogger.new(
|
56
|
+
File.join(@app_root, 'log', logfile),
|
57
|
+
%w{ staging production }.include?(Dzl.env) ? ::Logger::INFO : ::Logger::DEBUG
|
58
|
+
)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.logger
|
63
|
+
@@logger ||= Logger.new
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
require 'rack'
|
2
|
+
require 'dzl/request'
|
3
|
+
|
4
|
+
module Dzl::RackInterface
|
5
|
+
PROFILE_REQUESTS = false
|
6
|
+
|
7
|
+
def call(env)
|
8
|
+
response = nil
|
9
|
+
request = nil
|
10
|
+
start_time = Time.now
|
11
|
+
start_profile if PROFILE_REQUESTS
|
12
|
+
response = begin
|
13
|
+
request = Dzl::Request.new(env)
|
14
|
+
__router.handle_request(request)
|
15
|
+
rescue Dzl::RespondWithHTTPBasicChallenge
|
16
|
+
respond_with_http_basic_challenge
|
17
|
+
rescue Dzl::Error => e
|
18
|
+
respond_with_dzl_error_handler(e)
|
19
|
+
rescue StandardError => e
|
20
|
+
respond_with_standard_error_handler(e)
|
21
|
+
end
|
22
|
+
|
23
|
+
if response[0] < 100
|
24
|
+
response = respond_with_standard_error_handler(StandardError.new('Application did not respond'))
|
25
|
+
end
|
26
|
+
|
27
|
+
stop_profiling_and_print if PROFILE_REQUESTS
|
28
|
+
log_request(request, response, (Time.now - start_time)) unless request.silent?
|
29
|
+
|
30
|
+
if Dzl.production? || Dzl.staging?
|
31
|
+
(response[0] < 500) ? response : [response[0], [], [response[0].to_s]]
|
32
|
+
else
|
33
|
+
response
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def respond_with_http_basic_challenge
|
38
|
+
response = Rack::Response.new
|
39
|
+
response['WWW-Authenticate'] = %(Basic realm="Dzl HTTP Basic")
|
40
|
+
response.status = 401
|
41
|
+
response.headers['Content-Type'] = 'text/html'
|
42
|
+
response.write("Not Authorized\n")
|
43
|
+
response.finish
|
44
|
+
end
|
45
|
+
|
46
|
+
def respond_with_standard_error_handler(e)
|
47
|
+
response = Rack::Response.new
|
48
|
+
response.headers['Content-Type'] = 'application/json'
|
49
|
+
response.status = 500
|
50
|
+
|
51
|
+
response.write({
|
52
|
+
status: 500,
|
53
|
+
error_class: e.class.to_s,
|
54
|
+
errors: e.to_s,
|
55
|
+
trace: e.backtrace
|
56
|
+
}.to_json)
|
57
|
+
|
58
|
+
response.finish
|
59
|
+
end
|
60
|
+
|
61
|
+
def respond_with_dzl_error_handler(e)
|
62
|
+
response = Rack::Response.new
|
63
|
+
response.headers['Content-Type'] = 'application/json'
|
64
|
+
|
65
|
+
if e.is_a?(Dzl::RequestError)
|
66
|
+
response.status = e.status
|
67
|
+
response.write(e.to_json)
|
68
|
+
else
|
69
|
+
response.status = e.status
|
70
|
+
response.write(e.to_json)
|
71
|
+
end
|
72
|
+
|
73
|
+
response.finish
|
74
|
+
end
|
75
|
+
|
76
|
+
def start_profile
|
77
|
+
require 'ruby-prof'
|
78
|
+
RubyProf.start
|
79
|
+
end
|
80
|
+
|
81
|
+
def stop_profiling_and_print
|
82
|
+
result = RubyProf.stop
|
83
|
+
printer = RubyProf::GraphHtmlPrinter.new(result)
|
84
|
+
printer.print(
|
85
|
+
File.open('/Projects/dzl/profile.html', 'w'),
|
86
|
+
min_percent: 5
|
87
|
+
)
|
88
|
+
end
|
89
|
+
|
90
|
+
def log_request(request, response, seconds)
|
91
|
+
logger.info "#{request.request_method} #{request.path}"
|
92
|
+
logger.info "PARAMS: #{request.params}"
|
93
|
+
logger.info "#{response[0]} in #{seconds * 1000}ms"
|
94
|
+
end
|
95
|
+
end
|
data/lib/dzl/request.rb
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
class Dzl::Request < Rack::Request
|
2
|
+
attr_accessor :silent
|
3
|
+
|
4
|
+
def initialize(env)
|
5
|
+
super(env)
|
6
|
+
|
7
|
+
@endpoints = Hash.new({})
|
8
|
+
end
|
9
|
+
|
10
|
+
def headers
|
11
|
+
@headers ||= begin
|
12
|
+
env.each_with_object({}) do |env_pair, headers|
|
13
|
+
k, v = env_pair
|
14
|
+
if header = (/HTTP_(.+)/.match(k.upcase.gsub('-', '_'))[1]) rescue nil
|
15
|
+
headers[header.downcase] = v
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def params
|
22
|
+
@params ||= super
|
23
|
+
end
|
24
|
+
|
25
|
+
def overwrite_headers(new_headers)
|
26
|
+
@headers = new_headers
|
27
|
+
end
|
28
|
+
|
29
|
+
def overwrite_params(new_params)
|
30
|
+
@params = new_params
|
31
|
+
end
|
32
|
+
|
33
|
+
def handle_with_endpoint(endpoint)
|
34
|
+
overwrite_params(@endpoints[endpoint][:params])
|
35
|
+
overwrite_headers(@endpoints[endpoint][:headers])
|
36
|
+
endpoint.handle(self).finish
|
37
|
+
end
|
38
|
+
|
39
|
+
def params_and_headers_for_endpoint(endpoint, params_and_headers = nil)
|
40
|
+
if params_and_headers
|
41
|
+
raise ArgumentError unless params_and_headers.is_a?(Hash) &&
|
42
|
+
params_and_headers.has_key?(:params) &&
|
43
|
+
params_and_headers.has_key?(:headers)
|
44
|
+
|
45
|
+
@endpoints[endpoint].merge!(params_and_headers)
|
46
|
+
else
|
47
|
+
@endpoints[endpoint].slice(:params, :headers)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def silent?
|
52
|
+
@silent == true
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'dzl/response_context/request_helpers'
|
2
|
+
|
3
|
+
class Dzl::ResponseContext
|
4
|
+
include RequestHelpers
|
5
|
+
attr_reader :request, :response, :endpoint
|
6
|
+
|
7
|
+
@@default_handler = Proc.new do
|
8
|
+
response['Content-Type'] = 'application/json'
|
9
|
+
{
|
10
|
+
headers: headers,
|
11
|
+
params: params
|
12
|
+
}.to_json
|
13
|
+
end
|
14
|
+
|
15
|
+
def initialize(endpoint, request, handler = nil)
|
16
|
+
@request = request
|
17
|
+
@endpoint = endpoint
|
18
|
+
@handler = handler
|
19
|
+
__build_response_with_defaults__
|
20
|
+
end
|
21
|
+
|
22
|
+
def logger
|
23
|
+
@logger ||= @endpoint.router.app.logger
|
24
|
+
end
|
25
|
+
|
26
|
+
def __respond__
|
27
|
+
@endpoint.hooks[:after_validate].each do |proc|
|
28
|
+
self.instance_exec(&proc)
|
29
|
+
end
|
30
|
+
|
31
|
+
value = @handler ? self.instance_exec(&@handler) : self.instance_exec(&@@default_handler)
|
32
|
+
|
33
|
+
unless @response.body.present?
|
34
|
+
@response.write(value)
|
35
|
+
end
|
36
|
+
|
37
|
+
@response
|
38
|
+
end
|
39
|
+
|
40
|
+
def __build_response_with_defaults__
|
41
|
+
@response = Rack::Response.new
|
42
|
+
|
43
|
+
if ct = @endpoint.router.defaults[:content_type]
|
44
|
+
@response['Content-Type'] = ct
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Dzl::Validators
|
2
|
+
class Size < Dzl::Validator
|
3
|
+
attr_reader :conditions
|
4
|
+
def initialize
|
5
|
+
@conditions = []
|
6
|
+
end
|
7
|
+
|
8
|
+
def validate(input)
|
9
|
+
unless input.respond_to?(:size)
|
10
|
+
return Dzl::ValueOrError.new(
|
11
|
+
e: :cannot_validate_size
|
12
|
+
)
|
13
|
+
end
|
14
|
+
|
15
|
+
valid = @conditions.all? do |op, n|
|
16
|
+
input.size.send(op, n)
|
17
|
+
end
|
18
|
+
|
19
|
+
if valid
|
20
|
+
Dzl::ValueOrError.new(v: input)
|
21
|
+
else
|
22
|
+
Dzl::ValueOrError.new(e: :size_validation_failed)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
[:==, :<=, :>=, :<, :>].each do |op|
|
27
|
+
define_method(op) do |n|
|
28
|
+
@conditions << [op, n]
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Dzl::Validators
|
2
|
+
class Value < Dzl::Validator
|
3
|
+
attr_reader :conditions
|
4
|
+
def initialize
|
5
|
+
@conditions = []
|
6
|
+
end
|
7
|
+
|
8
|
+
def validate(input)
|
9
|
+
valid = @conditions.all? do |op, n|
|
10
|
+
return Dzl::ValueOrError.new(
|
11
|
+
e: :value_validation_failed
|
12
|
+
) unless input.respond_to?(op)
|
13
|
+
|
14
|
+
input.send(op, n)
|
15
|
+
end
|
16
|
+
|
17
|
+
if valid
|
18
|
+
Dzl::ValueOrError.new(v: input)
|
19
|
+
else
|
20
|
+
Dzl::ValueOrError.new(e: :value_validation_failed)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
[:==, :<=, :>=, :<, :>].each do |op|
|
25
|
+
define_method(op) do |n|
|
26
|
+
@conditions << [op, n]
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
class Dzl::ValueOrError
|
2
|
+
attr_reader :error, :value
|
3
|
+
|
4
|
+
def initialize(opts = {})
|
5
|
+
@error = opts[:error] || opts[:e]
|
6
|
+
@value = opts[:value] || opts[:v]
|
7
|
+
|
8
|
+
if @error && @value
|
9
|
+
raise ArgumentError, "it's ValueOrError, not ValueAndError"
|
10
|
+
end
|
11
|
+
|
12
|
+
unless @error || opts.has_key?(:v) || opts.has_key?(:value)
|
13
|
+
raise ArgumentError, "Must provide :value key, even if nil"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def error?
|
18
|
+
@error.present?
|
19
|
+
end
|
20
|
+
|
21
|
+
def value?
|
22
|
+
!error?
|
23
|
+
end
|
24
|
+
|
25
|
+
def to_s
|
26
|
+
if error?
|
27
|
+
"e: #{@error.inspect}"
|
28
|
+
else
|
29
|
+
"v: #{@value.inspect}"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/lib/dzl/version.rb
ADDED