jellyfish 1.0.2 → 1.1.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.
@@ -0,0 +1,180 @@
1
+
2
+ require 'jellyfish/test'
3
+ require 'jellyfish/urlmap'
4
+
5
+ require 'rack/mock'
6
+
7
+ describe Jellyfish::URLMap do
8
+ would "dispatches paths correctly" do
9
+ app = lambda { |env|
10
+ [200, {
11
+ 'X-ScriptName' => env['SCRIPT_NAME'],
12
+ 'X-PathInfo' => env['PATH_INFO'],
13
+ 'Content-Type' => 'text/plain'
14
+ }, [""]]
15
+ }
16
+ map = Rack::Lint.new(Jellyfish::URLMap.new({
17
+ '/bar' => app,
18
+ '/foo' => app,
19
+ '/foo/bar' => app
20
+ }))
21
+
22
+ res = Rack::MockRequest.new(map).get("/")
23
+ res.should.not_found?
24
+
25
+ res = Rack::MockRequest.new(map).get("/qux")
26
+ res.should.not_found?
27
+
28
+ res = Rack::MockRequest.new(map).get("/foo")
29
+ res.should.ok?
30
+ res["X-ScriptName"].should.eq "/foo"
31
+ res["X-PathInfo"].should.eq ""
32
+
33
+ res = Rack::MockRequest.new(map).get("/foo/")
34
+ res.should.ok?
35
+ res["X-ScriptName"].should.eq "/foo"
36
+ res["X-PathInfo"].should.eq "/"
37
+
38
+ res = Rack::MockRequest.new(map).get("/foo/bar")
39
+ res.should.ok?
40
+ res["X-ScriptName"].should.eq "/foo/bar"
41
+ res["X-PathInfo"].should.eq ""
42
+
43
+ res = Rack::MockRequest.new(map).get("/foo/bar/")
44
+ res.should.ok?
45
+ res["X-ScriptName"].should.eq "/foo/bar"
46
+ res["X-PathInfo"].should.eq "/"
47
+
48
+ res = Rack::MockRequest.new(map).get("/foo///bar//quux")
49
+ res.status.should.eq 200
50
+ res.should.ok?
51
+ res["X-ScriptName"].should.eq "/foo/bar"
52
+ res["X-PathInfo"].should.eq "//quux"
53
+
54
+ res = Rack::MockRequest.new(map).get("/foo/quux", "SCRIPT_NAME" => "/bleh")
55
+ res.should.ok?
56
+ res["X-ScriptName"].should.eq "/bleh/foo"
57
+ res["X-PathInfo"].should.eq "/quux"
58
+
59
+ res = Rack::MockRequest.new(map).get("/bar", 'HTTP_HOST' => 'foo.org')
60
+ res.should.ok?
61
+ res["X-ScriptName"].should.eq "/bar"
62
+ res["X-PathInfo"].should.empty?
63
+
64
+ res = Rack::MockRequest.new(map).get("/bar/", 'HTTP_HOST' => 'foo.org')
65
+ res.should.ok?
66
+ res["X-ScriptName"].should.eq "/bar"
67
+ res["X-PathInfo"].should.eq '/'
68
+ end
69
+
70
+ would "be nestable" do
71
+ map = Rack::Lint.new(Rack::URLMap.new("/foo" =>
72
+ Rack::URLMap.new("/bar" =>
73
+ Rack::URLMap.new("/quux" => lambda { |env|
74
+ [200,
75
+ { "Content-Type" => "text/plain",
76
+ "X-Position" => "/foo/bar/quux",
77
+ "X-PathInfo" => env["PATH_INFO"],
78
+ "X-ScriptName" => env["SCRIPT_NAME"],
79
+ }, [""]]}
80
+ ))))
81
+
82
+ res = Rack::MockRequest.new(map).get("/foo/bar")
83
+ res.should.not_found?
84
+
85
+ res = Rack::MockRequest.new(map).get("/foo/bar/quux")
86
+ res.should.ok?
87
+ res["X-Position"].should.eq "/foo/bar/quux"
88
+ res["X-PathInfo"].should.eq ""
89
+ res["X-ScriptName"].should.eq "/foo/bar/quux"
90
+ end
91
+
92
+ would "route root apps correctly" do
93
+ map = Rack::Lint.new(Rack::URLMap.new("/" => lambda { |env|
94
+ [200,
95
+ { "Content-Type" => "text/plain",
96
+ "X-Position" => "root",
97
+ "X-PathInfo" => env["PATH_INFO"],
98
+ "X-ScriptName" => env["SCRIPT_NAME"]
99
+ }, [""]]},
100
+ "/foo" => lambda { |env|
101
+ [200,
102
+ { "Content-Type" => "text/plain",
103
+ "X-Position" => "foo",
104
+ "X-PathInfo" => env["PATH_INFO"],
105
+ "X-ScriptName" => env["SCRIPT_NAME"]
106
+ }, [""]]}
107
+ ))
108
+
109
+ res = Rack::MockRequest.new(map).get("/foo/bar")
110
+ res.should.ok?
111
+ res["X-Position"].should.eq "foo"
112
+ res["X-PathInfo"].should.eq "/bar"
113
+ res["X-ScriptName"].should.eq "/foo"
114
+
115
+ res = Rack::MockRequest.new(map).get("/foo")
116
+ res.should.ok?
117
+ res["X-Position"].should.eq "foo"
118
+ res["X-PathInfo"].should.eq ""
119
+ res["X-ScriptName"].should.eq "/foo"
120
+
121
+ res = Rack::MockRequest.new(map).get("/bar")
122
+ res.should.ok?
123
+ res["X-Position"].should.eq "root"
124
+ res["X-PathInfo"].should.eq "/bar"
125
+ res["X-ScriptName"].should.eq ""
126
+
127
+ res = Rack::MockRequest.new(map).get("")
128
+ res.should.ok?
129
+ res["X-Position"].should.eq "root"
130
+ res["X-PathInfo"].should.eq "/"
131
+ res["X-ScriptName"].should.eq ""
132
+ end
133
+
134
+ would "not squeeze slashes" do
135
+ map = Rack::Lint.new(Rack::URLMap.new("/" => lambda { |env|
136
+ [200,
137
+ { "Content-Type" => "text/plain",
138
+ "X-Position" => "root",
139
+ "X-PathInfo" => env["PATH_INFO"],
140
+ "X-ScriptName" => env["SCRIPT_NAME"]
141
+ }, [""]]},
142
+ "/foo" => lambda { |env|
143
+ [200,
144
+ { "Content-Type" => "text/plain",
145
+ "X-Position" => "foo",
146
+ "X-PathInfo" => env["PATH_INFO"],
147
+ "X-ScriptName" => env["SCRIPT_NAME"]
148
+ }, [""]]}
149
+ ))
150
+
151
+ res = Rack::MockRequest.new(map).get("/http://example.org/bar")
152
+ res.should.ok?
153
+ res["X-Position"].should.eq "root"
154
+ res["X-PathInfo"].should.eq "/http://example.org/bar"
155
+ res["X-ScriptName"].should.eq ""
156
+ end
157
+
158
+ would "not be case sensitive with hosts" do
159
+ map = Rack::Lint.new(Rack::URLMap.new("/" => lambda { |env|
160
+ [200,
161
+ { "Content-Type" => "text/plain",
162
+ "X-Position" => "root",
163
+ "X-PathInfo" => env["PATH_INFO"],
164
+ "X-ScriptName" => env["SCRIPT_NAME"]
165
+ }, [""]]}
166
+ ))
167
+
168
+ res = Rack::MockRequest.new(map).get("/")
169
+ res.should.ok?
170
+ res["X-Position"].should.eq "root"
171
+ res["X-PathInfo"].should.eq "/"
172
+ res["X-ScriptName"].should.eq ""
173
+
174
+ res = Rack::MockRequest.new(map).get("/")
175
+ res.should.ok?
176
+ res["X-Position"].should.eq "root"
177
+ res["X-PathInfo"].should.eq "/"
178
+ res["X-ScriptName"].should.eq ""
179
+ end
180
+ end
@@ -98,7 +98,7 @@ describe 'Sinatra base_test.rb' do
98
98
  status .should.eq 210
