webservice 0.4.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|