keight 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +263 -0
  4. data/Rakefile +92 -0
  5. data/bench/bench.rb +278 -0
  6. data/bench/benchmarker.rb +502 -0
  7. data/bin/k8rb +496 -0
  8. data/keight.gemspec +36 -0
  9. data/lib/keight/skeleton/.gitignore +10 -0
  10. data/lib/keight/skeleton/app/action.rb +98 -0
  11. data/lib/keight/skeleton/app/api/hello.rb +39 -0
  12. data/lib/keight/skeleton/app/form/.keep +0 -0
  13. data/lib/keight/skeleton/app/helper/.keep +0 -0
  14. data/lib/keight/skeleton/app/model/.keep +0 -0
  15. data/lib/keight/skeleton/app/model.rb +144 -0
  16. data/lib/keight/skeleton/app/page/welcome.rb +17 -0
  17. data/lib/keight/skeleton/app/template/_layout.html.eruby +56 -0
  18. data/lib/keight/skeleton/app/template/welcome.html.eruby +6 -0
  19. data/lib/keight/skeleton/app/usecase/.keep +0 -0
  20. data/lib/keight/skeleton/config/app.rb +29 -0
  21. data/lib/keight/skeleton/config/app_dev.private +11 -0
  22. data/lib/keight/skeleton/config/app_dev.rb +8 -0
  23. data/lib/keight/skeleton/config/app_prod.rb +7 -0
  24. data/lib/keight/skeleton/config/app_stg.rb +5 -0
  25. data/lib/keight/skeleton/config/app_test.private +11 -0
  26. data/lib/keight/skeleton/config/app_test.rb +8 -0
  27. data/lib/keight/skeleton/config/server_puma.rb +22 -0
  28. data/lib/keight/skeleton/config/server_unicorn.rb +21 -0
  29. data/lib/keight/skeleton/config/urlpath_mapping.rb +16 -0
  30. data/lib/keight/skeleton/config.rb +44 -0
  31. data/lib/keight/skeleton/config.ru +21 -0
  32. data/lib/keight/skeleton/index.txt +38 -0
  33. data/lib/keight/skeleton/static/lib/jquery/1.11.3/jquery.min.js +6 -0
  34. data/lib/keight/skeleton/static/lib/jquery/1.11.3/jquery.min.js.gz +0 -0
  35. data/lib/keight/skeleton/static/lib/modernizr/2.8.3/modernizr.min.js +4 -0
  36. data/lib/keight/skeleton/static/lib/modernizr/2.8.3/modernizr.min.js.gz +0 -0
  37. data/lib/keight/skeleton/tmp/upload/.keep +0 -0
  38. data/lib/keight.rb +2017 -0
  39. data/test/data/example1.jpg +0 -0
  40. data/test/data/example1.png +0 -0
  41. data/test/data/multipart.form +0 -0
  42. data/test/data/wabisabi.js +77 -0
  43. data/test/data/wabisabi.js.gz +0 -0
  44. data/test/keight_test.rb +3161 -0
  45. data/test/oktest.rb +1537 -0
  46. metadata +114 -0
