casual-api 3.0.6 → 3.0.7
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/lib/action.rb +126 -0
- data/lib/annotation.rb +47 -0
- data/lib/body_writer.rb +29 -0
- data/lib/casual.rb +12 -51
- data/lib/child_process.rb +22 -0
- data/lib/dsl.rb +25 -233
- data/lib/errors.rb +9 -0
- data/lib/ext_expression.rb +8 -0
- data/lib/request_checker.rb +60 -0
- data/lib/syntax_sugar.rb +46 -0
- metadata +10 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9853c2f2400652c1be412d4e1d06a1c225fdb0e2
|
4
|
+
data.tar.gz: d426774057b79915cd53fe5a0784e17fb4790cf8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c15aa9b8c5a2136ad750256fa26eb5979cb732bce08eac311a4b1735490583701d6a2ba96fc8c9982e0205e5c5da8b47a3a01c729685c0791c1cddfcb7bc3e5e
|
7
|
+
data.tar.gz: 705df3971a06e55ff8e07ecbd3c93fd9570841b40dce661a5dfc5e3a74606514cb1aa7ffef34d75f49db45a42c5c8a9fbdfe6b064516e3bdfecffbf7d86028ee
|
data/lib/action.rb
ADDED
@@ -0,0 +1,126 @@
|
|
1
|
+
module CasualAPI
|
2
|
+
module Action
|
3
|
+
def self.extended obj
|
4
|
+
obj.instance_variable_set(:@redirect, nil)
|
5
|
+
obj.instance_variable_set(:@session, {})
|
6
|
+
obj.instance_variable_set(:@content_type, nil)
|
7
|
+
obj.instance_variable_set(:@status_code, 200)
|
8
|
+
obj.instance_variable_set(:@tempfiles, [])
|
9
|
+
end
|
10
|
+
|
11
|
+
def invalid_parameter *params
|
12
|
+
raise InvalidParameterError,
|
13
|
+
"Invalid parameter(s): #{params.map{|p|p.to_s}.join(',')}"
|
14
|
+
end
|
15
|
+
|
16
|
+
def file? file
|
17
|
+
Action.is_file? file
|
18
|
+
end
|
19
|
+
|
20
|
+
def tempfile file
|
21
|
+
Action.tempfile self, file
|
22
|
+
end
|
23
|
+
|
24
|
+
def redirect_to url
|
25
|
+
@redirect = url
|
26
|
+
end
|
27
|
+
|
28
|
+
def session_clear
|
29
|
+
session.clear
|
30
|
+
@session = nil
|
31
|
+
end
|
32
|
+
|
33
|
+
def session; @session; end
|
34
|
+
def session=(value); @session = value; end
|
35
|
+
def content_type; @content_type; end
|
36
|
+
def tempfiles; @tempfiles; end
|
37
|
+
def status_code; @status_code; end
|
38
|
+
def content_type=(type); @content_type = type; end
|
39
|
+
def status_code=(code); @status_code = code; end
|
40
|
+
def redirect; @redirect; end
|
41
|
+
|
42
|
+
|
43
|
+
def self.fire(action, params, session)
|
44
|
+
obj = Object
|
45
|
+
obj.extend Action
|
46
|
+
obj.extend BodyWriter
|
47
|
+
obj.content_type = action[:content_type] || :txt
|
48
|
+
obj.session = session
|
49
|
+
ps = action[:action].parameters.map{|_, name|
|
50
|
+
{name => params[name]}
|
51
|
+
}.inject({}, :merge)
|
52
|
+
execute(obj, ps, action)
|
53
|
+
obj.tempfiles.each{|f| f.close }
|
54
|
+
obj
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.is_file? param
|
58
|
+
param.is_a?(Hash) && param[:tempfile] && param[:tempfile].is_a?(Tempfile)
|
59
|
+
end
|
60
|
+
|
61
|
+
|
62
|
+
private
|
63
|
+
def self.execute(obj, ps, action)
|
64
|
+
ps = to_as_file(obj, ps, action)
|
65
|
+
ps = to_tempfile(obj, ps, action)
|
66
|
+
vs = action[:parameters].map{|k,v|ps[k]}
|
67
|
+
obj.instance_exec(*vs, &(action[:action]))
|
68
|
+
end
|
69
|
+
|
70
|
+
def self.to_as_file(obj, ps, action)
|
71
|
+
action[:parameters].select{|_,v|v[:as_file]}.each{|k,v|
|
72
|
+
if v[:is_array]
|
73
|
+
ps[k] = ps[k].map.with_index{|value,i|
|
74
|
+
create_temp_file(obj, i.to_s, value)
|
75
|
+
}
|
76
|
+
elsif v[:is_hash]
|
77
|
+
ps[k] = ps[k].map{|key, value|
|
78
|
+
{key => create_temp_file(obj, key.to_s, value)}
|
79
|
+
}.inject({},:merge)
|
80
|
+
else
|
81
|
+
ps[k] = create_temp_file(obj, k.to_s, ps[k])
|
82
|
+
end
|
83
|
+
}
|
84
|
+
ps
|
85
|
+
end
|
86
|
+
def self.create_temp_file(obj, name, value)
|
87
|
+
f = Tempfile.open(name)
|
88
|
+
f.write value
|
89
|
+
f.close
|
90
|
+
f.open
|
91
|
+
obj.tempfiles.push f
|
92
|
+
{tempfile: f}
|
93
|
+
end
|
94
|
+
|
95
|
+
def self.to_tempfile(obj, ps, action)
|
96
|
+
action[:parameters].select{|_,v|v[:tempfile]}.each{|k,v|
|
97
|
+
if v[:is_array]
|
98
|
+
ps[k] = ps[k].map{|value|
|
99
|
+
tempfile obj, value
|
100
|
+
}
|
101
|
+
elsif v[:is_hash]
|
102
|
+
ps[k] = ps[k].map{|key, value|
|
103
|
+
{ key => tempfile(obj, value) }
|
104
|
+
}.inject({},:merge)
|
105
|
+
else
|
106
|
+
ps[k] = tempfile obj, ps[k]
|
107
|
+
end
|
108
|
+
}
|
109
|
+
ps
|
110
|
+
end
|
111
|
+
|
112
|
+
def self.tempfile(obj,file)
|
113
|
+
if Action.is_file? file
|
114
|
+
file[:tempfile].path
|
115
|
+
else
|
116
|
+
f = Tempfile.open(SecureRandom.hex(4))
|
117
|
+
f.write file
|
118
|
+
f.flush
|
119
|
+
f.close
|
120
|
+
f.open
|
121
|
+
obj.tempfiles.push f
|
122
|
+
f.path
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
data/lib/annotation.rb
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
module CasualAPI
|
2
|
+
module Annotation
|
3
|
+
def is_file *files
|
4
|
+
@context_stack.last[:is_file] ||= []
|
5
|
+
@context_stack.last[:is_file].push(*files)
|
6
|
+
end
|
7
|
+
def as_file *files
|
8
|
+
@context_stack.last[:as_file] ||= []
|
9
|
+
@context_stack.last[:as_file].push(*files)
|
10
|
+
end
|
11
|
+
def tempfile *files
|
12
|
+
@context_stack.last[:tempfile] ||= []
|
13
|
+
@context_stack.last[:tempfile].push(*files)
|
14
|
+
end
|
15
|
+
def is_array *params
|
16
|
+
@context_stack.last[:is_array] ||= []
|
17
|
+
@context_stack.last[:is_array].push(*params)
|
18
|
+
end
|
19
|
+
def is_hash *params
|
20
|
+
@context_stack.last[:is_hash] ||= []
|
21
|
+
@context_stack.last[:is_hash].push(*params)
|
22
|
+
end
|
23
|
+
|
24
|
+
def description(param1, param2=nil)
|
25
|
+
@context_stack.last[:description] ||= {}
|
26
|
+
if param2
|
27
|
+
@context_stack.last[:description][:params] ||= {}
|
28
|
+
@context_stack.last[:description][:params][param1] = param2
|
29
|
+
else
|
30
|
+
@context_stack.last[:description][:path] = param1
|
31
|
+
end
|
32
|
+
end
|
33
|
+
def hide(value=true)
|
34
|
+
@context_stack.last[:hide] = value
|
35
|
+
end
|
36
|
+
|
37
|
+
def clear_annotaion
|
38
|
+
@context_stack.last.delete(:is_file)
|
39
|
+
@context_stack.last.delete(:as_file)
|
40
|
+
@context_stack.last.delete(:tempfile)
|
41
|
+
@context_stack.last.delete(:is_array)
|
42
|
+
@context_stack.last.delete(:is_hash)
|
43
|
+
@context_stack.last.delete(:description)
|
44
|
+
@context_stack.last.delete(:hide)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
data/lib/body_writer.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
|
2
|
+
module CasualAPI
|
3
|
+
module BodyWriter
|
4
|
+
def self.extended obj
|
5
|
+
obj.instance_variable_set(:@body, "")
|
6
|
+
end
|
7
|
+
def write str
|
8
|
+
@body << str.to_s
|
9
|
+
end
|
10
|
+
def print str
|
11
|
+
@body << str.to_s
|
12
|
+
end
|
13
|
+
def puts str
|
14
|
+
@body << str.to_s << "\n"
|
15
|
+
end
|
16
|
+
def printf *p
|
17
|
+
@body << sprintf(*p)
|
18
|
+
end
|
19
|
+
def command cmd
|
20
|
+
write `#{cmd.to_s}`
|
21
|
+
end
|
22
|
+
def body
|
23
|
+
@body
|
24
|
+
end
|
25
|
+
def body=(value)
|
26
|
+
@body = value
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/lib/casual.rb
CHANGED
@@ -1,52 +1,10 @@
|
|
1
1
|
require 'rack'
|
2
2
|
require 'tempfile'
|
3
3
|
require_relative './dsl.rb'
|
4
|
+
require_relative './child_process.rb'
|
5
|
+
require_relative './request_checker.rb'
|
4
6
|
|
5
7
|
module CasualAPI
|
6
|
-
class ChildProcess
|
7
|
-
def initialize(action, parameters, session)
|
8
|
-
@action = action
|
9
|
-
@params = parameters
|
10
|
-
@session = session
|
11
|
-
end
|
12
|
-
|
13
|
-
def execute
|
14
|
-
check_parameter
|
15
|
-
obj = Action.fire @action, @params, @session
|
16
|
-
{
|
17
|
-
redirect: obj.redirect,
|
18
|
-
session: obj.session,
|
19
|
-
status_code: obj.status_code,
|
20
|
-
content_type: obj.content_type,
|
21
|
-
body: obj.body,
|
22
|
-
}
|
23
|
-
end
|
24
|
-
|
25
|
-
private
|
26
|
-
def check_parameter
|
27
|
-
check_satisfy_required_parameters
|
28
|
-
check_upload_file
|
29
|
-
end
|
30
|
-
def check_satisfy_required_parameters
|
31
|
-
unless @action[:parameters].all?{|k,v|@params[k] || !v[:required]}
|
32
|
-
raise InvalidParameterError, "Invalid parameter(s)"
|
33
|
-
end
|
34
|
-
end
|
35
|
-
def check_upload_file
|
36
|
-
unless @action[:parameters].all?{|k,v|
|
37
|
-
next false if v[:is_file] ^Action.is_file?(Hash)
|
38
|
-
next false if v[:as_file] && Action.is_file?(Hash)
|
39
|
-
next false if v[:is_array] ^ @params[k].is_a?(Array)
|
40
|
-
next false if v[:is_hash] && !Action.is_file?(@params[k]) && !@params[k].is_a?(Hash)
|
41
|
-
next false if !v[:is_hash] && !Action.is_file?(@params[k]) && @params[k].is_a?(Hash)
|
42
|
-
true
|
43
|
-
}
|
44
|
-
raise InvalidParameterError, "Invalid parameter(s)"
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
|
50
8
|
# RackApp
|
51
9
|
class Casual
|
52
10
|
def initialize(prefix, file, mode)
|
@@ -88,14 +46,13 @@ module CasualAPI
|
|
88
46
|
},
|
89
47
|
[ex.message]]
|
90
48
|
rescue => ex
|
91
|
-
[500, {
|
92
|
-
|
93
|
-
|
49
|
+
[500, {'Access-Control-Allow-Origin' => '*'},
|
50
|
+
["Server Error\n"] + (@mode == "development" ? [ex.message] : [])
|
51
|
+
]
|
94
52
|
end
|
95
53
|
else
|
96
|
-
[404, {
|
97
|
-
|
98
|
-
}, []]
|
54
|
+
[404, {'Access-Control-Allow-Origin' => '*'},
|
55
|
+
["API Not Found or Parameter(s) Not Enough"]]
|
99
56
|
end
|
100
57
|
end
|
101
58
|
|
@@ -118,9 +75,13 @@ module CasualAPI
|
|
118
75
|
path = request_path
|
119
76
|
_method = request_method
|
120
77
|
actions.detect{|act|
|
121
|
-
act[:method] == _method
|
78
|
+
cond = act[:method] == _method
|
79
|
+
cond = cond && make_path(act) == path
|
80
|
+
cond = cond && RequestChecker.check(act, parameters)
|
81
|
+
cond
|
122
82
|
}
|
123
83
|
end
|
84
|
+
|
124
85
|
def make_path action
|
125
86
|
@prefix + (action[:domain] + action[:names]).compact.map{|p|p.to_s}.join('/')
|
126
87
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require_relative './request_checker.rb'
|
2
|
+
|
3
|
+
module CasualAPI
|
4
|
+
class ChildProcess
|
5
|
+
def initialize(action, parameters, session)
|
6
|
+
@action = action
|
7
|
+
@params = parameters
|
8
|
+
@session = session
|
9
|
+
end
|
10
|
+
|
11
|
+
def execute
|
12
|
+
obj = Action.fire @action, @params, @session
|
13
|
+
{
|
14
|
+
redirect: obj.redirect,
|
15
|
+
session: obj.session,
|
16
|
+
status_code: obj.status_code,
|
17
|
+
content_type: obj.content_type,
|
18
|
+
body: obj.body,
|
19
|
+
}
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/dsl.rb
CHANGED
@@ -1,234 +1,14 @@
|
|
1
1
|
require 'pp'
|
2
2
|
require 'securerandom'
|
3
3
|
require 'tempfile'
|
4
|
+
require_relative './errors.rb'
|
5
|
+
require_relative './body_writer.rb'
|
6
|
+
require_relative './action.rb'
|
7
|
+
require_relative './annotation.rb'
|
8
|
+
require_relative './ext_expression.rb'
|
9
|
+
require_relative './syntax_sugar.rb'
|
4
10
|
|
5
11
|
module CasualAPI
|
6
|
-
module BodyWriter
|
7
|
-
def self.extended obj
|
8
|
-
obj.instance_variable_set(:@body, "")
|
9
|
-
end
|
10
|
-
def write str
|
11
|
-
@body << str.to_s
|
12
|
-
end
|
13
|
-
def print str
|
14
|
-
@body << str.to_s
|
15
|
-
end
|
16
|
-
def puts str
|
17
|
-
@body << str.to_s << "\n"
|
18
|
-
end
|
19
|
-
def printf *p
|
20
|
-
@body << sprintf(*p)
|
21
|
-
end
|
22
|
-
def command cmd
|
23
|
-
write `#{cmd.to_s}`
|
24
|
-
end
|
25
|
-
def body
|
26
|
-
@body
|
27
|
-
end
|
28
|
-
def body=(value)
|
29
|
-
@body = value
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
class CommandError < StandardError
|
34
|
-
def content_type; :txt; end
|
35
|
-
def status_code; 400; end
|
36
|
-
end
|
37
|
-
class InvalidParameterError < CommandError
|
38
|
-
end
|
39
|
-
|
40
|
-
module Action
|
41
|
-
def self.extended obj
|
42
|
-
obj.instance_variable_set(:@redirect, nil)
|
43
|
-
obj.instance_variable_set(:@session, {})
|
44
|
-
obj.instance_variable_set(:@content_type, nil)
|
45
|
-
obj.instance_variable_set(:@status_code, 200)
|
46
|
-
obj.instance_variable_set(:@tempfiles, [])
|
47
|
-
end
|
48
|
-
|
49
|
-
def invalid_parameter *params
|
50
|
-
raise InvalidParameterError, "Invalid parameter(s): #{params.map{|p|p.to_s}.join(',')}"
|
51
|
-
end
|
52
|
-
|
53
|
-
def file? file
|
54
|
-
Action.is_file? file
|
55
|
-
end
|
56
|
-
|
57
|
-
def tempfile file
|
58
|
-
Action.tempfile self, file
|
59
|
-
end
|
60
|
-
|
61
|
-
def redirect_to url
|
62
|
-
@redirect = url
|
63
|
-
end
|
64
|
-
|
65
|
-
def session_clear
|
66
|
-
session.clear
|
67
|
-
@session = nil
|
68
|
-
end
|
69
|
-
|
70
|
-
def session; @session; end
|
71
|
-
def session=(value); @session = value; end
|
72
|
-
def content_type; @content_type; end
|
73
|
-
def tempfiles; @tempfiles; end
|
74
|
-
def status_code; @status_code; end
|
75
|
-
def content_type=(type); @content_type = type; end
|
76
|
-
def status_code=(code); @status_code = code; end
|
77
|
-
def redirect; @redirect; end
|
78
|
-
|
79
|
-
|
80
|
-
def self.fire(action, params, session)
|
81
|
-
obj = Object
|
82
|
-
obj.extend Action
|
83
|
-
obj.extend BodyWriter
|
84
|
-
obj.content_type = action[:content_type] || :txt
|
85
|
-
obj.session = session
|
86
|
-
ps = action[:action].parameters.map{|_, name|
|
87
|
-
{name => params[name]}
|
88
|
-
}.inject({}, :merge)
|
89
|
-
execute(obj, ps, action)
|
90
|
-
obj.tempfiles.each{|f| f.close }
|
91
|
-
obj
|
92
|
-
end
|
93
|
-
|
94
|
-
def self.is_file? param
|
95
|
-
param.is_a?(Hash) && param[:tempfile] && param[:tempfile].is_a?(Tempfile)
|
96
|
-
end
|
97
|
-
|
98
|
-
|
99
|
-
private
|
100
|
-
def self.execute(obj, ps, action)
|
101
|
-
ps = to_as_file(obj, ps, action)
|
102
|
-
ps = to_tempfile(obj, ps, action)
|
103
|
-
vs = action[:parameters].map{|k,v|ps[k]}
|
104
|
-
obj.instance_exec(*vs, &(action[:action]))
|
105
|
-
end
|
106
|
-
|
107
|
-
def self.to_as_file(obj, ps, action)
|
108
|
-
action[:parameters].select{|_,v|v[:as_file]}.each{|k,_|
|
109
|
-
f = Tempfile.open(k.to_s)
|
110
|
-
f.write ps[k]
|
111
|
-
f.close
|
112
|
-
f.open
|
113
|
-
obj.tempfiles.push f
|
114
|
-
ps[k] = {tempfile: f}
|
115
|
-
}
|
116
|
-
ps
|
117
|
-
end
|
118
|
-
def self.to_tempfile(obj, ps, action)
|
119
|
-
action[:parameters].select{|_,v|v[:tempfile]}.each{|k,_|
|
120
|
-
ps[k] = tempfile obj, ps[k]
|
121
|
-
}
|
122
|
-
ps
|
123
|
-
end
|
124
|
-
def self.tempfile(obj,file)
|
125
|
-
if Action.is_file? file
|
126
|
-
file[:tempfile].path
|
127
|
-
else
|
128
|
-
f = Tempfile.open(SecureRandom.hex(4))
|
129
|
-
f.write file
|
130
|
-
f.flush
|
131
|
-
f.close
|
132
|
-
f.open
|
133
|
-
obj.tempfiles.push f
|
134
|
-
f.path
|
135
|
-
end
|
136
|
-
end
|
137
|
-
end
|
138
|
-
|
139
|
-
module Annotation
|
140
|
-
def is_file *files
|
141
|
-
@context_stack.last[:is_file] ||= []
|
142
|
-
@context_stack.last[:is_file].push(*files)
|
143
|
-
end
|
144
|
-
def as_file *files
|
145
|
-
@context_stack.last[:as_file] ||= []
|
146
|
-
@context_stack.last[:as_file].push(*files)
|
147
|
-
end
|
148
|
-
def tempfile *files
|
149
|
-
@context_stack.last[:tempfile] ||= []
|
150
|
-
@context_stack.last[:tempfile].push(*files)
|
151
|
-
end
|
152
|
-
def is_array *params
|
153
|
-
@context_stack.last[:is_array] ||= []
|
154
|
-
@context_stack.last[:is_array].push(*params)
|
155
|
-
end
|
156
|
-
def is_hash *params
|
157
|
-
@context_stack.last[:is_hash] ||= []
|
158
|
-
@context_stack.last[:is_hash].push(*params)
|
159
|
-
end
|
160
|
-
|
161
|
-
def description(param1, param2=nil)
|
162
|
-
@context_stack.last[:description] ||= {}
|
163
|
-
if param2
|
164
|
-
@context_stack.last[:description][:params] ||= {}
|
165
|
-
@context_stack.last[:description][:params][param1] = param2
|
166
|
-
else
|
167
|
-
@context_stack.last[:description][:path] = param1
|
168
|
-
end
|
169
|
-
end
|
170
|
-
def clear_annotaion
|
171
|
-
@context_stack.last.delete(:is_file)
|
172
|
-
@context_stack.last.delete(:as_file)
|
173
|
-
@context_stack.last.delete(:tempfile)
|
174
|
-
@context_stack.last.delete(:is_array)
|
175
|
-
@context_stack.last.delete(:is_hash)
|
176
|
-
@context_stack.last.delete(:description)
|
177
|
-
end
|
178
|
-
end
|
179
|
-
|
180
|
-
module ExtExpression
|
181
|
-
def content_type type
|
182
|
-
@context_stack.last[:content_type] = type
|
183
|
-
end
|
184
|
-
end
|
185
|
-
|
186
|
-
module SyntaxSugar
|
187
|
-
def get(*names, &block); path(:get, *names, &block); end
|
188
|
-
def post(*names, &block); path(:post, *names, &block); end
|
189
|
-
|
190
|
-
def command(*names, cmd)
|
191
|
-
eval(replace :get, names, "write `#{cmd}`")
|
192
|
-
end
|
193
|
-
|
194
|
-
def text(*names, text)
|
195
|
-
eval(replace :get, names, "write \"#{text}\"")
|
196
|
-
end
|
197
|
-
|
198
|
-
def get_command(*names, cmd); command(*names, cmd); end
|
199
|
-
def post_command(*names, cmd)
|
200
|
-
eval(replace :post, names, "write `#{cmd}`")
|
201
|
-
end
|
202
|
-
|
203
|
-
def get_text(*names, text); text(*names, text); end
|
204
|
-
def post_text(*names, text)
|
205
|
-
eval(replace :post, names, "write \"#{text}\"")
|
206
|
-
end
|
207
|
-
|
208
|
-
private
|
209
|
-
def replace meth, names, cmd
|
210
|
-
ps = cmd.scan(/\$\{(?<p>[^:\}]*)\}/).flatten
|
211
|
-
fs = cmd.scan(/\$\{file:(?<p>[^:\}]*)\}/).flatten
|
212
|
-
c = ps.inject(cmd){|acc,c|
|
213
|
-
acc.gsub /\$\{#{c}\}/, "\#{#{c}}"
|
214
|
-
}
|
215
|
-
c = fs.inject(c){|acc,c|
|
216
|
-
acc.gsub /\$\{file:#{c}\}/, "\#{#{c}}"
|
217
|
-
}
|
218
|
-
is_file_annotation = "is_file " + fs.map{|f|":#{f}"}.join(',')
|
219
|
-
tempfile_annotation = "tempfile " + fs.map{|f|":#{f}"}.join(',')
|
220
|
-
args = (ps + fs).join(',')
|
221
|
-
<<PROC
|
222
|
-
#{is_file_annotation}
|
223
|
-
#{tempfile_annotation}
|
224
|
-
#{meth.to_s}(#{names.map{|n|":#{n.to_s}"}.join(',')}) do | #{args} |
|
225
|
-
#{c}
|
226
|
-
end
|
227
|
-
PROC
|
228
|
-
end
|
229
|
-
end
|
230
|
-
|
231
|
-
|
232
12
|
module DSL
|
233
13
|
def self.extended obj
|
234
14
|
# add stacks and a context to an extended object.
|
@@ -244,10 +24,20 @@ PROC
|
|
244
24
|
@action_stack
|
245
25
|
end
|
246
26
|
|
27
|
+
def echo
|
28
|
+
p "W"
|
29
|
+
end
|
30
|
+
|
31
|
+
def import(path)
|
32
|
+
if File.exist?(path)
|
33
|
+
open(path){|f| eval(f.read, binding) }
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
247
37
|
def domain(*path , &block)
|
248
38
|
# annotations don't effect over domain
|
249
39
|
clear_annotaion
|
250
|
-
@domain_stack.push
|
40
|
+
@domain_stack.push(*path)
|
251
41
|
@context_stack.push(@context_stack.last.clone)
|
252
42
|
block.call
|
253
43
|
@context_stack.pop
|
@@ -287,13 +77,15 @@ PROC
|
|
287
77
|
}
|
288
78
|
}
|
289
79
|
}.inject({}, :merge)
|
290
|
-
{
|
80
|
+
{
|
81
|
+
content_type: hs[:content_type],
|
291
82
|
method: hs[:method],
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
83
|
+
names: hs[:names],
|
84
|
+
description: description,
|
85
|
+
domain: hs[:domain],
|
86
|
+
action: hs[:action],
|
87
|
+
parameters: parameters,
|
88
|
+
hide: hs[:hide],
|
297
89
|
}
|
298
90
|
end
|
299
91
|
end
|
data/lib/errors.rb
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
module CasualAPI
|
2
|
+
class RequestChecker
|
3
|
+
def self.check(action, params)
|
4
|
+
@action = action
|
5
|
+
@params = params
|
6
|
+
check_satisfy_required_parameters && check_upload_file
|
7
|
+
end
|
8
|
+
private
|
9
|
+
def self.check_satisfy_required_parameters
|
10
|
+
@action[:parameters].all?{|k,v|@params[k] || !v[:required]}
|
11
|
+
end
|
12
|
+
def self.check_upload_file
|
13
|
+
@action[:parameters].all?{|k,v|
|
14
|
+
next false unless check_is_file(v, @params[k])
|
15
|
+
next false unless check_as_file(v, @params[k])
|
16
|
+
next false unless check_is_array(v, @params[k])
|
17
|
+
next false unless check_is_hash(v, @params[k])
|
18
|
+
true
|
19
|
+
}
|
20
|
+
end
|
21
|
+
def self.check_is_hash(attr, value)
|
22
|
+
attr[:is_hash] ^ !(value.is_a?(Hash) && !Action.is_file?(value))
|
23
|
+
end
|
24
|
+
def self.check_is_array(attr, value)
|
25
|
+
attr[:is_array] ^ !value.is_a?(Array)
|
26
|
+
end
|
27
|
+
def self.check_as_file(attr, value)
|
28
|
+
if attr[:as_file]
|
29
|
+
if attr[:is_array]
|
30
|
+
return value.is_a?(Array) && value.all?{|v| !Action.is_file?(v) }
|
31
|
+
elsif attr[:is_hash]
|
32
|
+
return value.is_?(Hash) && value.all?{|_,v| !Action.is_file?(v) }
|
33
|
+
else
|
34
|
+
return !Action.is_file?(value)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
return true
|
38
|
+
end
|
39
|
+
def self.check_is_file(attr, value)
|
40
|
+
if attr[:is_file]
|
41
|
+
if attr[:is_array]
|
42
|
+
return value.is_a?(Array) && value.all?{|v| Action.is_file?(v) }
|
43
|
+
elsif attr[:is_hash]
|
44
|
+
return value.is_?(Hash) && value.all?{|_,v| Action.is_file?(v) }
|
45
|
+
else
|
46
|
+
return Action.is_file?(value)
|
47
|
+
end
|
48
|
+
else
|
49
|
+
if attr[:is_array]
|
50
|
+
return value.is_a?(Array) && value.all?{|v| !Action.is_file?(v) }
|
51
|
+
elsif attr[:is_hash]
|
52
|
+
return value.is_?(Hash) && value.all?{|_,v| !Action.is_file?(v) }
|
53
|
+
else
|
54
|
+
return !Action.is_file?(value)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
return false
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
data/lib/syntax_sugar.rb
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
module CasualAPI
|
2
|
+
module SyntaxSugar
|
3
|
+
def get(*names, &block); path(:get, *names, &block); end
|
4
|
+
def post(*names, &block); path(:post, *names, &block); end
|
5
|
+
|
6
|
+
def command(*names, cmd)
|
7
|
+
eval(replace :get, names, "write `#{cmd}`")
|
8
|
+
end
|
9
|
+
|
10
|
+
def text(*names, text)
|
11
|
+
eval(replace :get, names, "write \"#{text}\"")
|
12
|
+
end
|
13
|
+
|
14
|
+
def get_command(*names, cmd); command(*names, cmd); end
|
15
|
+
def post_command(*names, cmd)
|
16
|
+
eval(replace :post, names, "write `#{cmd}`")
|
17
|
+
end
|
18
|
+
|
19
|
+
def get_text(*names, text); text(*names, text); end
|
20
|
+
def post_text(*names, text)
|
21
|
+
eval(replace :post, names, "write \"#{text}\"")
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
def replace meth, names, cmd
|
26
|
+
ps = cmd.scan(/\$\{(?<p>[^:\}]*)\}/).flatten
|
27
|
+
fs = cmd.scan(/\$\{file:(?<p>[^:\}]*)\}/).flatten
|
28
|
+
cmd = ps.inject(cmd){|acc,c|
|
29
|
+
acc.gsub(/\$\{#{c}\}/, "\#{#{c}}")
|
30
|
+
}
|
31
|
+
cmd = fs.inject(cmd){|acc,c|
|
32
|
+
acc.gsub(/\$\{file:#{c}\}/, "\#{#{c}}")
|
33
|
+
}
|
34
|
+
is_file_annotation = "is_file " + fs.map{|f|":#{f}"}.join(',')
|
35
|
+
tempfile_annotation = "tempfile " + fs.map{|f|":#{f}"}.join(',')
|
36
|
+
args = (ps + fs).join(',')
|
37
|
+
<<PROC
|
38
|
+
#{is_file_annotation}
|
39
|
+
#{tempfile_annotation}
|
40
|
+
#{meth.to_s}(#{names.map{|n|":#{n.to_s}"}.join(',')}) do | #{args} |
|
41
|
+
#{cmd}
|
42
|
+
end
|
43
|
+
PROC
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: casual-api
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.0.
|
4
|
+
version: 3.0.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Takeshi Kojima
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-09-
|
11
|
+
date: 2014-09-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rack
|
@@ -38,10 +38,18 @@ extensions: []
|
|
38
38
|
extra_rdoc_files: []
|
39
39
|
files:
|
40
40
|
- bin/casual-api
|
41
|
+
- lib/action.rb
|
42
|
+
- lib/annotation.rb
|
43
|
+
- lib/body_writer.rb
|
41
44
|
- lib/casual-api.rb
|
42
45
|
- lib/casual.rb
|
46
|
+
- lib/child_process.rb
|
43
47
|
- lib/config.ru
|
44
48
|
- lib/dsl.rb
|
49
|
+
- lib/errors.rb
|
50
|
+
- lib/ext_expression.rb
|
51
|
+
- lib/request_checker.rb
|
52
|
+
- lib/syntax_sugar.rb
|
45
53
|
homepage: https://github.com/tatkeshi/casual-api
|
46
54
|
licenses:
|
47
55
|
- MIT
|