webservice 0.4.0 → 0.5.0
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/README.md +142 -2
- data/lib/webservice.rb +3 -0
- data/lib/webservice/base.rb +164 -56
- data/lib/webservice/version.rb +10 -4
- data/test/service/app.rb +0 -2
- data/test/test_app.rb +30 -17
- 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: fca9552fa4818068271c81022e7ab9a4ec277d30
|
4
|
+
data.tar.gz: 23e2d0051213a5834cafff2762df4324c6907935
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6b53f3b4ea61aed918b16b5b73ad3be4e162131599d6cb1222607097d5cff3f8757222458373a2a3e30dbea91d47f32c092f6557e274bebcbdaf0ae8c121f992
|
7
|
+
data.tar.gz: b32faf56e9286e1b4283d900f59f7b1af4bfd89b70366e849200c014540c8e80c45a9110a1d51239372eb414aec5f5f308149960786d6d32f254a942fd404a85
|
data/README.md
CHANGED
@@ -10,11 +10,151 @@ webservice gem - yet another HTTP JSON API (web service) builder
|
|
10
10
|
|
11
11
|
## Usage
|
12
12
|
|
13
|
-
|
13
|
+
[Dynamic Example](#dynamic-example) •
|
14
|
+
[Classic Example](#classic-example) •
|
15
|
+
[Rackup Example](#rackup-example)
|
16
|
+
|
17
|
+
|
18
|
+
### Dynamic Example
|
19
|
+
|
20
|
+
You can load services at-runtime from files using `Webservice.load_file`.
|
21
|
+
Example:
|
22
|
+
|
23
|
+
```ruby
|
24
|
+
# service.rb
|
25
|
+
|
26
|
+
get '/' do
|
27
|
+
'Hello, world!'
|
28
|
+
end
|
29
|
+
```
|
30
|
+
|
31
|
+
and
|
32
|
+
|
33
|
+
```ruby
|
34
|
+
# server.rb
|
35
|
+
|
36
|
+
require 'webservice'
|
37
|
+
|
38
|
+
App = Webservice.load_file( './service.rb' )
|
39
|
+
App.run!
|
40
|
+
```
|
41
|
+
|
42
|
+
and to run type
|
43
|
+
|
44
|
+
```
|
45
|
+
$ ruby ./server.rb
|
46
|
+
```
|
47
|
+
|
48
|
+
|
49
|
+
### Classic Example
|
50
|
+
|
51
|
+
```ruby
|
52
|
+
# server.rb
|
53
|
+
|
54
|
+
require 'webservice'
|
55
|
+
|
56
|
+
class App < Webservice::Base
|
57
|
+
get '/' do
|
58
|
+
'Hello, world!'
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
App.run!
|
63
|
+
```
|
64
|
+
and to run type
|
65
|
+
|
66
|
+
```
|
67
|
+
$ ruby ./server.rb
|
68
|
+
```
|
69
|
+
|
70
|
+
|
71
|
+
### Rackup Example
|
72
|
+
|
73
|
+
Use `config.ru` and `rackup`. Example:
|
74
|
+
|
75
|
+
```ruby
|
76
|
+
# config.ru
|
77
|
+
|
78
|
+
require `webservice`
|
79
|
+
|
80
|
+
class App < Webservice::Base
|
81
|
+
get '/' do
|
82
|
+
'Hello, world!'
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
run App
|
87
|
+
```
|
88
|
+
|
89
|
+
and to run type
|
90
|
+
|
91
|
+
```
|
92
|
+
$ rackup # will (auto-)load config.ru
|
93
|
+
```
|
94
|
+
|
95
|
+
Note: `config.ru` is a shortcut (inline)
|
96
|
+
version of `Rack::Builder.new do ... end`:
|
97
|
+
|
98
|
+
```ruby
|
99
|
+
# server.rb
|
100
|
+
|
101
|
+
require 'webservice'
|
102
|
+
|
103
|
+
class App < Webservice::Base
|
104
|
+
get '/' do
|
105
|
+
'Hello, world!'
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
builder = Rack::Builder.new do
|
110
|
+
run App
|
111
|
+
end
|
112
|
+
|
113
|
+
Rack::Server.start builder.to_app
|
114
|
+
```
|
115
|
+
|
116
|
+
and to run type
|
117
|
+
|
118
|
+
```
|
119
|
+
$ ruby ./server.rb
|
120
|
+
```
|
121
|
+
|
122
|
+
|
123
|
+
|
124
|
+
## "Real World" Examples
|
125
|
+
|
126
|
+
See
|
127
|
+
|
128
|
+
[**`beerkit / beer.db.service`**](https://github.com/beerkit/beer.db.service) -
|
129
|
+
beer.db HTTP JSON API (web service) scripts e.g.
|
130
|
+
|
131
|
+
```ruby
|
132
|
+
get '/beer/(r|rnd|rand|random)' do # special keys for random beer
|
133
|
+
Beer.rnd
|
134
|
+
end
|
135
|
+
|
136
|
+
get '/beer/:key'
|
137
|
+
Beer.find_by! key: params[:key]
|
138
|
+
end
|
139
|
+
|
140
|
+
get '/brewery/(r|rnd|rand|random)' do # special keys for random brewery
|
141
|
+
Brewery.rnd
|
142
|
+
end
|
143
|
+
|
144
|
+
get '/brewery/:key'
|
145
|
+
Brewery.find_by! key: params[:key]
|
146
|
+
end
|
147
|
+
```
|
148
|
+
|
149
|
+
[**`worlddb / world.db.service`**](https://github.com/worlddb/world.db.service) -
|
150
|
+
world.db HTTP JSON API (web service) scripts
|
151
|
+
|
152
|
+
[**`sportdb / sport.db.service`**](https://github.com/sportdb/sport.db.service) -
|
153
|
+
sport.db (football.db) HTTP JSON API (web service) scripts
|
154
|
+
|
14
155
|
|
15
156
|
|
16
157
|
## License
|
17
158
|
|
18
159
|
The `webservice` scripts are dedicated to the public domain.
|
19
160
|
Use it as you please with no restrictions whatsoever.
|
20
|
-
|
data/lib/webservice.rb
CHANGED
data/lib/webservice/base.rb
CHANGED
@@ -3,31 +3,50 @@
|
|
3
3
|
|
4
4
|
module Webservice
|
5
5
|
|
6
|
+
## use (an reuse from Rack) some freezed string constants
|
7
|
+
## HTTP verbs
|
8
|
+
GET = Rack::GET
|
9
|
+
POST = Rack::POST
|
10
|
+
PATCH = Rack::PATCH
|
11
|
+
PUT = Rack::PUT
|
12
|
+
DELETE = Rack::DELETE
|
13
|
+
HEAD = Rack::HEAD
|
14
|
+
OPTIONS = Rack::OPTIONS
|
15
|
+
|
16
|
+
## HTTP headers
|
17
|
+
CONTENT_LENGTH = Rack::CONTENT_LENGTH
|
18
|
+
CONTENT_TYPE = Rack::CONTENT_TYPE
|
19
|
+
|
20
|
+
LOCATION = 'Location'.freeze # not available from Rack
|
21
|
+
|
6
22
|
|
7
23
|
module Helpers
|
8
24
|
## add some more helpers
|
9
25
|
## "inspired" by sinatra (mostly) - for staying compatible
|
10
26
|
## see https://github.com/sinatra/sinatra/blob/master/lib/sinatra/base.rb
|
11
27
|
|
12
|
-
## todo -- add
|
13
|
-
## add status -- why? why not??
|
28
|
+
## todo -- add status -- why? why not??
|
14
29
|
|
15
30
|
# 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
|
-
|
31
|
+
def error( code, body=nil )
|
20
32
|
response.body = body unless body.nil?
|
21
33
|
halt code
|
22
34
|
end
|
23
35
|
|
24
36
|
# Halt processing and return a 404 Not Found.
|
25
|
-
def not_found(body=nil)
|
37
|
+
def not_found( body=nil )
|
26
38
|
error 404, body
|
27
39
|
end
|
28
40
|
|
41
|
+
|
42
|
+
def redirect_to( uri, status=302 ) ## Note: 302 == Found, 301 == Moved Permanently
|
43
|
+
halt status, { LOCATION => uri }
|
44
|
+
end
|
45
|
+
alias_method :redirect, :redirect_to
|
46
|
+
|
47
|
+
|
29
48
|
# Set multiple response headers with Hash.
|
30
|
-
def headers(hash=nil)
|
49
|
+
def headers( hash=nil )
|
31
50
|
response.headers.merge! hash if hash
|
32
51
|
response.headers
|
33
52
|
end
|
@@ -36,18 +55,18 @@ module Helpers
|
|
36
55
|
|
37
56
|
## (simple) content_type helper - all "hard-coded" for now; always uses utf-8 too
|
38
57
|
def content_type( type=nil )
|
39
|
-
return response[
|
58
|
+
return response[ CONTENT_TYPE ] unless type
|
40
59
|
|
41
60
|
if type.to_sym == :json
|
42
|
-
response[
|
61
|
+
response[ CONTENT_TYPE ] = 'application/json; charset=utf-8'
|
43
62
|
elsif type.to_sym == :js || type.to_sym == :javascript
|
44
|
-
response[
|
63
|
+
response[ CONTENT_TYPE ] = 'application/javascript; charset=utf-8'
|
45
64
|
## use 'text/javascript; charset=utf-8' -- why? why not??
|
46
65
|
## note: ietf recommends application/javascript
|
47
66
|
elsif type.to_sym == :csv || type.to_sym == :text || type.to_sym == :txt
|
48
|
-
response[
|
67
|
+
response[ CONTENT_TYPE ] = 'text/plain; charset=utf-8'
|
49
68
|
elsif type.to_sym == :html || type.to_sym == :htm
|
50
|
-
response[
|
69
|
+
response[ CONTENT_TYPE ] = 'text/html; charset=utf-8'
|
51
70
|
else
|
52
71
|
### unknown type; do nothing - sorry; issue warning - why? why not??
|
53
72
|
end
|
@@ -58,24 +77,38 @@ end ## module Helpers
|
|
58
77
|
class Base
|
59
78
|
include Helpers
|
60
79
|
|
80
|
+
|
61
81
|
class << self
|
62
82
|
|
83
|
+
def call( env ) ## note self.call(env) lets you use => run Base instead of run Base.new
|
84
|
+
## puts "calling #{self.name}.call"
|
85
|
+
prototype.call( env )
|
86
|
+
end
|
87
|
+
|
88
|
+
def prototype
|
89
|
+
## puts "calling #{self.name}.prototype"
|
90
|
+
@prototype ||= self.new
|
91
|
+
## pp @prototype
|
92
|
+
## @prototype
|
93
|
+
end
|
94
|
+
|
95
|
+
|
63
96
|
## todo/check: all verbs needed! (supported) - why, why not??
|
64
97
|
## e.g. add LINK, UNLINK ??
|
65
98
|
|
66
99
|
# Note: for now defining a `GET` handler also automatically defines
|
67
100
|
# a `HEAD` handler (follows sinatra convention)
|
68
|
-
def get( pattern, &block)
|
69
|
-
route(
|
70
|
-
route(
|
101
|
+
def get( pattern, &block )
|
102
|
+
route( GET, pattern, &block )
|
103
|
+
route( HEAD, pattern, &block )
|
71
104
|
end
|
72
105
|
|
73
|
-
def post( pattern, &block) route(
|
74
|
-
def patch( pattern, &block) route(
|
75
|
-
def put( pattern, &block) route(
|
76
|
-
def delete( pattern, &block) route(
|
77
|
-
def head( pattern, &block) route(
|
78
|
-
def options( pattern, &block) route(
|
106
|
+
def post( pattern, &block) route( POST, pattern, &block ); end
|
107
|
+
def patch( pattern, &block) route( PATCH, pattern, &block ); end
|
108
|
+
def put( pattern, &block) route( PUT, pattern, &block ); end
|
109
|
+
def delete( pattern, &block) route( DELETE, pattern, &block ); end
|
110
|
+
def head( pattern, &block) route( HEAD, pattern, &block ); end
|
111
|
+
def options( pattern, &block) route( OPTIONS, pattern, &block ); end
|
79
112
|
|
80
113
|
def route( method, pattern, &block )
|
81
114
|
puts "[debug] Webservice::Base.#{method.downcase} - add route #{method} '#{pattern}' to #<#{self.name}:#{self.object_id}> : #{self.class.name}"
|
@@ -93,7 +126,7 @@ class Base
|
|
93
126
|
def environment
|
94
127
|
## include APP_ENV why? why not?
|
95
128
|
## todo -- cache value? why why not? (see/follow sinatara set machinery ??)
|
96
|
-
(ENV['RACK_ENV'] || :development).to_sym
|
129
|
+
(ENV['APP_ENV'] || ENV['RACK_ENV'] || :development).to_sym
|
97
130
|
end
|
98
131
|
|
99
132
|
def development?() environment == :development; end
|
@@ -104,9 +137,9 @@ class Base
|
|
104
137
|
## convenience method
|
105
138
|
def run!
|
106
139
|
puts "[debug] Webservice::Base.run! - self = #<#{self.name}:#{self.object_id}> : #{self.class.name}" # note: assumes self is class
|
107
|
-
app = self
|
140
|
+
app = self ## note: use self; will be derived class (e.g. App and not Base)
|
108
141
|
port = 4567
|
109
|
-
Rack::Handler.
|
142
|
+
Rack::Handler::WEBrick.run( app, Port:port ) do |server|
|
110
143
|
## todo: add traps here - why, why not??
|
111
144
|
end
|
112
145
|
end
|
@@ -119,25 +152,35 @@ class Base
|
|
119
152
|
attr_reader :params
|
120
153
|
attr_reader :env
|
121
154
|
|
122
|
-
def call(env)
|
123
|
-
dup.call!(env)
|
155
|
+
def call( env )
|
156
|
+
dup.call!( env )
|
124
157
|
end
|
125
158
|
|
126
|
-
def call!(env)
|
159
|
+
def call!( env )
|
127
160
|
env['PATH_INFO'] = '/' if env['PATH_INFO'].empty?
|
128
|
-
|
161
|
+
|
162
|
+
@request = Rack::Request.new( env )
|
129
163
|
@response = Rack::Response.new
|
130
164
|
@params = request.params
|
131
165
|
@env = env
|
166
|
+
|
167
|
+
|
168
|
+
## (auto-)add (merge in) cors headers
|
169
|
+
## todo: move into a before filter ?? lets you overwrite headers - needed - why? why not??
|
170
|
+
headers 'Access-Control-Allow-Origin' => '*',
|
171
|
+
'Access-Control-Allow-Headers' => 'Authorization,Accepts,Content-Type,X-CSRF-Token,X-Requested-With',
|
172
|
+
'Access-Control-Allow-Methods' => 'GET,POST,PUT,DELETE,OPTIONS'
|
173
|
+
|
132
174
|
route_eval
|
175
|
+
|
133
176
|
@response.finish
|
134
177
|
end
|
135
178
|
|
136
179
|
|
137
180
|
def halt( *args )
|
138
|
-
response.status = args.detect{|arg| arg.is_a?(Fixnum) } || 200
|
139
|
-
response.header.merge!(args.detect{|arg| arg.is_a?(Hash) } || {})
|
140
|
-
response.body = [args.detect{|arg| arg.is_a?(String) } || '']
|
181
|
+
response.status = args.detect{ |arg| arg.is_a?(Fixnum) } || 200
|
182
|
+
response.header.merge!( args.detect{ |arg| arg.is_a?(Hash) } || {} )
|
183
|
+
response.body = [args.detect{ |arg| arg.is_a?(String) } || '']
|
141
184
|
throw :halt, response
|
142
185
|
end
|
143
186
|
|
@@ -145,57 +188,98 @@ private
|
|
145
188
|
|
146
189
|
def route_eval
|
147
190
|
catch(:halt) do
|
148
|
-
self.class.routes[request.request_method]
|
191
|
+
routes = self.class.routes[ request.request_method ]
|
192
|
+
routes.each do |pattern, block|
|
149
193
|
## puts "trying matching route >#{request.path_info}<..."
|
150
194
|
url_params = pattern.params( request.path_info )
|
151
195
|
if url_params ## note: params returns nil if no match
|
152
196
|
## puts " BINGO! url_params: #{url_params.inspect}"
|
153
197
|
if !url_params.empty? ## url_params hash NOT empty (e.g. {}) merge with req params
|
154
198
|
## todo/fix: check merge order - params overwrites url_params - why? why not??
|
155
|
-
@params = url_params.merge( params )
|
199
|
+
@params = url_params.merge( @params )
|
156
200
|
end
|
157
201
|
handle_response( instance_eval( &block ))
|
158
202
|
return
|
159
203
|
end
|
160
204
|
end
|
205
|
+
# no match found for route/request
|
161
206
|
halt 404
|
162
207
|
end
|
163
208
|
end
|
164
209
|
|
165
210
|
|
166
211
|
|
167
|
-
|
168
|
-
def handle_response( obj )
|
212
|
+
## todo: add as_json like opts={} why? why not?
|
213
|
+
def handle_response( obj, opts={} )
|
169
214
|
puts "[Webservice::Base#handle_response (#{request.path_info}) params: #{params.inspect}] - obj : #{obj.class.name}"
|
170
215
|
pp obj
|
171
216
|
|
172
217
|
## "magic" param format; default to json
|
173
218
|
format = params['format'] || 'json'
|
174
219
|
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
220
|
+
## note: response.body must be (expects) an array!!!
|
221
|
+
## thus, [json] etc.
|
222
|
+
|
223
|
+
if format == 'csv' || format == 'txt' ||
|
224
|
+
format == 'html' || format == 'htm'
|
225
|
+
|
226
|
+
data = as_tabular( obj )
|
227
|
+
|
228
|
+
## note: array required!!!
|
229
|
+
# array => multiple records (array of hashes)
|
230
|
+
if data.is_a?( Array )
|
231
|
+
if format == 'csv' || format == 'txt'
|
232
|
+
content_type :txt ## use csv content type - why? why not??
|
233
|
+
response.body = [generate_csv( data )]
|
234
|
+
else
|
235
|
+
## asume html
|
236
|
+
content_type :html
|
237
|
+
response.body = [generate_html_table( data )]
|
238
|
+
end
|
239
|
+
else
|
240
|
+
## wrong format (expect array of hashes)
|
241
|
+
## todo: issue warning/notice about wrong format - how?
|
242
|
+
## use different http status code - why? why not??
|
243
|
+
content_type :txt
|
244
|
+
## todo/check: use just data.to_s for all - why? why not?
|
245
|
+
## for now return as is (convert to string with to_s or inspect)
|
246
|
+
response.body = [data.is_a?( String ) ? data.to_s : data.inspect]
|
247
|
+
end
|
183
248
|
else
|
184
|
-
|
249
|
+
data = as_json( obj )
|
250
|
+
|
251
|
+
## note: hash or array required!!! for now for json generation
|
252
|
+
# hash => single record
|
253
|
+
# array => multiple records (that is, array of hashes)
|
254
|
+
|
255
|
+
if data.is_a?( Hash ) || data.is_a?( Array )
|
256
|
+
json = JSON.pretty_generate( data ) ## use pretty printer
|
185
257
|
|
186
|
-
|
258
|
+
callback = params.delete( 'callback' )
|
187
259
|
|
188
|
-
|
189
|
-
|
190
|
-
|
260
|
+
if callback
|
261
|
+
content_type :js
|
262
|
+
response.body = ["#{callback}(#{json})"]
|
263
|
+
else
|
264
|
+
content_type :json
|
265
|
+
response.body = [json]
|
266
|
+
end
|
191
267
|
else
|
192
|
-
|
193
|
-
|
268
|
+
## todo/fix/check: change http status to unprocessable entity
|
269
|
+
## or something -- why ??? why not??
|
270
|
+
##
|
271
|
+
## allow "standalone" number, nils, strings - why? why not?
|
272
|
+
## for now valid json must be wrapped in array [] or hash {}
|
273
|
+
content_type :txt
|
274
|
+
## todo/check: use just data.to_s for all - why? why not?
|
275
|
+
## for now return as is (convert to string with to_s or inspect)
|
276
|
+
response.body = [data.is_a?( String ) ? data.to_s : data.inspect]
|
194
277
|
end
|
195
278
|
end
|
196
279
|
end # method handle_response
|
197
280
|
|
198
281
|
|
282
|
+
|
199
283
|
def generate_csv( recs )
|
200
284
|
## note: for now assumes (only works with) array of hash records e.g.:
|
201
285
|
## [
|
@@ -243,14 +327,38 @@ private
|
|
243
327
|
end
|
244
328
|
|
245
329
|
|
246
|
-
|
247
|
-
|
330
|
+
##########################################
|
331
|
+
## auto-generate/convert "magic"
|
332
|
+
|
333
|
+
def as_tabular( obj, opts={} )
|
334
|
+
## for now allow
|
335
|
+
## as_tab, as_tabular - others too? e.g. as_table why? why not?
|
336
|
+
## like as_json will return a hash or array of hashes NOT a string!!!!
|
337
|
+
|
338
|
+
if obj.respond_to? :as_tab
|
339
|
+
obj.as_tab
|
340
|
+
elsif obj.respond_to? :as_tabular
|
341
|
+
obj.as_tabular
|
342
|
+
else
|
343
|
+
## note: use as_json will return hash (for record) or array of hashes (for records)
|
344
|
+
if obj.respond_to? :as_json
|
345
|
+
obj.as_json
|
346
|
+
else
|
347
|
+
obj ## just try/use as is (assumes array of hashesd)
|
348
|
+
end
|
349
|
+
end
|
350
|
+
end
|
351
|
+
|
352
|
+
|
353
|
+
def as_json( obj, opts={} )
|
354
|
+
if obj.respond_to? :as_json_v3 ## try (our own) serializer first
|
355
|
+
obj.as_json_v3
|
356
|
+
elsif obj.respond_to? :as_json_v2 ## try (our own) serializer first
|
248
357
|
obj.as_json_v2
|
249
358
|
elsif obj.respond_to? :as_json ## try (activerecord) serializer
|
250
|
-
obj.
|
359
|
+
obj.as_json
|
251
360
|
else
|
252
|
-
## just try/use
|
253
|
-
obj.to_json
|
361
|
+
obj ## just try/use as is
|
254
362
|
end
|
255
363
|
end
|
256
364
|
|
data/lib/webservice/version.rb
CHANGED
@@ -1,10 +1,16 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
3
|
module Webservice
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
4
|
+
|
5
|
+
module Version
|
6
|
+
MAJOR = 0 ## todo: namespace inside version or something - why? why not??
|
7
|
+
MINOR = 5
|
8
|
+
PATCH = 0 ## note: if not put in module will overwrite PATCH (HTTP Verb Constant)!!!
|
9
|
+
end
|
10
|
+
|
11
|
+
VERSION = [Version::MAJOR,
|
12
|
+
Version::MINOR,
|
13
|
+
Version::PATCH].join('.')
|
8
14
|
|
9
15
|
def self.version
|
10
16
|
VERSION
|
data/test/service/app.rb
CHANGED
@@ -13,12 +13,10 @@ end
|
|
13
13
|
|
14
14
|
get '/halt/404' do
|
15
15
|
halt 404 # 404 - not found
|
16
|
-
## todo: check why log reports 200-OK (for status code)!!
|
17
16
|
end
|
18
17
|
|
19
18
|
get '/halt_error' do
|
20
19
|
halt 500, "Error fatal" # 500 - internal server error
|
21
|
-
## todo: check why log reports 200-OK (for status code)!!
|
22
20
|
end
|
23
21
|
|
24
22
|
|
data/test/test_app.rb
CHANGED
@@ -24,46 +24,46 @@ class TestApp < MiniTest::Test
|
|
24
24
|
def test_get
|
25
25
|
get '/'
|
26
26
|
assert last_response.ok?
|
27
|
-
assert_equal
|
27
|
+
assert_equal "Hello World", last_response.body
|
28
28
|
|
29
29
|
get '/hello/world'
|
30
30
|
assert last_response.ok?
|
31
|
-
assert_equal
|
31
|
+
assert_equal "Hello world", last_response.body
|
32
32
|
|
33
33
|
##############################
|
34
34
|
## get '/hello/:name'
|
35
35
|
get '/hello/ruby'
|
36
36
|
assert last_response.ok?
|
37
|
-
assert_equal
|
37
|
+
assert_equal "Hello ruby", last_response.body
|
38
38
|
|
39
39
|
get '/hello/ruby?test=t' ## try w/ extra query string/params
|
40
40
|
assert last_response.ok?
|
41
|
-
assert_equal
|
41
|
+
assert_equal "Hello ruby", last_response.body
|
42
42
|
|
43
43
|
##################################
|
44
44
|
## get '/:message/:name'
|
45
45
|
get '/servus/wien'
|
46
46
|
assert last_response.ok?
|
47
|
-
assert_equal
|
47
|
+
assert_equal "servus wien", last_response.body
|
48
48
|
|
49
49
|
get '/Hallo/Welt'
|
50
50
|
assert last_response.ok?
|
51
|
-
assert_equal
|
51
|
+
assert_equal "Hallo Welt", last_response.body
|
52
52
|
end
|
53
53
|
|
54
54
|
|
55
55
|
def test_format
|
56
56
|
get '/key.format'
|
57
57
|
assert last_response.ok?
|
58
|
-
assert_equal
|
58
|
+
assert_equal "key format", last_response.body
|
59
59
|
|
60
60
|
get '/ottakringer.xxx'
|
61
61
|
assert last_response.ok?
|
62
|
-
assert_equal
|
62
|
+
assert_equal "ottakringer xxx", last_response.body
|
63
63
|
|
64
64
|
get '/ottakringer'
|
65
65
|
assert last_response.ok?
|
66
|
-
assert_equal
|
66
|
+
assert_equal "ottakringer ", last_response.body
|
67
67
|
end
|
68
68
|
|
69
69
|
|
@@ -85,25 +85,38 @@ CSV
|
|
85
85
|
</table>
|
86
86
|
HTML
|
87
87
|
|
88
|
+
|
89
|
+
countries_json = <<JSON.strip
|
90
|
+
[
|
91
|
+
{
|
92
|
+
"key": "at",
|
93
|
+
"name": "Austria"
|
94
|
+
},
|
95
|
+
{
|
96
|
+
"key": "mx",
|
97
|
+
"name": "Mexico"
|
98
|
+
}
|
99
|
+
]
|
100
|
+
JSON
|
101
|
+
|
88
102
|
get '/countries.json'
|
89
103
|
assert last_response.ok?
|
90
|
-
assert_equal
|
104
|
+
assert_equal countries_json, last_response.body
|
91
105
|
|
92
106
|
get '/countries'
|
93
107
|
assert last_response.ok?
|
94
|
-
assert_equal
|
108
|
+
assert_equal countries_json, last_response.body
|
95
109
|
end # method test_countries
|
96
110
|
|
97
111
|
|
112
|
+
|
98
113
|
def test_halt
|
99
|
-
## get '/halt/404'
|
100
114
|
get '/halt/404'
|
115
|
+
assert_equal 404, last_response.status
|
101
116
|
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
## todo: check error codes
|
106
|
-
assert true
|
117
|
+
get '/halt_error' ## 500, "Error fatal" # 500 - internal server error
|
118
|
+
assert_equal 500, last_response.status
|
119
|
+
assert_equal "Error fatal", last_response.body
|
107
120
|
end
|
108
121
|
|
109
122
|
end # class TestApp
|
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.5.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-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: logutils
|