webservice 0.3.1 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/webservice.rb +1 -0
- data/lib/webservice/base.rb +167 -16
- data/lib/webservice/version.rb +2 -2
- data/test/service/app.rb +8 -0
- data/test/test_app.rb +30 -2
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b43248423b9aeba87a88f63b6a708167bbf7d723
|
4
|
+
data.tar.gz: 35b9cd86f34c708a4d55f7f61a08a878f4e19d12
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: def6d86899d29ca10acb0c70af15de8887005fc47dc9f1d5586103eb98033d7e68d5c44744c51b30493cbcef344a565f9dbcc21c6681aa55257e42c772c0f307
|
7
|
+
data.tar.gz: 2417ece5303df96025515574a343e2b21eaa1e08015ff7cfe11822a9d9d757c918a798e149d1d03f24b74a7574e0ef6e4625778b6b63b6b42fa0f403c31adb19
|
data/lib/webservice.rb
CHANGED
data/lib/webservice/base.rb
CHANGED
@@ -3,21 +3,85 @@
|
|
3
3
|
|
4
4
|
module Webservice
|
5
5
|
|
6
|
-
class Base
|
7
6
|
|
8
|
-
|
7
|
+
module Helpers
|
8
|
+
## add some more helpers
|
9
|
+
## "inspired" by sinatra (mostly) - for staying compatible
|
10
|
+
## see https://github.com/sinatra/sinatra/blob/master/lib/sinatra/base.rb
|
11
|
+
|
12
|
+
## todo -- add redirect/redirect_to
|
13
|
+
## add status -- why? why not??
|
14
|
+
|
15
|
+
# Halt processing and return the error status provided.
|
16
|
+
def error(code, body=nil)
|
17
|
+
code = 500
|
18
|
+
body = code.to_str if code.respond_to? :to_str
|
19
|
+
|
20
|
+
response.body = body unless body.nil?
|
21
|
+
halt code
|
22
|
+
end
|
23
|
+
|
24
|
+
# Halt processing and return a 404 Not Found.
|
25
|
+
def not_found(body=nil)
|
26
|
+
error 404, body
|
27
|
+
end
|
28
|
+
|
29
|
+
# Set multiple response headers with Hash.
|
30
|
+
def headers(hash=nil)
|
31
|
+
response.headers.merge! hash if hash
|
32
|
+
response.headers
|
33
|
+
end
|
34
|
+
|
35
|
+
|
36
|
+
|
37
|
+
## (simple) content_type helper - all "hard-coded" for now; always uses utf-8 too
|
38
|
+
def content_type( type=nil )
|
39
|
+
return response['Content-Type'] unless type
|
40
|
+
|
41
|
+
if type.to_sym == :json
|
42
|
+
response['Content-Type'] = 'application/json; charset=utf-8'
|
43
|
+
elsif type.to_sym == :js || type.to_sym == :javascript
|
44
|
+
response['Content-Type'] = 'application/javascript; charset=utf-8'
|
45
|
+
## use 'text/javascript; charset=utf-8' -- why? why not??
|
46
|
+
## note: ietf recommends application/javascript
|
47
|
+
elsif type.to_sym == :csv || type.to_sym == :text || type.to_sym == :txt
|
48
|
+
response['Content-Type'] = 'text/plain; charset=utf-8'
|
49
|
+
elsif type.to_sym == :html || type.to_sym == :htm
|
50
|
+
response['Content-Type'] = 'text/html; charset=utf-8'
|
51
|
+
else
|
52
|
+
### unknown type; do nothing - sorry; issue warning - why? why not??
|
53
|
+
end
|
54
|
+
end ## method content_type
|
55
|
+
end ## module Helpers
|
9
56
|
|
10
57
|
|
58
|
+
class Base
|
59
|
+
include Helpers
|
60
|
+
|
11
61
|
class << self
|
12
62
|
|
13
63
|
## todo/check: all verbs needed! (supported) - why, why not??
|
14
|
-
|
15
|
-
define_method( method.downcase ) do |pattern, &block|
|
16
|
-
puts "[debug] Webservice::Base.#{method.downcase} - add route #{method} '#{pattern}' to #<#{self.name}:#{self.object_id}> : #{self.class.name}"
|
64
|
+
## e.g. add LINK, UNLINK ??
|
17
65
|
|
18
|
-
|
19
|
-
|
20
|
-
|
66
|
+
# Note: for now defining a `GET` handler also automatically defines
|
67
|
+
# a `HEAD` handler (follows sinatra convention)
|
68
|
+
def get( pattern, &block)
|
69
|
+
route( 'GET', pattern, &block )
|
70
|
+
route( 'HEAD', pattern, &block )
|
71
|
+
end
|
72
|
+
|
73
|
+
def post( pattern, &block) route( 'POST', pattern, &block ); end
|
74
|
+
def patch( pattern, &block) route( 'PATCH', pattern, &block ); end
|
75
|
+
def put( pattern, &block) route( 'PUT', pattern, &block ); end
|
76
|
+
def delete( pattern, &block) route( 'DELETE', pattern, &block ); end
|
77
|
+
def head( pattern, &block) route( 'HEAD', pattern, &block ); end
|
78
|
+
def options( pattern, &block) route( 'OPTIONS', pattern, &block ); end
|
79
|
+
|
80
|
+
def route( method, pattern, &block )
|
81
|
+
puts "[debug] Webservice::Base.#{method.downcase} - add route #{method} '#{pattern}' to #<#{self.name}:#{self.object_id}> : #{self.class.name}"
|
82
|
+
|
83
|
+
## note: for now use the sintatra-style patterns (with mustermann)
|
84
|
+
routes[method] << [Mustermann::Sinatra.new(pattern), block]
|
21
85
|
end
|
22
86
|
|
23
87
|
|
@@ -26,6 +90,17 @@ class Base
|
|
26
90
|
end
|
27
91
|
|
28
92
|
|
93
|
+
def environment
|
94
|
+
## include APP_ENV why? why not?
|
95
|
+
## todo -- cache value? why why not? (see/follow sinatara set machinery ??)
|
96
|
+
(ENV['RACK_ENV'] || :development).to_sym
|
97
|
+
end
|
98
|
+
|
99
|
+
def development?() environment == :development; end
|
100
|
+
def production?() environment == :production; end
|
101
|
+
def test?() environment == :test; end
|
102
|
+
|
103
|
+
|
29
104
|
## convenience method
|
30
105
|
def run!
|
31
106
|
puts "[debug] Webservice::Base.run! - self = #<#{self.name}:#{self.object_id}> : #{self.class.name}" # note: assumes self is class
|
@@ -39,7 +114,6 @@ class Base
|
|
39
114
|
end ## class << self
|
40
115
|
|
41
116
|
|
42
|
-
|
43
117
|
attr_reader :request
|
44
118
|
attr_reader :response
|
45
119
|
attr_reader :params
|
@@ -67,7 +141,6 @@ class Base
|
|
67
141
|
throw :halt, response
|
68
142
|
end
|
69
143
|
|
70
|
-
|
71
144
|
private
|
72
145
|
|
73
146
|
def route_eval
|
@@ -78,6 +151,7 @@ private
|
|
78
151
|
if url_params ## note: params returns nil if no match
|
79
152
|
## puts " BINGO! url_params: #{url_params.inspect}"
|
80
153
|
if !url_params.empty? ## url_params hash NOT empty (e.g. {}) merge with req params
|
154
|
+
## todo/fix: check merge order - params overwrites url_params - why? why not??
|
81
155
|
@params = url_params.merge( params )
|
82
156
|
end
|
83
157
|
handle_response( instance_eval( &block ))
|
@@ -89,20 +163,97 @@ private
|
|
89
163
|
end
|
90
164
|
|
91
165
|
|
166
|
+
|
167
|
+
|
92
168
|
def handle_response( obj )
|
93
|
-
puts "[Webservice::Base#handle_response] - obj : #{obj.class.name}"
|
169
|
+
puts "[Webservice::Base#handle_response (#{request.path_info}) params: #{params.inspect}] - obj : #{obj.class.name}"
|
170
|
+
pp obj
|
94
171
|
|
95
|
-
|
172
|
+
## "magic" param format; default to json
|
173
|
+
format = params['format'] || 'json'
|
96
174
|
|
97
|
-
if
|
98
|
-
|
175
|
+
if format == 'csv' || format == 'txt'
|
176
|
+
text = generate_csv( obj )
|
177
|
+
content_type :text
|
178
|
+
response.write text
|
179
|
+
elsif format == 'html' || format == 'htm'
|
180
|
+
text = generate_html_table( obj )
|
181
|
+
content_type :html
|
182
|
+
response.write text
|
99
183
|
else
|
100
|
-
|
101
|
-
|
184
|
+
json = generate_json( obj )
|
185
|
+
|
186
|
+
callback = params.delete('callback')
|
187
|
+
|
188
|
+
if callback
|
189
|
+
content_type :js
|
190
|
+
response.write "#{callback}(#{json})"
|
191
|
+
else
|
192
|
+
content_type :json
|
193
|
+
response.write json
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end # method handle_response
|
197
|
+
|
198
|
+
|
199
|
+
def generate_csv( recs )
|
200
|
+
## note: for now assumes (only works with) array of hash records e.g.:
|
201
|
+
## [
|
202
|
+
## { key: 'at', name: 'Austria', ...},
|
203
|
+
## { key: 'mx', name: 'Mexico', ...},
|
204
|
+
## ...
|
205
|
+
## ]
|
206
|
+
|
207
|
+
## :col_sep => "\t"
|
208
|
+
## :col_sep => ";"
|
209
|
+
|
210
|
+
## todo: use rec.key for headers/first row
|
211
|
+
|
212
|
+
## pp recs
|
213
|
+
|
214
|
+
CSV.generate do |csv|
|
215
|
+
recs.each do |rec|
|
216
|
+
csv << rec.values
|
217
|
+
end
|
102
218
|
end
|
103
219
|
end
|
104
220
|
|
105
221
|
|
222
|
+
def generate_html_table( recs )
|
223
|
+
## note: for now assumes (only works with) array of hash records e.g.:
|
224
|
+
## [
|
225
|
+
## { key: 'at', name: 'Austria', ...},
|
226
|
+
## { key: 'mx', name: 'Mexico', ...},
|
227
|
+
## ...
|
228
|
+
## ]
|
229
|
+
|
230
|
+
## pp recs
|
231
|
+
|
232
|
+
buf = ""
|
233
|
+
buf << "<table>\n"
|
234
|
+
recs.each do |rec|
|
235
|
+
buf << " <tr>"
|
236
|
+
rec.values.each do |value|
|
237
|
+
buf << "<td>#{value}</td>"
|
238
|
+
end
|
239
|
+
buf << "</tr>\n"
|
240
|
+
end
|
241
|
+
buf << "</table>\n"
|
242
|
+
buf
|
243
|
+
end
|
244
|
+
|
245
|
+
|
246
|
+
def generate_json( obj )
|
247
|
+
if obj.respond_to? :as_json_v2 ## try (our own) serializer first
|
248
|
+
obj.as_json_v2
|
249
|
+
elsif obj.respond_to? :as_json ## try (activerecord) serializer
|
250
|
+
obj.as_json_v2
|
251
|
+
else
|
252
|
+
## just try/use to_json
|
253
|
+
obj.to_json
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
106
257
|
end # class Base
|
107
258
|
|
108
259
|
end # module Webservice
|
data/lib/webservice/version.rb
CHANGED
data/test/service/app.rb
CHANGED
@@ -22,6 +22,14 @@ get '/halt_error' do
|
|
22
22
|
end
|
23
23
|
|
24
24
|
|
25
|
+
get '/countries(.:format)?' do
|
26
|
+
## array of hash records
|
27
|
+
[ { key: 'at', name: 'Austria' },
|
28
|
+
{ key: 'mx', name: 'Mexico' } ]
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
|
25
33
|
get '/:message/:name' do
|
26
34
|
message = params['message']
|
27
35
|
name = params['name']
|
data/test/test_app.rb
CHANGED
@@ -57,9 +57,9 @@ class TestApp < MiniTest::Test
|
|
57
57
|
assert last_response.ok?
|
58
58
|
assert_equal %q{"key format"}, last_response.body
|
59
59
|
|
60
|
-
get '/ottakringer.
|
60
|
+
get '/ottakringer.xxx'
|
61
61
|
assert last_response.ok?
|
62
|
-
assert_equal %q{"ottakringer
|
62
|
+
assert_equal %q{"ottakringer xxx"}, last_response.body
|
63
63
|
|
64
64
|
get '/ottakringer'
|
65
65
|
assert last_response.ok?
|
@@ -67,6 +67,34 @@ class TestApp < MiniTest::Test
|
|
67
67
|
end
|
68
68
|
|
69
69
|
|
70
|
+
def test_countries
|
71
|
+
|
72
|
+
get '/countries.csv'
|
73
|
+
assert last_response.ok?
|
74
|
+
assert_equal <<CSV, last_response.body
|
75
|
+
at,Austria
|
76
|
+
mx,Mexico
|
77
|
+
CSV
|
78
|
+
|
79
|
+
get '/countries.html'
|
80
|
+
assert last_response.ok?
|
81
|
+
assert_equal <<HTML, last_response.body
|
82
|
+
<table>
|
83
|
+
<tr><td>at</td><td>Austria</td></tr>
|
84
|
+
<tr><td>mx</td><td>Mexico</td></tr>
|
85
|
+
</table>
|
86
|
+
HTML
|
87
|
+
|
88
|
+
get '/countries.json'
|
89
|
+
assert last_response.ok?
|
90
|
+
assert_equal %q<[{"key":"at","name":"Austria"},{"key":"mx","name":"Mexico"}]>, last_response.body
|
91
|
+
|
92
|
+
get '/countries'
|
93
|
+
assert last_response.ok?
|
94
|
+
assert_equal %q<[{"key":"at","name":"Austria"},{"key":"mx","name":"Mexico"}]>, last_response.body
|
95
|
+
end # method test_countries
|
96
|
+
|
97
|
+
|
70
98
|
def test_halt
|
71
99
|
## get '/halt/404'
|
72
100
|
get '/halt/404'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: webservice
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Gerald Bauer
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-08-
|
11
|
+
date: 2017-08-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: logutils
|