99
99
  headers['X-Downstream'] .should.eq 'true'
100
100
  headers['Content-Length'].should.eq '28'
101
- body .should.eq ['Hello after explicit forward']
101
+ body.to_a .should.eq ['Hello after explicit forward']
102
102
  end
103
103
  end
104
104
  end
@@ -292,66 +292,6 @@ describe 'Sinatra routing_test.rb' do
292
292
  should.raise(TypeError)
293
293
  end
294
294
 
295
- would 'return response immediately on next or halt' do
296
- app = Class.new{
297
- include Jellyfish
298
- controller_include Jellyfish::MultiActions
299
-
300
- get '/next' do
301
- body 'Hello World'
302
- next
303
- end
304
-
305
- get '/halt' do
306
- body 'Hello World'
307
- halt
308
- 'Boo-hoo World'
309
- end
310
- }.new
311
-
312
- %w[/next /halt].each do |path|
313
- status, _, body = get(path, app)
314
- status.should.eq 200
315
- body .should.eq ['Hello World']
316
- end
317
- end
318
-
319
- would 'halt with a response tuple' do
320
- app = Class.new{
321
- include Jellyfish
322
- controller_include Jellyfish::MultiActions
323
-
324
- get '/' do
325
- halt [295, {'Content-Type' => 'text/plain'}, ['Hello World']]
326
- end
327
- }.new
328
-
329
- status, headers, body = get('/', app)
330
- status .should.eq 295
331
- headers['Content-Type'].should.eq 'text/plain'
332
- body .should.eq ['Hello World']
333
- end
334
-
335
- would 'transition to the next matching route on next' do
336
- app = Class.new{
337
- include Jellyfish
338
- controller_include Jellyfish::MultiActions, Jellyfish::NormalizedParams
339
- get %r{^/(?<foo>\w+)} do
340
- params['foo'].should.eq 'bar'
341
- next
342
- end
343
-
344
- get do
345
- params.should.not.include?('foo')
346
- 'Hello World'
347
- end
348
- }.new
349
-
350
- status, _, body = get('/bar', app)
351
- status.should.eq 200
352
- body .should.eq ['Hello World']
353
- end
354
-
355
295
  would 'match routes defined in superclasses' do
