zleb 0.1.6
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 +7 -0
- data/.gitignore +11 -0
- data/.rake_tasks~ +7 -0
- data/.rspec +3 -0
- data/.ruby-version +1 -0
- data/.travis.yml +6 -0
- data/Gemfile +9 -0
- data/Gemfile.lock +131 -0
- data/LICENSE.txt +21 -0
- data/README.md +40 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/build.sh +1 -0
- data/config/errors.yml +218 -0
- data/lib/zleb/controller.rb +33 -0
- data/lib/zleb/plugins/api_route.rb +21 -0
- data/lib/zleb/plugins/basic_restful_action.rb +212 -0
- data/lib/zleb/plugins/dry_schema_enhance.rb +44 -0
- data/lib/zleb/plugins/http_auth.rb +70 -0
- data/lib/zleb/plugins/method_route.rb +59 -0
- data/lib/zleb/plugins/params_check.rb +312 -0
- data/lib/zleb/plugins/params_snake_keys.rb +33 -0
- data/lib/zleb/plugins/render_static.rb +142 -0
- data/lib/zleb/plugins/schema_compiler.rb +293 -0
- data/lib/zleb/plugins/uni_logger.rb +18 -0
- data/lib/zleb/symbolize_helper.rb +19 -0
- data/lib/zleb/version.rb +3 -0
- data/lib/zleb.rb +133 -0
- data/push.sh +3 -0
- data/zleb.gemspec +43 -0
- metadata +248 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
#转换为snake
|
|
2
|
+
require 'plissken'
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class Roda
|
|
6
|
+
module RodaPlugins
|
|
7
|
+
|
|
8
|
+
def self.load_dependencies(app)
|
|
9
|
+
app.plugin :request_headers
|
|
10
|
+
app.plugin :json_parser
|
|
11
|
+
end
|
|
12
|
+
module ParamsSnakeKeys
|
|
13
|
+
|
|
14
|
+
def self.configure(config)
|
|
15
|
+
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
module RequestMethods
|
|
19
|
+
def params
|
|
20
|
+
super_params = super
|
|
21
|
+
if headers['X-Convert-Key'] == 'true'
|
|
22
|
+
super_params.to_snake_keys
|
|
23
|
+
else
|
|
24
|
+
super_params
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
register_plugin(:params_snake_keys, ParamsSnakeKeys)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# frozen-string-literal: true
|
|
2
|
+
|
|
3
|
+
require 'uri'
|
|
4
|
+
|
|
5
|
+
begin
|
|
6
|
+
require 'rack/files'
|
|
7
|
+
rescue LoadError
|
|
8
|
+
require 'rack/file'
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
#
|
|
12
|
+
class Roda
|
|
13
|
+
module RodaPlugins
|
|
14
|
+
# The public plugin adds a +r.public+ routing method to serve static files
|
|
15
|
+
# from a directory.
|
|
16
|
+
#
|
|
17
|
+
# The public plugin recognizes the application's :root option, and defaults to
|
|
18
|
+
# using the +public+ subfolder of the application's +:root+ option. If the application's
|
|
19
|
+
# :root option is not set, it defaults to the +public+ folder in the working
|
|
20
|
+
# directory. Additionally, if a relative path is provided as the +:root+
|
|
21
|
+
# option to the plugin, it will be considered relative to the application's
|
|
22
|
+
# +:root+ option.
|
|
23
|
+
#
|
|
24
|
+
# Examples:
|
|
25
|
+
#
|
|
26
|
+
# # Use public folder as location of files
|
|
27
|
+
# plugin :public
|
|
28
|
+
#
|
|
29
|
+
# # Use /path/to/app/static as location of files
|
|
30
|
+
# opts[:root] = '/path/to/app'
|
|
31
|
+
# plugin :public, root: 'static'
|
|
32
|
+
#
|
|
33
|
+
# # Assuming public is the location of files
|
|
34
|
+
# r.route do
|
|
35
|
+
# # Make GET /images/foo.png look for public/images/foo.png
|
|
36
|
+
# r.public
|
|
37
|
+
#
|
|
38
|
+
# # Make GET /static/images/foo.png look for public/images/foo.png
|
|
39
|
+
# r.on(:static) do
|
|
40
|
+
# r.public
|
|
41
|
+
# end
|
|
42
|
+
# end
|
|
43
|
+
module RenderStatic
|
|
44
|
+
SPLIT = Regexp.union(*[File::SEPARATOR, File::ALT_SEPARATOR].compact)
|
|
45
|
+
PARSER = URI::DEFAULT_PARSER
|
|
46
|
+
|
|
47
|
+
RACK_FILES = defined?(Rack::Files) ? Rack::Files : Rack::File
|
|
48
|
+
# Use options given to setup a Rack::File instance for serving files. Options:
|
|
49
|
+
# :default_mime :: The default mime type to use if the mime type is not recognized.
|
|
50
|
+
# :gzip :: Whether to serve already gzipped files with a .gz extension for clients
|
|
51
|
+
# supporting gzipped transfer encoding.
|
|
52
|
+
# :headers :: A hash of headers to use for statically served files
|
|
53
|
+
# :root :: Use this option for the root of the public directory (default: "public")
|
|
54
|
+
def self.configure(app, opts={})
|
|
55
|
+
if opts[:root]
|
|
56
|
+
app.opts[:public_root] = app.expand_path(opts[:root])
|
|
57
|
+
elsif !app.opts[:public_root]
|
|
58
|
+
app.opts[:public_root] = app.expand_path("public")
|
|
59
|
+
end
|
|
60
|
+
app.opts[:public_server] = RACK_FILES.new(app.opts[:public_root], opts[:headers]||{}, opts[:default_mime] || 'text/plain')
|
|
61
|
+
app.opts[:public_gzip] = opts[:gzip]
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
module RequestMethods
|
|
65
|
+
# Serve files from the public directory if the file exists and this is a GET request.
|
|
66
|
+
def render_static(render_path)
|
|
67
|
+
if is_get?
|
|
68
|
+
path = PARSER.unescape(render_path)
|
|
69
|
+
return if path.include?("\0")
|
|
70
|
+
|
|
71
|
+
roda_opts = roda_class.opts
|
|
72
|
+
server = roda_opts[:public_server]
|
|
73
|
+
path = ::File.join(server.root, *public_path_segments(path))
|
|
74
|
+
|
|
75
|
+
if roda_opts[:public_gzip] && env['HTTP_ACCEPT_ENCODING'] =~ /\bgzip\b/
|
|
76
|
+
gzip_path = path + '.gz'
|
|
77
|
+
|
|
78
|
+
if public_file_readable?(gzip_path)
|
|
79
|
+
res = public_serve(server, gzip_path)
|
|
80
|
+
headers = res[1]
|
|
81
|
+
|
|
82
|
+
unless res[0] == 304
|
|
83
|
+
if mime_type = ::Rack::Mime.mime_type(::File.extname(path), 'text/plain')
|
|
84
|
+
headers['Content-Type'] = mime_type
|
|
85
|
+
end
|
|
86
|
+
headers['Content-Encoding'] = 'gzip'
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
halt res
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
if public_file_readable?(path)
|
|
94
|
+
halt public_serve(server, path)
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
private
|
|
100
|
+
|
|
101
|
+
# Return an array of segments for the given path, handling ..
|
|
102
|
+
# and . components
|
|
103
|
+
def public_path_segments(path)
|
|
104
|
+
segments = []
|
|
105
|
+
|
|
106
|
+
path.split(SPLIT).each do |seg|
|
|
107
|
+
next if seg.empty? || seg == '.'
|
|
108
|
+
seg == '..' ? segments.pop : segments << seg
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
segments
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# Return whether the given path is a readable regular file.
|
|
115
|
+
def public_file_readable?(path)
|
|
116
|
+
::File.file?(path) && ::File.readable?(path)
|
|
117
|
+
rescue SystemCallError
|
|
118
|
+
# :nocov:
|
|
119
|
+
false
|
|
120
|
+
# :nocov:
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
if ::Rack.release > '2'
|
|
124
|
+
# Serve the given path using the given Rack::File server.
|
|
125
|
+
def public_serve(server, path)
|
|
126
|
+
server.serving(self, path)
|
|
127
|
+
end
|
|
128
|
+
else
|
|
129
|
+
# :nocov:
|
|
130
|
+
def public_serve(server, path)
|
|
131
|
+
server = server.dup
|
|
132
|
+
server.path = path
|
|
133
|
+
server.serving(env)
|
|
134
|
+
end
|
|
135
|
+
# :nocov:
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
register_plugin(:render_static, RenderStatic)
|
|
141
|
+
end
|
|
142
|
+
end
|
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
|
|
2
|
+
#dry schema enhance
|
|
3
|
+
require_relative "dry_schema_enhance.rb"
|
|
4
|
+
|
|
5
|
+
module DrySchemaExtend
|
|
6
|
+
class DrySchemaExendError < Exception
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
class SchemaInfoCompiler
|
|
10
|
+
EMPTY_HASH = {}
|
|
11
|
+
PREDICATE_TO_TYPE = {
|
|
12
|
+
array?: "array",
|
|
13
|
+
bool?: "bool",
|
|
14
|
+
date?: "date",
|
|
15
|
+
date_time?: "date_time",
|
|
16
|
+
decimal?: "decimal",
|
|
17
|
+
float?: "float",
|
|
18
|
+
hash?: "hash",
|
|
19
|
+
int?: "integer",
|
|
20
|
+
nil?: "nil",
|
|
21
|
+
str?: "string",
|
|
22
|
+
time?: "time",
|
|
23
|
+
}.freeze
|
|
24
|
+
|
|
25
|
+
# @api private
|
|
26
|
+
attr_reader :keys
|
|
27
|
+
|
|
28
|
+
# @api private
|
|
29
|
+
def initialize(schema)
|
|
30
|
+
@keys = EMPTY_HASH.dup
|
|
31
|
+
@schema = schema
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# @api private
|
|
35
|
+
def to_h
|
|
36
|
+
{ children: @keys, type: "hash" }
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# @api private
|
|
40
|
+
def call
|
|
41
|
+
visit(@schema.to_ast)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# @api private
|
|
45
|
+
def visit(node, opts = EMPTY_HASH)
|
|
46
|
+
meth, rest = node
|
|
47
|
+
public_send(:"visit_#{meth}", rest, opts)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# @api private
|
|
51
|
+
def visit_set(node, opts = EMPTY_HASH)
|
|
52
|
+
target = (key = opts[:key]) ? self.class.new(@schema) : self
|
|
53
|
+
|
|
54
|
+
node.map { |child| target.visit(child, opts) }
|
|
55
|
+
|
|
56
|
+
return unless key
|
|
57
|
+
|
|
58
|
+
target_info = opts[:member] ? { member: target.to_h } : target.to_h
|
|
59
|
+
type = opts[:member] ? "array" : "hash"
|
|
60
|
+
|
|
61
|
+
keys.update(key => { **keys[key], type: type, **target_info })
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# @api private
|
|
65
|
+
def visit_and(node, opts = EMPTY_HASH)
|
|
66
|
+
left, right = node
|
|
67
|
+
|
|
68
|
+
visit(left, opts)
|
|
69
|
+
visit(right, opts)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# @api private
|
|
73
|
+
def visit_implication(node, opts = EMPTY_HASH)
|
|
74
|
+
node.each do |el|
|
|
75
|
+
# p "--------------"
|
|
76
|
+
# p el
|
|
77
|
+
if el[0] == :predicate and el[1][0] == :key?
|
|
78
|
+
visit(el, opts.merge(required: false))
|
|
79
|
+
else
|
|
80
|
+
visit(el, opts)
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def visit_not(node, opts= EMPTY_HASH)
|
|
86
|
+
visit(node, opts.merge(not: true))
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# @api private
|
|
90
|
+
def visit_each(node, opts = EMPTY_HASH)
|
|
91
|
+
visit(node, opts.merge(member: true))
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# @api private
|
|
95
|
+
def visit_key(node, opts = EMPTY_HASH)
|
|
96
|
+
|
|
97
|
+
name, rest = node
|
|
98
|
+
# puts "visit_key is ### #{name}"
|
|
99
|
+
visit(rest, opts.merge(key: name, required: true, member: false)) # modified by zhanghz
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# @api private
|
|
103
|
+
def visit_predicate(node, opts = EMPTY_HASH)
|
|
104
|
+
name, rest = node
|
|
105
|
+
|
|
106
|
+
key = opts[:key]
|
|
107
|
+
|
|
108
|
+
if name.equal?(:key?)
|
|
109
|
+
# p "---key is #{rest[0][1]} #{opts}"
|
|
110
|
+
keys[rest[0][1]] = { required: opts.fetch(:required, true) }
|
|
111
|
+
else
|
|
112
|
+
type = PREDICATE_TO_TYPE[name]
|
|
113
|
+
# p opts
|
|
114
|
+
# p "rest predicate key is #{key} content is #{name}| #{rest}"
|
|
115
|
+
|
|
116
|
+
# modified by zhanghz
|
|
117
|
+
if opts[:member] == true
|
|
118
|
+
keys[key][:member] ||= {}
|
|
119
|
+
if type
|
|
120
|
+
if type == 'nil' and opts[:not] == true
|
|
121
|
+
keys[key][:member][:maybe] = type
|
|
122
|
+
else
|
|
123
|
+
keys[key][:member][:type] = type
|
|
124
|
+
end
|
|
125
|
+
keys[key][:type] = "array"
|
|
126
|
+
else
|
|
127
|
+
keys[key][:member][:validations] = [] unless keys[key][:member][:validations]
|
|
128
|
+
keys[key][:member][:validations] << predicate_message(key, name, rest)
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
else
|
|
132
|
+
if type
|
|
133
|
+
if type == 'nil' and opts[:not] == true
|
|
134
|
+
keys[key][:maybe] = type
|
|
135
|
+
else
|
|
136
|
+
keys[key][:type] = type
|
|
137
|
+
end
|
|
138
|
+
else
|
|
139
|
+
keys[key][:validations] = [] unless keys[key][:validations]
|
|
140
|
+
keys[key][:validations] << predicate_message(key, name, rest)
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def predicate_message(key, name, rest)
|
|
147
|
+
result = nil
|
|
148
|
+
if rest.count == 2
|
|
149
|
+
param_name = rest[0][0]
|
|
150
|
+
param_value = rest[0][1]
|
|
151
|
+
|
|
152
|
+
result = @schema.message_compiler.messages.get_message_for_key(name,{:path=> key, :arg_type => param_value.class})
|
|
153
|
+
if param_value.class == Range
|
|
154
|
+
result = result[:text].gsub("%{#{param_name}_left}", param_value.first.to_s).gsub("%{#{param_name}_right}", param_value.last.to_s)
|
|
155
|
+
else
|
|
156
|
+
result = result[:text].gsub("%{#{param_name}}", param_value.to_s)
|
|
157
|
+
end
|
|
158
|
+
else
|
|
159
|
+
result = @schema.message_compiler.messages.get_message_for_key(name,{:path=> key})
|
|
160
|
+
result = result[:text]
|
|
161
|
+
end
|
|
162
|
+
result
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
class SchemaExtendEdInfo
|
|
168
|
+
|
|
169
|
+
def self.define(&block)
|
|
170
|
+
desc = self.new
|
|
171
|
+
desc.instance_eval(&block)
|
|
172
|
+
desc
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
def initialize()
|
|
176
|
+
@schema_desc = {}
|
|
177
|
+
@current_field_name = nil
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
def required(field_name)
|
|
182
|
+
key(:required, field_name)
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
def optional(field_name)
|
|
186
|
+
key(:optional, field_name)
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
def hash(&block)
|
|
190
|
+
instance_eval(&block)
|
|
191
|
+
self
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
def get_desc
|
|
196
|
+
@schema_desc.transform_values do |field|
|
|
197
|
+
field.get_desc
|
|
198
|
+
end
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
private
|
|
205
|
+
def key(type, name)
|
|
206
|
+
if @schema_desc.key?(name)
|
|
207
|
+
raise DrySchemaExendError.new("the key: #{name} already exists")
|
|
208
|
+
end
|
|
209
|
+
field_desc = FieldExtendedInfo.new(name)
|
|
210
|
+
@schema_desc[name] = field_desc
|
|
211
|
+
@current_field_name = name
|
|
212
|
+
field_desc
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
class FieldExtendedInfo
|
|
220
|
+
|
|
221
|
+
def initialize(field_name)
|
|
222
|
+
@field_name = field_name
|
|
223
|
+
@desc = nil
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
def desc(**info)
|
|
227
|
+
@desc = info
|
|
228
|
+
self
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
def get_desc
|
|
233
|
+
result = {}
|
|
234
|
+
if @children
|
|
235
|
+
if @is_member
|
|
236
|
+
result[:member] = {}
|
|
237
|
+
result[:member][:children] = @children.get_desc
|
|
238
|
+
else
|
|
239
|
+
result[:children] = @children.get_desc
|
|
240
|
+
end
|
|
241
|
+
end
|
|
242
|
+
result[:desc] = @desc if @desc
|
|
243
|
+
result
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
def method_missing(method_name, *args, &block)
|
|
247
|
+
rest_method(method_name, *args, &block)
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
def hash(*arg, &block)
|
|
251
|
+
rest_method(:hash, *arg, &block)
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
private
|
|
256
|
+
def rest_method(method_name, *args, &block)
|
|
257
|
+
if block_given?
|
|
258
|
+
sub_schema_desc = SchemaExtendEdInfo.new
|
|
259
|
+
sub_schema_desc.instance_eval(&block)
|
|
260
|
+
@children = sub_schema_desc
|
|
261
|
+
if method_name == :array or method_name == :each
|
|
262
|
+
@is_member = true
|
|
263
|
+
end
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
if args[0].class == SchemaExtendEdInfo
|
|
267
|
+
@children = args[0]
|
|
268
|
+
end
|
|
269
|
+
self
|
|
270
|
+
end
|
|
271
|
+
end
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
module Dry
|
|
277
|
+
module Schema
|
|
278
|
+
module Macros
|
|
279
|
+
# Macro specialization used within the DSL
|
|
280
|
+
#
|
|
281
|
+
# @api public
|
|
282
|
+
class DSL
|
|
283
|
+
def desc(*args)
|
|
284
|
+
self
|
|
285
|
+
end
|
|
286
|
+
end
|
|
287
|
+
end
|
|
288
|
+
end
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
|
|
293
|
+
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
require 'semantic_logger'
|
|
2
|
+
|
|
3
|
+
class Roda
|
|
4
|
+
module RodaPlugins
|
|
5
|
+
module UniLogger
|
|
6
|
+
|
|
7
|
+
module InstanceMethods
|
|
8
|
+
include SemanticLogger::Loggable
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
module ClassMethods
|
|
12
|
+
include SemanticLogger::Loggable
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
register_plugin(:uni_logger, UniLogger)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module SymbolizeHelper
|
|
2
|
+
extend self
|
|
3
|
+
def symbolize_recursive(hash)
|
|
4
|
+
{}.tap do |h|
|
|
5
|
+
hash.each { |key, value| h[key.to_sym] = map_value(value) }
|
|
6
|
+
end
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def map_value(thing)
|
|
10
|
+
case thing
|
|
11
|
+
when Hash
|
|
12
|
+
symbolize_recursive(thing)
|
|
13
|
+
when Array
|
|
14
|
+
thing.map { |v| map_value(v) }
|
|
15
|
+
else
|
|
16
|
+
thing
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
data/lib/zleb/version.rb
ADDED
data/lib/zleb.rb
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
require "zleb/version"
|
|
2
|
+
require "zleb/symbolize_helper"
|
|
3
|
+
require "zleb/controller"
|
|
4
|
+
|
|
5
|
+
require 'roda'
|
|
6
|
+
|
|
7
|
+
# for logging
|
|
8
|
+
require 'semantic_logger'
|
|
9
|
+
|
|
10
|
+
if ENV['RACK_ENV'] == 'development'
|
|
11
|
+
SemanticLogger.default_level = :trace # :trace
|
|
12
|
+
# SemanticLogger.backtrace_level = :trace
|
|
13
|
+
# SemanticLogger.add_appender(io: $stderr, level: :error)
|
|
14
|
+
SemanticLogger.add_appender(io: $stdout, formatter: :color)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# add logger to Object
|
|
18
|
+
class Object
|
|
19
|
+
include SemanticLogger::Loggable
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
require 'roda/session_middleware'
|
|
23
|
+
|
|
24
|
+
require 'zleb/plugins/params_check'
|
|
25
|
+
require 'zleb/plugins/render_static'
|
|
26
|
+
require 'zleb/plugins/uni_logger'
|
|
27
|
+
require 'zleb/plugins/params_snake_keys'
|
|
28
|
+
require 'zleb/plugins/basic_restful_action'
|
|
29
|
+
require 'zleb/plugins/api_route'
|
|
30
|
+
require 'zleb/plugins/method_route'
|
|
31
|
+
require 'zleb/plugins/http_auth'
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
#转换为驼峰
|
|
35
|
+
require 'awrence'
|
|
36
|
+
#转换为snake
|
|
37
|
+
require 'plissken'
|
|
38
|
+
|
|
39
|
+
module Zleb
|
|
40
|
+
class Error < StandardError; end
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
module Config
|
|
44
|
+
def self.prefix
|
|
45
|
+
@prefix || 'api'
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def self.prefix=(pre)
|
|
49
|
+
@prefix = pre
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def self.controller_module
|
|
53
|
+
@controller_module
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def self.controller_module=(c)
|
|
57
|
+
@controller_module = c
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def self.set_global_check(&block)
|
|
61
|
+
@global_check = block
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def self.global_check=(c)
|
|
65
|
+
@global_check = c
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def self.global_check
|
|
69
|
+
@global_check
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
class BaseApp < Roda
|
|
75
|
+
|
|
76
|
+
plugin :empty_root
|
|
77
|
+
plugin :all_verbs
|
|
78
|
+
|
|
79
|
+
json_serializer = proc do |res, req|
|
|
80
|
+
if req.headers['X-Convert-Key'] == 'true'
|
|
81
|
+
res.to_camelback_keys.to_json
|
|
82
|
+
else
|
|
83
|
+
res.to_json
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
plugin :request_headers
|
|
88
|
+
plugin :json, include_request: true, classes: [Array, Hash], serializer: json_serializer
|
|
89
|
+
plugin :params_snake_keys
|
|
90
|
+
|
|
91
|
+
plugin :json_parser #, parser: proc{|req| JSON.parse(req).to_snake_keys}
|
|
92
|
+
plugin :hash_routes
|
|
93
|
+
plugin :public
|
|
94
|
+
plugin :params_check
|
|
95
|
+
plugin :basic_restful_action
|
|
96
|
+
plugin :render_static
|
|
97
|
+
|
|
98
|
+
plugin :uni_logger
|
|
99
|
+
plugin :cookies
|
|
100
|
+
plugin :symbolized_params
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
plugin :api_route
|
|
104
|
+
# plugin :error_handler, classes: [Mongoid::Errors::DocumentNotFound] do |e|
|
|
105
|
+
# response.status = 406
|
|
106
|
+
# { error: "object is not existed" }
|
|
107
|
+
# end
|
|
108
|
+
|
|
109
|
+
# plugin :not_found do |r|
|
|
110
|
+
# r.render_static(File.join(Prefix, 'index.html'))
|
|
111
|
+
# # {error: "not found #{r.path}"}
|
|
112
|
+
# end
|
|
113
|
+
|
|
114
|
+
secret = ENV.delete('SESSION_SECRET') || SecureRandom.random_bytes(64)
|
|
115
|
+
use RodaSessionMiddleware, secret: secret
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
class App < BaseApp
|
|
119
|
+
plugin :method_route
|
|
120
|
+
|
|
121
|
+
GlobalCheck =
|
|
122
|
+
|
|
123
|
+
route do |r|
|
|
124
|
+
r.public
|
|
125
|
+
r.on Config.prefix do
|
|
126
|
+
instance_eval(&Config.global_check) if Config.global_check
|
|
127
|
+
r.method_to Config.controller_module if Config.controller_module
|
|
128
|
+
r.hash_routes(:api)
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
end
|
|
133
|
+
end
|
data/push.sh
ADDED
data/zleb.gemspec
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
require_relative 'lib/zleb/version'
|
|
2
|
+
|
|
3
|
+
Gem::Specification.new do |spec|
|
|
4
|
+
spec.name = "zleb"
|
|
5
|
+
spec.version = Zleb::VERSION
|
|
6
|
+
spec.authors = ["saidev"]
|
|
7
|
+
spec.email = ["saidev@163.com"]
|
|
8
|
+
|
|
9
|
+
spec.summary = %q{a more convenient web framework}
|
|
10
|
+
spec.description = %q{a more convenient web framework}
|
|
11
|
+
spec.homepage = "https://github.com/bluesaiz/zleb"
|
|
12
|
+
spec.license = "MIT"
|
|
13
|
+
spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
|
|
14
|
+
|
|
15
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
|
16
|
+
spec.metadata["source_code_uri"] = spec.homepage
|
|
17
|
+
spec.metadata["changelog_uri"] = spec.homepage
|
|
18
|
+
|
|
19
|
+
# Specify which files should be added to the gem when it is released.
|
|
20
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
|
21
|
+
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
|
22
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
|
23
|
+
end
|
|
24
|
+
spec.bindir = "exe"
|
|
25
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
|
26
|
+
spec.require_paths = ["lib"]
|
|
27
|
+
|
|
28
|
+
spec.add_dependency "roda", '~> 3.52'
|
|
29
|
+
spec.add_dependency "roda-symbolized_params", '~> 0.0.2'
|
|
30
|
+
spec.add_dependency "dry-validation", '~> 1.6'
|
|
31
|
+
spec.add_dependency 'puma', '~> 6.4'
|
|
32
|
+
spec.add_dependency "semantic_logger", "~> 4.7", ">= 4.7.4"
|
|
33
|
+
|
|
34
|
+
spec.add_dependency "awrence", "~> 1.2", ">= 1.2.1"
|
|
35
|
+
spec.add_dependency "plissken", "~> 1.4", ">= 1.4.1"
|
|
36
|
+
spec.add_dependency "concurrent-ruby"
|
|
37
|
+
|
|
38
|
+
spec.add_dependency "dry-schema", "= 1.13.3"
|
|
39
|
+
spec.add_dependency "dry-container", "~> 0.7"
|
|
40
|
+
|
|
41
|
+
spec.add_development_dependency 'rack-test'
|
|
42
|
+
|
|
43
|
+
end
|