data/bin/k8rb ADDED
@@ -0,0 +1,496 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+
4
+ ###
5
+ ### $Release: 0.0.1 $
6
+ ### $Copyright: copyright(c) 2014-2015 kuwata-lab.com all rights reserved $
7
+ ### $License: MIT License $
8
+ ###
9
+
10
+
11
+ require 'digest/sha1'
12
+
13
+ require 'keight'
14
+ require 'baby_erubis'
15
+
16
+
17
+ module K8
18
+
19
+
20
+ class Main
21
+
22
+ @__current = nil
23
+ @__actions = []
24
+
25
+ @action = proc do |action_name, desc|
26
+ options = []
27
+ method_name = nil
28
+ tuple = [action_name, desc, options, method_name]
29
+ @__current = tuple
30
+ @__actions << tuple
31
+ end
32
+
33
+ @option = proc do |optdef_str, desc|
34
+ tuple = @__current or
35
+ raise "@option.() is called without @action.()"
36
+ tuple[2] << [optdef_str, desc]
37
+ end
38
+
39
+ def self.method_added(method_name)
40
+ tuple = @__current or return
41
+ tuple[3] = method_name
42
+ @__current = nil
43
+ end
44
+
45
+ def self.find_action(name)
46
+ name = name.to_s
47
+ return @__actions.find {|tuple| tuple[0].to_s == name }
48
+ end
49
+
50
+ def self.each_action(&block)
51
+ @__actions.each(&block)
52
+ end
53
+
54
+
55
+ ###
56
+
57
+ def initialize(script_name=nil)
58
+ @script_name = script_name || File.basename($0) # ex: 'k8rb'
59
+ end
60
+
61
+ attr_reader :script_name
62
+
63
+
64
+ ### actions
65
+
66
+ @action.(:help, "show help")
67
+ def do_help(action_name=nil)
68
+ script = self.script_name
69
+ sb = []
70
+ if action_name.nil?
71
+ sb << "Usage:"
72
+ sb << " #{script} ACTION [..OPTIONS..]"
73
+ sb << ""
74
+ sb << "Actions:"
75
+ self.class.each_action do |action_name, desc, options, _|
76
+ next unless desc
77
+ help = desc.lines.first.chomp()
78
+ sb << " #{script} %-15s # #{help}" % [action_name, help]
79
+ end
80
+ sb << ""
81
+ sb << "(Tips: try '#{script} help ACTION' for details of each action.)"
82
+ else
83
+ tuple = self.class.find_action(action_name) or
84
+ raise K8::OptionError.new("help #{action_name}: no such action.")
85
+ action_name, desc, options, method_name = tuple
86
+ pnames = self.method(method_name).parameters.collect {|kind, pname|
87
+ case kind
88
+ when :req ; pname
89
+ when :opt ; "[#{pname}]"
90
+ when :rest ; "[#{pname}...]"
91
+ when :key ; nil
92
+ else
93
+ raise "** kind=#{kind.inspect}, pname=#{pname.inspect}"
94
+ end
95
+ }.compact()
96
+ pnames.unshift('') unless pnames.empty?
97
+ argstr = pnames.join(' ')
98
+ sb << "#{script} #{action_name} - #{desc}"
99
+ sb << ""
100
+ sb << "Usage:"
101
+ if options.empty?
102
+ sb << " #{script} #{action_name}#{argstr}"
103
+ else
104
+ sb << " #{script} #{action_name} [options]#{argstr}"
105
+ sb << ""
106
+ sb << "Options:"
107
+ options.each do |optdef_str, optdesc|
108
+ optstr = optdef_str.sub(/\A\s*--/, ' --').sub(/\s+\#\w+\s*\z/, '')
109
+ sb << " %-20s # %s" % [optstr, optdesc] if optdesc
110
+ end
111
+ end
112
+ end
113
+ sb << ""
114
+ sb << ""
115
+ return sb.join("\n")
116
+ end
117
+
118
+ @action.(:init, "create project files")
119
+ @option.("-s, --skeleton=DIR", "directory of skeleton files")
120
+ def do_init(project_name, dir: nil)
121
+ dir ||= K8::FILEPATH.sub(/\.rb\z/, '') + "/skeleton"
122
+ if dir
123
+ File.directory?(dir) or
124
+ raise "#{dir}: directory not exist."
125
+ o = K8::FileTool.new
126
+ descs = o.parse_index_file("#{dir}/index.txt")
127
+ o.mkdir(project_name, "project root directory")
128
+ files = Dir.glob("#{dir}/**/*")
129
+ files.concat(["#{dir}/.gitignore"])
130
+ files.each do |path|
131
+ base = path[(dir.length+1)..-1]
132
+ if base == "index.txt"
133
+ next
134
+ elsif base =~ /\/\.keep\z/
135
+ next
136
+ elsif File.directory?(path)
137
+ o.mkdir("#{project_name}/#{base}", descs[base+"/"])
138
+ elsif File.file?(path)
139
+ content = path =~ /\Astatic\/lib|\.gz\z/ \
140
+ ? File.read(path, encoding: 'ascii-8bit') \
141
+ : K8::SkeletonTemplate.new.from_file(path, 'ascii-8bit').render()
142
+ o.mkfile("#{project_name}/#{base}", content, descs[base])
143
+ else
144
+ next
145
+ end
146
+ end
147
+ return
148
+ end
149
+ 0
150
+ end
151
+
152
+ @action.(:mapping, "show action mappings")
153
+ def do_mapping()
154
+ ENV['APP_MODE'] ||= 'dev'
155
+ load_config()
156
+ require './config/urlpath_mapping'
157
+ app = K8::RackApplication.new
158
+ $urlpath_mapping.each do |urlpath, children|
159
+ app.mount(urlpath, children)
160
+ end
161
+ return app.show_mappings()
162
+ end
163
+
164
+ @action.(:configs, "list config keys and values")
165
+ @option.("--getenv", "show actual ENV value")
166
+ def do_configs(getenv: false)
167
+ ENV['APP_MODE'] ||= 'dev'
168
+ load_config()
169
+ s = ""
170
+ ::Config.each do |key, val, desc, secret|
171
+ kv = "%-20s = %s" % [key, __var_dump(val, secret, getenv)]
172
+ s << ("%-43s # %s\n" % [kv, desc]) if desc
173
+ end
174
+ return s
175
+ end
176
+
177
+ @action.(:config, "show config value")
178
+ @option.("--getenv", "show actual ENV value")
179
+ def do_config(key, getenv: false)
180
+ key_name = key
181
+ ENV['APP_MODE'] ||= 'dev'
182
+ load_config()
183
+ ::Config.each do |key, val, desc, secret|
184
+ if key.to_s == key_name
185
+ return __var_dump(val, secret, getenv)
186
+ end
187
+ end
188
+ $stderr.puts "#{key_name}: no such config key."
189
+ return 1
190
+ end
191
+
192
+ @action.(:'config:check', "check config values")
193
+ def do_config_check()
194
+ ENV['APP_MODE'] ||= 'dev'
195
+ load_config()
196
+ not_set = []
197
+ not_env = []
198
+ ::Config.each do |key, val, desc, secret|
199
+ if val.is_a?(K8::SecretValue)
200
+ if ! val.name
201
+ not_set << [key, val, desc]
202
+ elsif ! ENV[val.name]
203
+ not_env << [key, val, desc]
204
+ end
205
+ end
206
+ end
207
+ if not_set.empty? && not_env.empty?
208
+ puts "ok."
209
+ return 0
210
+ else
211
+ sb = []
212
+ sb << "**"
213
+ sb << "** NG!"
214
+ unless not_set.empty?
215
+ sb << "**"
216
+ sb << "** The following configs should be set, but not."
217
+ sb << "**"
218
+ not_set.each do |key, val, desc|
219
+ sb << "** %-20s = %s" % [key, val.inspect]
220
+ end
221
+ end
222
+ unless not_env.empty?
223
+ sb << "**"
224
+ sb << "** The following configs expect environment variable, but not set."
225
+ sb << "**"
226
+ not_env.each do |key, val, desc|
227
+ sb << "** %-20s = %s" % [key, val.inspect]
228
+ end
229
+ end
230
+ sb << "**"
231
+ puts sb.join("\n")
232
+ return 1
233
+ end
234
+ end
235
+
236
+ def __var_dump(val, secret, getenv)
237
+ if ! val.is_a?(K8::SecretValue)
238
+ #secret ? '<secret>' : val.inspect
239
+ val.inspect
240
+ elsif val.name
241
+ getenv ? ENV[val.name].inspect : "ENV['#{val.name}']"
242
+ else
243
+ '<SECRET>'
244
+ end
245
+ end
246
+ private :__var_dump
247
+
248
+
249
+ if ENV['DEBUG']
250
+ @action.(:debug, "debug")
251
+ @option.("-h, --help" , "show help message")
252
+ @option.("--version" , "print version")
253
+ #@option.("-f, --file=FILE" , "filename")
254
+ @option.("-f FILE #file" , "filename")
255
+ @option.("-i, --indent[=N]" , "indent depth (default 2)")
256
+ @option.("-s" , "be silent")
257
+ @option.("-S #silent" , "be silent")
258
+ @option.("-d[N] #dbg1" , "debug level #1")
259
+ @option.(" --dbg2[=N]" , "debug level #2")
260
+ def do_debug(argmnt=nil, help: nil, version: nil, file: nil, indent: nil, s: nil, silent: false, dbg1: nil, dbg2: nil)
261
+ sb = []
262
+ sb << "** argmnt = #{argmnt.inspect}"
263
+ sb << "** help: #{help.inspect}"
264
+ sb << "** version: #{version.inspect}"
265
+ sb << "** file: #{file.inspect}"
266
+ sb << "** indent: #{indent.inspect}"
267
+ sb << "** s: #{s.inspect}"
268
+ sb << "** silent: #{silent.inspect}"
269
+ sb << "** dbg1: #{dbg1.inspect}"
270
+ sb << "** dbg2: #{dbg2.inspect}"
271
+ return sb.join("\n")
272
+ end
273
+ end
274
+
275
+
276
+ ###
277
+
278
+ def load_config
279
+ require './config' rescue K8::ConfigError
280
+ end
281
+
282
+ def run(*cmd_args)
283
+ action_name = cmd_args.shift() || 'help'
284
+ tuple = self.class.find_action(action_name) or
285
+ raise K8::OptionError.new("#{action_name}: unknown action.")
286
+ action_name, desc, options, method_name = tuple
287
+ optdefs = options.collect {|arr| K8::OptionDefinition.new(*arr) }
288
+ optparser = K8::OptionParser.new(optdefs)
289
+ cmd_opts = optparser.parse(cmd_args)
290
+ func_args = []
291
+ func_kwds = {}
292
+ method_params = self.method(method_name).parameters
293
+ method_params.each do |param_info|
294
+ kind, pname = param_info
295
+ case kind
296
+ when :req
297
+ ! cmd_args.empty? or
298
+ raise K8::OptionError.new("#{action_name}: argument '#{pname}' required.")
299
+ func_args << cmd_args.shift()
300
+ when :opt
301
+ func_args << cmd_args.shift() # may be nil
302
+ when :rest
303
+ func_args.concat(cmd_args)
304
+ cmd_args.clear()
305
+ when :key
306
+ k = pname.to_s
307
+ func_kwds[pname] = cmd_opts.delete(k) if cmd_opts.key?(k)
308
+ if cmd_opts.key?(pname.to_s)
309
+ func_kwds[pname] = cmd_opts.delete(pname.to_s)
310
+ end
311
+ else
312
+ $stderr.puts "*** internal error: kind=#{kind.inspect}, pname=#{pname.inspect}"
313
+ end
314
+ end
315
+ cmd_args.empty? or
316
+ raise K8::OptionError.new("#{action_name}: too many argument.")
317
+ cmd_opts.empty? or
318
+ raise K8::OptionError.new("#{action_name}: keyword arg not defined (#{cmd_opts.inspect}).")
319
+ if func_kwds.empty?
320
+ output = __send__(method_name, *func_args)
321
+ else
322
+ output = __send__(method_name, *func_args, func_kwds)
323
+ end
324
+ return output
325
+ end
326
+
327
+ def self.main
328
+ status = 0
329
+ obj = self.new()
330
+ begin
331
+ output = obj.run(*ARGV)
332
+ case output
333
+ when nil ;
334
+ when String ; puts output
335
+ when Integer ; status = output
336
+ else ; raise "** output=#{output.inspect}"
337
+ end
338
+ rescue K8::OptionError => ex
339
+ $stderr.puts "ERROR (#{obj.script_name}): #{ex}"
340
+ output = nil
341
+ status = 1
342
+ end
343
+ exit status
344
+ end
345
+
346
+ end
347
+
348
+
349
+ class OptionDefinition
350
+
351
+ def initialize(defstr, desc)
352
+ @defstr = defstr
353
+ @desc = desc
354
+ parse(defstr)
355
+ end
356
+
357
+ attr_reader :defstr, :name, :desc, :short, :long, :argstr, :arg_required
358
+
359
+ def parse(defstr)
360
+ case defstr
361
+ when /\A\s*-(\w),\s+--(\w[-\w]*)(?:=(\S*)|\[=(\S+)\])?(?:\s+\#(\w+))?\z/
362
+ short, long, arg1, arg2, optname = $1, $2, $3, $4, $5
363
+ when /\A\s*--(\w[-\w]*)(?:=(\S*)|\[=(\S+)\])?(?:\s+\#(\w+))?\z/
364
+ short, long, arg1, arg2, optname = nil, $1, $2, $3, $4
365
+ when /\A\s*-(\w)(?:\s+(\S+)|\[(\S+)\])?(?:\s+\#(\w+))?\z/
366
+ short, long, arg1, arg2, optname = $1, nil, $2, $3, $4
367
+ else
368
+ raise "#{defstr.inspect}: invalid option definition."
369
+ end
370
+ @short = short
371
+ @long = long
372
+ @argstr = arg1 || arg2
373
+ @arg_required = !! arg1 # true when option argument is required
374
+ @name = optname || long || short
375
+ end
376
+
377
+ end
378
+
379
+
380
+ class OptionParser
381
+
382
+ def initialize(optdefs)
383
+ @optdefs = optdefs
384
+ end
385
+
386
+ def parse(cmd_args)
387
+ options = {}
388
+ while cmd_args.length > 0 && cmd_args.first.start_with?('-')
389
+ optstr = cmd_args.shift()
390
+ if optstr == '--'
391
+ break
392
+ elsif optstr.start_with?('--')
393
+ optstr =~ /\A--(\w+)(?:=(.*))?\z/ or
394
+ raise OptionError.new("#{optstr}: invalid option.")
395
+ long, optarg = $1, $2
396
+ optdef = @optdefs.find {|x| x.long == long } or
397
+ raise OptionError.new("#{optstr}: unknown option.")
398
+ if ! optdef.argstr && optarg
399
+ raise OptionError.new("#{optstr}: unexpected argument.")
400
+ elsif optdef.arg_required && ! optarg
401
+ raise OptionError.new("#{optstr}: argument required.")
402
+ end
403
+ options[optdef.name] = optarg || true
404
+ else
405
+ i = 0; len = optstr.length
406
+ while (i += 1) < len
407
+ ch = optstr[i]
408
+ optdef = @optdefs.find {|x| x.short == ch } or
409
+ raise OptionError.new("-#{ch}: unknown option.")
410
+ if ! optdef.argstr # no arg
411
+ optarg = true
412
+ elsif ! optdef.arg_required # optional arg
413
+ optarg = i + 1 < len ? optstr[(i+1)..-1] : true
414
+ i = len - 1
415
+ else # required arg
416
+ optarg = optstr[(i+1)..-1]
417
+ if optarg.empty?
418
+ optarg = cmd_args.shift() or
419
+ raise OptionError.new("-#{ch}: argument required.")
420
+ end
421
+ i = len - 1
422
+ end
423
+ options[optdef.name] = optarg
424
+ end
425
+ end
426
+ end
427
+ return options
428
+ end
429
+
430
+ end
431
+
432
+
433
+ class OptionError < StandardError
434
+ end
435
+
436
+
437
+ class SkeletonTemplate < BabyErubis::Text
438
+
439
+ rexp = BabyErubis::Text::PATTERN
440
+ PATTERN = Regexp.compile(rexp.to_s.sub(/<%/, '\{%').sub(/%>/, '%\}'))
441
+
442
+ def pattern
443
+ PATTERN
444
+ end
445
+
446
+ end
447
+
448
+
449
+ class FileTool
450
+
451
+ def initialize(width: 30)
452
+ @width = width
453
+ @depth = 0
454
+ end
455
+
456
+ def parse_index_file(index_file)
457
+ dict = File.open(index_file) {|f|
458
+ f.grep(/^[^#]/).each_with_object({}) {|line, d|
459
+ path, desc = line.chomp.split(/\s+/, 2)
460
+ d[path] = desc
461
+ }
462
+ }
463
+ return dict
464
+ end
465
+
466
+ def report(s, desc)
467
+ indent = ' ' * @depth
468
+ puts "%s%-#{@width - indent.length}s # %s" % [indent, s, desc]
469
+ end
470
+
471
+ def mkrootdir(dirpath)
472
+ @root = dirpath
473
+ mkdir(dirpath)
474
+ end
475
+
476
+ def mkdir(dirpath, desc)
477
+ Dir.mkdir dirpath
478
+ s = dirpath.gsub(/.*?[\/\\]/, ' ') + "/"
479
+ report(s, desc)
480
+ end
481
+
482
+ def mkfile(filepath, content, desc)
483
+ File.open(filepath, 'wb') {|dst| dst.write(content) }
484
+ s = filepath.gsub(/.*?[\/\\]/, ' ')
485
+ report(s, desc)
486
+ end
487
+
488
+ end
489
+
490
+
491
+ end
492
+
493
+
494
+ #if __FILE__ == $0
495
+ K8::Main.main() unless defined? NOEXEC_SCRIPT
496
+ #end
data/keight.gemspec ADDED
@@ -0,0 +1,36 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+
4
+ Gem::Specification.new do |o|
5
+ o.name = "keight"
6
+ o.version = "$Release: 0.0.1 $".split[1]
7
+ o.author = "makoto kuwata"
8
+ o.email = "kwa(at)kuwata-lab.com"
9
+ o.platform = Gem::Platform::RUBY
10
+ o.homepage = "https://github.com/kwatch/keight/tree/ruby"
11
+ o.license = "MIT Lisense"
12
+ o.summary = "Jet-speed webapp framework for Ruby"
13
+ o.description = <<'END'
14
+ Keight.rb is the crazy-fast webapp framework for Ruby.
15
+ It is about 100 times faster than Rails and 20 times faster than Sinatra.
16
+
17
+ See https://github.com/kwatch/keight/tree/ruby for details.
18
+ END
19
+
20
+ o.files = Dir[*%w[
21
+ README.md MIT-LICENSE keight.gemspec setup.rb Rakefile
22
+ bin/k8rb
23
+ lib/keight.rb lib/keight/**/*.{[a-z]*} lib/keight/**/.{[a-z]*}
24
+ test/*_test.rb test/data/* test/oktest.rb
25
+ bench/bench.rb bench/benchmarker.rb
26
+ ]]
27
+ #lib/keight.rb lib/keight/**/*
28
+ o.executables = ["k8rb"]
29
+ o.bindir = ["bin"]
30
+ #o.test_files = o.files.grep(/^test\//)
31
+ o.test_file = "test/keight_test.rb"
32
+
33
+ o.required_ruby_version = '>= 2.0'
34
+ o.add_runtime_dependency 'baby_erubis', '~> 2.1', '>= 2.1.1'
35
+ #o.add_development_dependency "oktest", "~> 0"
36
+ end
@@ -0,0 +1,10 @@
1
+ config/*.private
2
+ *.cache
3
+ *.gem
4
+ *.rbc
5
+ tmp/
6
+ .bundle
7
+ .rvmrc
8
+ .repl_history
9
+ .yardoc
10
+ _yardoc
@@ -0,0 +1,98 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'keight'
4
+ require 'baby_erubis'
5
+ require 'baby_erubis/renderer'
6
+
7
+ require './config'
8
+
9
+
10
+ module My
11
+ end
12
+
13
+
14
+ class My::Action < K8::Action
15
+
16
+
17
+ ##
18
+ ## template
19
+ ##
20
+
21
+ include BabyErubis::HtmlEscaper
22
+ include BabyErubis::Renderer
23
+
24
+ ERUBY_PATH = ['app/template']
25
+ ERUBY_LAYOUT = :_layout
26
+ ERUBY_HTML = BabyErubis::Html
27
+ ERUBY_HTML_EXT = '.html.eruby'
28
+ ERUBY_TEXT = BabyErubis::Text
29
+ ERUBY_TEXT_EXT = '.eruby'
30
+ ERUBY_CACHE = {}
31
+
32
+ protected
33
+
34
+ alias render_html eruby_render_html
35
+ alias render_text eruby_render_text
36
+
37
+
38
+ ##
39
+ ## event handler (= exception handler)
40
+ ##
41
+
42
+ protected
43
+
44
+ ##
45
+ ## Define event handlers here.
46
+ ##
47
+ ## ex:
48
+ ## class Event < Exception; end
49
+ ## class NotExist < Event; end
50
+ ## class NotPermitted < Event; end
51
+ ##
52
+ ## def on_NotExist(ev) # or: define_method "on_Foo::Bar" do |ev|
53
+ ## @resp.status_code = 404 # 404 Not Found
54
+ ## {"error"=>"Not exist"}
55
+ ## end
56
+ ## def on_NotPermitted(ev)
57
+ ## @resp.status_code = 403 # 403 Forbidden
58
+ ## {"error"=>"Not permitted"}
59
+ ## end
60
+ ##
61
+ ## def do_show(id)
62
+ ## item = Item.find(id) or raise NotExist
63
+ ## return {"item"=>{"id"=>id, "name"=>item.name}}
64
+ ## end
65
+ ##
66
+
67
+
68
+ end
69
+
70
+
71
+ class My::AdminAction < My::Action
72
+
73
+ ## override template configs
74
+ ERUBY_PATH = ['admin/template']
75
+ ERUBY_LAYOUT = :_admin_layout
76
+
77
+ end
78
+
79
+
80
+ class My::StaticPage < My::Action
81
+
82
+ mapping '/{urlpath:.+}', :GET=>:do_send_file
83
+ STATIC_DIR = "static"
84
+
85
+ def do_send_file(urlpath)
86
+ filepath = "#{STATIC_DIR}/#{urlpath}"
87
+ File.file?(filepath) or raise K8::HttpException.new(404)
88
+ #env = @req.env
89
+ #header_name = env['sendfile.type'] || env['HTTP_X_SENDFILE_TYPE']
90
+ #if header_name && ! header_name.empty?
91
+ # @resp.headers[header_name] = filepath
92
+ # return nil
93
+ #else
94
+ return send_file(filepath)
95
+ #end
96
+ end
97
+
98
+ end
@@ -0,0 +1,39 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'keight'
4
+
5
+ #require_relative '../action'
6
+
7
+
8
+ class HelloAPI < K8::Action # or My::Action
9
+
10
+ mapping '' , :GET=>:do_index, :POST=>:do_create
11
+ mapping '/{id}' , :GET=>:do_show, :PUT=>:do_update, :DELETE=>:do_delete
12
+ ## or if you want support '/hello.json' and '/hello/123.json':
13
+ #mapping '{ext}' , :GET=>:do_index, :POST=>:do_create
14
+ #mapping '/{id}{ext}' , :GET=>:do_show, :PUT=>:do_update, :DELETE=>:do_delete
15
+
16
+ def do_index()
17
+ query = @req.params_query # QUERY_STRING
18
+ {"action"=>"index", "query"=>query}
19
+ end
20
+
21
+ def do_create()
22
+ form = @req.params_form # or @req.params_json
23
+ {"action"=>"create", "form"=>form}
24
+ end
25
+
26
+ def do_show(id)
27
+ {"action"=>"show", "id"=>id}
28
+ end
29
+
30
+ def do_update(id)
31
+ form = @req.params_form # or @req.params_json
32
+ {"action"=>"update", "id"=>id, "form"=>form}
33
+ end
34
+
35
+ def do_delete(id)
36
+ {"action"=>"delete", "id"=>id}
37
+ end
38
+
39
+ end
File without changes
File without changes
File without changes