356
296
  sup = Class.new{
357
297
  include Jellyfish
@@ -20,27 +20,38 @@ describe 'from README.md' do
20
20
  next if title =~ /NewRelic/i
21
21
 
22
22
  would "pass from README.md #%02d #{title}" % index do
23
- method_path, expect = test.strip.split("\n", 2)
24
- method, path = method_path.split(' ')
25
- uri = URI.parse(path)
26
- pinfo, query = uri.path, uri.query
27
-
28
- sock = nil
29
- status, headers, body = File.open(File::NULL) do |input|
30
- Rack::Builder.app{ eval(code) }.call(
31
- 'REQUEST_METHOD' => method, 'PATH_INFO' => pinfo,
32
- 'QUERY_STRING' => query , 'SCRIPT_NAME'=> '' ,
33
- 'rack.input' => input ,
34
- 'rack.hijack' => lambda{
35
- sock = StringIO.new
36
- # or TypeError: no implicit conversion of StringIO into IO
37
- mock(IO).select([sock]){ [[sock], [], []] }
38
- sock
39
- })
40
- end
23
+ app = Rack::Builder.app{ eval(code) }
24
+
25
+ test.split("\n\n").each do |t|
26
+ method_path, expect = t.strip.split("\n", 2)
27
+ method, path = method_path.split(' ')
28
+ uri = URI.parse(path)
29
+ pinfo, query = uri.path, uri.query
30
+
31
+ sock = nil
32
+ status, headers, body = File.open(File::NULL) do |input|
33
+ app.call(
34
+ 'HTTP_VERSION' => 'HTTP/1.1',
35
+ 'REQUEST_METHOD' => method, 'PATH_INFO' => pinfo,
36
+ 'QUERY_STRING' => query , 'SCRIPT_NAME'=> '' ,
37
+ 'rack.input' => input ,
38
+ 'rack.hijack' => lambda{
39
+ sock = StringIO.new
40
+ # or TypeError: no implicit conversion of StringIO into IO
41
+ mock(IO).select([sock]){ [[sock], [], []] }
42
+ sock
43
+ })
44
+ end
41
45
 
42
- body.extend(Enumerable)
43
- [status, headers, body.to_a].should.eq eval(expect, binding, __FILE__)
46
+ if hijack = headers.delete('rack.hijack')
47
+ sock = StringIO.new
48
+ hijack.call(sock)
49
+ body = sock.string.each_line("\n\n")
50
+ end
51
+
52
+ body.extend(Enumerable)
53
+ [status, headers, body.to_a].should.eq eval(expect, binding, __FILE__)
54
+ end
44
55
  end
45
56
  end
46
57
  end
metadata CHANGED
@@ -1,18 +1,22 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jellyfish
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lin Jen-Shin (godfat)
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-12-09 00:00:00.000000000 Z
11
+ date: 2015-09-25 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: |-
14
14
  Pico web framework for building API-centric web applications.
15
- For Rack applications or Rack middlewares. Around 250 lines of code.
15
+ For Rack applications or Rack middleware. Around 250 lines of code.
16
+
17
+ Check [jellyfish-contrib][] for extra extensions.
18
+
19
+ [jellyfish-contrib]: https://github.com/godfat/jellyfish-contrib
16
20
  email:
17
21
  - godfat (XD) godfat.org
18
22
  executables: []
@@ -28,42 +32,36 @@ files:
28
32
  - README.md
29
33
  - Rakefile
30
34
  - TODO.md
35
+ - bench/bench_builder.rb
31
36
  - config.ru
32
37
  - jellyfish.gemspec
33
38
  - jellyfish.png
34
39
  - lib/jellyfish.rb
40
+ - lib/jellyfish/builder.rb
35
41
  - lib/jellyfish/chunked_body.rb
36
42
  - lib/jellyfish/json.rb
37
- - lib/jellyfish/multi_actions.rb
38
43
  - lib/jellyfish/newrelic.rb
39
44
  - lib/jellyfish/normalized_params.rb
40
45
  - lib/jellyfish/normalized_path.rb
41
46
  - lib/jellyfish/public/302.html
42
47
  - lib/jellyfish/public/404.html
43
48
  - lib/jellyfish/public/500.html
44
- - lib/jellyfish/sinatra.rb
45
- - lib/jellyfish/swagger.rb
46
49
  - lib/jellyfish/test.rb
50
+ - lib/jellyfish/urlmap.rb
47
51
  - lib/jellyfish/version.rb
48
52
  - lib/jellyfish/websocket.rb
49
- - public/css/screen.css
50
- - public/index.html
51
- - public/js/shred.bundle.js
52
- - public/js/shred/content.js
53
- - public/js/swagger-ui.js
54
- - public/js/swagger.js
55
53
  - task/README.md
56
54
  - task/gemgem.rb
55
+ - test/rack/test_builder.rb
56
+ - test/rack/test_urlmap.rb
57
57
  - test/sinatra/test_base.rb
58
58
  - test/sinatra/test_chunked_body.rb
59
59
  - test/sinatra/test_error.rb
60
- - test/sinatra/test_multi_actions.rb
61
60
  - test/sinatra/test_routing.rb
62
61
  - test/test_from_readme.rb
63
62
  - test/test_inheritance.rb
64
63
  - test/test_log.rb
65
64
  - test/test_misc.rb
66
- - test/test_swagger.rb
67
65
  - test/test_threads.rb
68
66
  - test/test_websocket.rb
69
67
  homepage: https://github.com/godfat/jellyfish
@@ -86,20 +84,20 @@ required_rubygems_version: !ruby/object:Gem::Requirement
86
84
  version: '0'
87
85
  requirements: []
88
86
  rubyforge_project:
89
- rubygems_version: 2.4.5
87
+ rubygems_version: 2.4.8
90
88
  signing_key:
91
89
  specification_version: 4
92
90
  summary: Pico web framework for building API-centric web applications.
93
91
  test_files:
92
+ - test/rack/test_builder.rb
93
+ - test/rack/test_urlmap.rb
94
94
  - test/sinatra/test_base.rb
95
95
  - test/sinatra/test_chunked_body.rb
96
96
  - test/sinatra/test_error.rb
97
- - test/sinatra/test_multi_actions.rb
98
97
  - test/sinatra/test_routing.rb
99
98
  - test/test_from_readme.rb
100
99
  - test/test_inheritance.rb
101
100
  - test/test_log.rb
102
101
  - test/test_misc.rb
103
- - test/test_swagger.rb
104
102
  - test/test_threads.rb
105
103
  - test/test_websocket.rb
@@ -1,31 +0,0 @@
1
-
2
- require 'jellyfish'
3
-
4
-
5
-
6
- module Jellyfish
7
- module MultiActions
8
- def call env
9
- @env = env
10
- dispatch.inject(nil){ |_, route_block| block_call(*route_block) }
11
- end
12
-
13
- def dispatch
14
- acts = actions.map{ |(route, block)|
15
- case route
16
- when String
17
- [route, block] if route == path_info
18
- else#Regexp, using else allows you to use custom matcher
19
- match = route.match(path_info)
20
- [match, block] if match
21
- end
22
- }.compact
23
-
24
- if acts.empty?
25
- action_missing
26
- else
27
- acts
28
- end
29
- end
30
- end
31
- end
@@ -1,13 +0,0 @@
1
-
2
- require 'jellyfish'
3
- require 'jellyfish/multi_actions'
4
- require 'jellyfish/normalized_params'
5
- require 'jellyfish/normalized_path'
6
-
7
- module Jellyfish
8
- module Sinatra
9
- include MultiActions
10
- include NormalizedParams
11
- include NormalizedPath
12
- end
13
- end