goliath 0.9.4 → 1.0.0.beta.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of goliath might be problematic. Click here for more details.

Files changed (102) hide show
  1. data/.gitignore +3 -0
  2. data/Guardfile +8 -0
  3. data/HISTORY.md +10 -0
  4. data/LICENSE +1 -1
  5. data/README.md +28 -29
  6. data/Rakefile +10 -2
  7. data/examples/activerecord/config/srv.rb +2 -1
  8. data/examples/activerecord/srv.rb +14 -5
  9. data/examples/api_proxy.rb +3 -7
  10. data/examples/around.rb +38 -0
  11. data/examples/async_aroundware_demo.rb +2 -2
  12. data/examples/async_upload.rb +1 -1
  13. data/examples/auth_and_rate_limit.rb +1 -1
  14. data/examples/clone.rb +26 -0
  15. data/examples/config/websocket.rb +1 -0
  16. data/examples/custom_logs.rb +21 -0
  17. data/examples/custom_server.rb +6 -44
  18. data/examples/early_abort.rb +6 -3
  19. data/examples/echo.rb +1 -1
  20. data/examples/fiber_pool.rb +35 -0
  21. data/examples/grape/config/apiserver.rb +8 -0
  22. data/examples/grape/server.rb +67 -0
  23. data/examples/gziped.rb +1 -1
  24. data/examples/params.rb +36 -0
  25. data/examples/rasterize/rasterize.rb +1 -2
  26. data/examples/router.rb +15 -0
  27. data/examples/template.rb +14 -7
  28. data/examples/test.rb +31 -0
  29. data/examples/upload.rb +17 -0
  30. data/examples/views/joke.markdown +4 -4
  31. data/examples/websocket.rb +39 -0
  32. data/examples/ws/favicon.ico +0 -0
  33. data/examples/ws/index.erb +50 -0
  34. data/goliath.gemspec +24 -6
  35. data/lib/goliath/api.rb +15 -82
  36. data/lib/goliath/application.rb +3 -17
  37. data/lib/goliath/connection.rb +16 -9
  38. data/lib/goliath/constants.rb +2 -0
  39. data/lib/goliath/env.rb +2 -3
  40. data/lib/goliath/goliath.rb +24 -34
  41. data/lib/goliath/plugins/latency.rb +7 -3
  42. data/lib/goliath/rack/builder.rb +1 -37
  43. data/lib/goliath/rack/favicon.rb +31 -0
  44. data/lib/goliath/rack/formatters/json.rb +1 -1
  45. data/lib/goliath/rack/heartbeat.rb +1 -0
  46. data/lib/goliath/rack/jsonp.rb +1 -0
  47. data/lib/goliath/rack/params.rb +2 -17
  48. data/lib/goliath/rack/render.rb +0 -1
  49. data/lib/goliath/rack/templates.rb +18 -7
  50. data/lib/goliath/rack/types/base.rb +24 -0
  51. data/lib/goliath/rack/types/boolean.rb +18 -0
  52. data/lib/goliath/rack/types/core.rb +19 -0
  53. data/lib/goliath/rack/types/symbol.rb +16 -0
  54. data/lib/goliath/rack/types.rb +10 -0
  55. data/lib/goliath/rack/validation/coerce.rb +48 -0
  56. data/lib/goliath/rack/validation/param.rb +113 -0
  57. data/lib/goliath/rack/validation/request_method.rb +1 -1
  58. data/lib/goliath/rack/validation/required.rb +47 -0
  59. data/lib/goliath/rack/validation/required_param.rb +42 -17
  60. data/lib/goliath/rack/validation.rb +3 -0
  61. data/lib/goliath/rack.rb +2 -2
  62. data/lib/goliath/request.rb +41 -9
  63. data/lib/goliath/response.rb +0 -2
  64. data/lib/goliath/runner.rb +55 -4
  65. data/lib/goliath/server.rb +7 -3
  66. data/lib/goliath/test_helper.rb +70 -16
  67. data/lib/goliath/test_helper_ws.rb +42 -0
  68. data/lib/goliath/version.rb +1 -1
  69. data/lib/goliath/websocket.rb +80 -0
  70. data/pkg/goliath-0.9.4.gem +0 -0
  71. data/pkg/goliath-1.0.0.beta.1.gem +0 -0
  72. data/spec/integration/async_request_processing.rb +1 -1
  73. data/spec/integration/early_abort_spec.rb +3 -10
  74. data/spec/integration/echo_spec.rb +8 -8
  75. data/spec/integration/jsonp_spec.rb +31 -0
  76. data/spec/integration/keepalive_spec.rb +2 -2
  77. data/spec/integration/template_spec.rb +10 -5
  78. data/spec/integration/test_helper_spec.rb +33 -0
  79. data/spec/integration/valid_spec.rb +35 -5
  80. data/spec/integration/websocket_spec.rb +44 -0
  81. data/spec/unit/api_spec.rb +2 -19
  82. data/spec/unit/connection_spec.rb +3 -0
  83. data/spec/unit/rack/formatters/json_spec.rb +3 -3
  84. data/spec/unit/rack/heartbeat_spec.rb +13 -0
  85. data/spec/unit/rack/params_spec.rb +2 -8
  86. data/spec/unit/rack/validation/param_spec.rb +443 -0
  87. data/spec/unit/rack/validation/request_method_spec.rb +5 -0
  88. data/spec/unit/rack/validation/required_param_spec.rb +71 -1
  89. data/spec/unit/runner_spec.rb +21 -7
  90. data/test/echo_test.rb +25 -0
  91. data/test/test_helper.rb +5 -0
  92. metadata +316 -78
  93. data/examples/env_use_statements.rb +0 -20
  94. data/examples/favicon.rb +0 -40
  95. data/examples/rack_routes.rb +0 -125
  96. data/examples/rasterize/thumb/f7ad4cb03e5bfd0e2c43db8e598fb3cd.png +0 -0
  97. data/examples/valid.rb +0 -17
  98. data/lib/goliath/deprecated/async_aroundware.rb +0 -133
  99. data/lib/goliath/deprecated/mongo_receiver.rb +0 -84
  100. data/lib/goliath/deprecated/response_receiver.rb +0 -97
  101. data/spec/integration/rack_routes_spec.rb +0 -169
  102. data/spec/unit/rack/builder_spec.rb +0 -40
@@ -1,20 +0,0 @@
1
- #!/usr/bin/env ruby
2
- $:<< '../lib' << 'lib'
3
-
4
- require 'goliath'
5
- require 'yajl'
6
-
7
- # API must be started with -e [production, development, ...]
8
- # or set your ENV['RACK_ENV'] to specify the environemtn
9
-
10
- class EnvUseStatements < Goliath::API
11
- if Goliath.dev?
12
- use Goliath::Rack::Render, 'json'
13
- elsif Goliath.prod?
14
- use Goliath::Rack::Render, 'xml'
15
- end
16
-
17
- def response(env)
18
- [200, {}, {'Test' => 'Response'}]
19
- end
20
- end
data/examples/favicon.rb DELETED
@@ -1,40 +0,0 @@
1
- #!/usr/bin/env ruby
2
- require 'time'
3
-
4
- #
5
- # Reads a favicon.ico statically at load time, renders it on any request for
6
- # '/favicon.ico', and sends every other request on downstream.
7
- #
8
- # If you will be serving even one more file than this one, you should instead
9
- # use Rack::Static:
10
- #
11
- # use(Rack::Static, # render static files from ./public
12
- # :root => Goliath::Application.app_path("public"),
13
- # :urls => ["/favicon.ico", '/stylesheets', '/javascripts', '/images'])
14
- #
15
- class Favicon
16
- def initialize(app, filename)
17
- @@favicon = File.read(filename)
18
- @@last_mod = File.mtime(filename).utc.rfc822
19
- @@expires = Time.at(Time.now + 604800).utc.rfc822 # 1 week from now
20
- @app = app
21
- end
22
-
23
- def call(env, *args)
24
- if env['REQUEST_PATH'] == '/favicon.ico'
25
- return [200, {"Last-Modified"=> @@last_mod.to_s, "Expires" => @@expires, "Content-Type"=>"image/vnd.microsoft.icon"}, @@favicon]
26
- else
27
- return @app.call(env)
28
- end
29
- end
30
- end
31
-
32
- if File.expand_path($0) == File.expand_path(__FILE__)
33
- $:<< '../lib' << 'lib'
34
- require 'goliath'
35
- puts "starting hello world!"
36
- class HelloWorld < Goliath::API
37
- HelloWorld.use(Favicon, File.expand_path(File.dirname(__FILE__)+"/public/favicon.ico"))
38
- end
39
- require(File.dirname(__FILE__)+'/hello_world.rb')
40
- end
@@ -1,125 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # encoding: utf-8
3
- $:<< '../lib' << 'lib'
4
-
5
- require 'goliath'
6
-
7
- # Example demonstrating how to have an API acting as a router.
8
- # RackRoutes defines multiple uris and how to map them accordingly.
9
- # Some of these routes are redirected to other Goliath API.
10
- #
11
- # The reason why only the last API is being used by the Goliath Server
12
- # is because its name matches the filename.
13
- # All the APIs are available but by default the server will use the one
14
- # matching the file name.
15
-
16
- # Our custom Goliath API
17
- class HelloWorld < Goliath::API
18
- def response(env)
19
- [200, {}, "hello world!"]
20
- end
21
- end
22
-
23
- class PostHelloWorld < Goliath::API
24
- def response(env)
25
- [200, {}, "hello post world!"]
26
- end
27
- end
28
-
29
- class HeaderCollector < Goliath::API
30
- def on_headers(env, header)
31
- @headers ||= {}
32
- @headers.merge!(header)
33
- end
34
-
35
- def response(env)
36
- [200, {}, "headers: #{@headers.inspect}"]
37
- end
38
- end
39
-
40
- class HelloNumber < Goliath::API
41
- use Goliath::Rack::Params
42
- def response(env)
43
- [200, {}, "number #{params[:number]}!"]
44
- end
45
- end
46
-
47
- class BigNumber < Goliath::API
48
- use Goliath::Rack::Params
49
- def response(env)
50
- [200, {}, "big number #{params[:number]}!"]
51
- end
52
- end
53
-
54
- class Bonjour < Goliath::API
55
- def response(env)
56
- [200, {}, "bonjour!"]
57
- end
58
- end
59
-
60
- class Hola < Goliath::API
61
- use Goliath::Rack::Params
62
- use Goliath::Rack::Validation::RequiredParam, {:key => "foo"}
63
-
64
- def response(env)
65
- [200, {}, "hola!"]
66
- end
67
- end
68
-
69
- class Aloha < Goliath::API
70
- use Goliath::Rack::Validation::RequestMethod, %w(GET)
71
-
72
- def response(env)
73
- [200, {}, "Aloha"]
74
- end
75
- end
76
-
77
- class RackRoutes < Goliath::API
78
- map '/version' do
79
- run Proc.new { |env| [200, {"Content-Type" => "text/html"}, ["Version 0.1"]] }
80
- end
81
-
82
- post "/hello_world" do
83
- run PostHelloWorld.new
84
- end
85
-
86
- get "/hello_world" do
87
- run HelloWorld.new
88
- end
89
-
90
- head "/hello_world" do
91
- run HelloWorld.new
92
- end
93
-
94
- map "/headers", HeaderCollector do
95
- use Goliath::Rack::Validation::RequestMethod, %w(GET)
96
- end
97
-
98
- map "/bonjour" do
99
- run Bonjour.new
100
- end
101
-
102
- map "/hola" do
103
- use Goliath::Rack::Validation::RequestMethod, %w(GET)
104
- run Hola.new
105
- end
106
-
107
- map "/aloha", Aloha
108
-
109
- map "/:number", :number => /\d+/ do
110
- if params[:number].to_i > 100
111
- run BigNumber.new
112
- else
113
- run HelloNumber.new
114
- end
115
- end
116
-
117
- not_found('/') do
118
- run Proc.new { |env| [404, {"Content-Type" => "text/html"}, ["Try /version /hello_world, /bonjour, or /hola"]] }
119
- end
120
-
121
- # You must use either maps or response, but never both!
122
- def response(env)
123
- raise RuntimeException.new("#response is ignored when using maps, so this exception won't raise. See spec/integration/rack_routes_spec.")
124
- end
125
- end
data/examples/valid.rb DELETED
@@ -1,17 +0,0 @@
1
- #!/usr/bin/env ruby
2
- $:<< '../lib' << 'lib'
3
-
4
- require 'goliath'
5
-
6
- class Valid < Goliath::API
7
- use Goliath::Rack::Params
8
- use Goliath::Rack::Validation::RequiredParam, {:key => 'test'}
9
-
10
- # If you are using Golaith version <=0.9.1 you need to use Goliath::Rack::ValidationError
11
- # to prevent the request from remaining open after an error occurs
12
- #use Goliath::Rack::ValidationError
13
-
14
- def response(env)
15
- [200, {}, 'OK']
16
- end
17
- end
@@ -1,133 +0,0 @@
1
- module Goliath
2
- module Rack
3
- #
4
- # Note: This class is deprecated. Instead, use BarrierAroundwareFactory
5
- # (orchestrates multiple concurrent requests) or SimpleAroundwareFactory
6
- # (like AsyncMiddleware, but with a simpler interface).
7
- #
8
- # The differences:
9
- # * ResponseReceiver/MultiReceiver was a stupid name. The thing that has
10
- # pre_ and post_process is the Aroundware, the thing that manufactures
11
- # it is an AroundwareFactory.
12
- # * An aroundware's pre_process may return a direct response, which is
13
- # immediately sent back upstream (no further downstream processing
14
- # happens). In the typical case, you will want to add
15
- # return Goliath::Connection::AsyncResponse
16
- # to your pre_process method.
17
- # * ResponseReceiver used to masquerade as callback and middleware. Yuck.
18
- # The downstream response is now set via #accept_response, not #call.
19
- #
20
- # * change
21
- # use Goliath::Rack::AsyncAroundware, MyObsoleteReceiver
22
- # to
23
- # use Goliath::Rack::BarrierAroundwareFactory, MyHappyBarrier
24
- # * `BarrierAroundware` provides the combined functionality of
25
- # `MultiReceiver` and `ResponseReceiver`, which will go away. It's now a
26
- # mixin (module) so you're not forced to inherit from it.
27
- # * There is no more `responses` method: either use instance accessors or
28
- # look in the `successes`/`failures` hashes for yourresults.
29
- # * Both enqueued responses and the downstream response are sent to
30
- # `accept_response`; there is no more `call` method.
31
- # * `MongoReceiver` will go away, because there's no need for it. See
32
- # `examples/auth_and_rate_limit.rb` for examples
33
- #
34
- class AsyncAroundware
35
- include Goliath::Rack::Validator
36
-
37
- #
38
- # Called by the framework to create the middleware.
39
- #
40
- # Any extra args passed to the use statement are sent to each
41
- # aroundware_klass as it is created.
42
- #
43
- # @example
44
- # class Awesomizer2011 < Goliath::Rack::MultiReceiver
45
- # def initialize(env, aq)
46
- # @awesomeness_quotient = aq
47
- # super(env)
48
- # end
49
- # # ... define pre_process and post_process ...
50
- # end
51
- #
52
- # class AwesomeApiWithShortening < Goliath::API
53
- # use Goliath::Rack::AsyncAroundware, Awesomizer2011, 3
54
- # # ... stuff ...
55
- # end
56
- #
57
- # @param app [#call] the downstream app
58
- # @param aroundware_klass a class that quacks like a
59
- # Goliath::Rack::ResponseReceiver and an EM::Deferrable
60
- # @param *args [Array] extra args to pass to the aroundware
61
- # @return [Goliath::Rack::AsyncAroundware]
62
- def initialize app, aroundware_klass, *args
63
- @app = app
64
- @aroundware_klass = aroundware_klass
65
- @aroundware_args = args
66
- end
67
-
68
- # Coordinates aroundware to process a request.
69
- #
70
- # We hook the aroundware in the middle of the async_callback chain:
71
- # * send the downstream response to the aroundware, whether received directly
72
- # from @app.call or via async callback
73
- # * have the upstream callback chain be invoked when the aroundware completes
74
- #
75
- # @param env [Goliath::Env] The goliath environment
76
- # @return [Array] The [status_code, headers, body] tuple
77
- def call(env)
78
- aroundware = new_aroundware(env)
79
-
80
- aroundware_resp = aroundware.pre_process
81
-
82
- hook_into_callback_chain(env, aroundware)
83
-
84
- downstream_resp = @app.call(env)
85
-
86
- # if downstream resp is final, pass it to the aroundware; it will invoke
87
- # the callback chain at its leisure. Our response is *always* async.
88
- if final_response?(downstream_resp)
89
- aroundware.call(downstream_resp)
90
- end
91
- return Goliath::Connection::AsyncResponse
92
- end
93
-
94
- # Put aroundware in the middle of the async_callback chain:
95
- # * save the old callback chain;
96
- # * have the downstream callback send results to the aroundware (possibly
97
- # completing it)
98
- # * set the old callback chain to fire when the aroundware completes
99
- def hook_into_callback_chain(env, aroundware)
100
- async_callback = env['async.callback']
101
-
102
- # The response from the downstream app is accepted by the aroundware...
103
- downstream_callback = Proc.new do |resp|
104
- safely(env){ aroundware.call(resp) }
105
- end
106
-
107
- # .. but the upstream chain is only invoked when the aroundware completes
108
- invoke_upstream_chain = Proc.new do
109
- new_resp = safely(env){ aroundware.post_process }
110
- async_callback.call(new_resp)
111
- end
112
-
113
- env['async.callback'] = downstream_callback
114
- aroundware.callback(&invoke_upstream_chain)
115
- aroundware.errback(&invoke_upstream_chain)
116
- end
117
-
118
- def final_response?(resp)
119
- resp != Goliath::Connection::AsyncResponse
120
- end
121
-
122
- # Generate a aroundware to process the request, using request env & any args
123
- # passed to this AsyncAroundware at creation
124
- #
125
- # @param env [Goliath::Env] The goliath environment
126
- # @return [Goliath::Rack::ResponseReceiver] The response_receiver to process this request
127
- def new_aroundware(env)
128
- @aroundware_klass.new(env, *@aroundware_args)
129
- end
130
-
131
- end
132
- end
133
- end
@@ -1,84 +0,0 @@
1
- require 'goliath/deprecated/response_receiver'
2
- require 'em-synchrony/em-mongo'
3
-
4
- module Goliath
5
- module Synchrony
6
- #
7
- # Note: This class is deprecated. Please instead use BarrierAroundware
8
- # (orchestrates multiple concurrent requests) or SimpleAroundware (like
9
- # AsyncMiddleware, but with a simpler interface).
10
- #
11
- # There are more notes on the lib/goliath/deprecated/async_aroundware docs.
12
- #
13
- # ___________________________________________________________________________
14
- #
15
- # Currently, you must provide in the env a method 'mongo' that returns a mongo
16
- # collection or collection proxy (probably by setting it up in the config).
17
- #
18
- # This will almost certainly change to something less crappy.
19
- #
20
- class MongoReceiver
21
- include Goliath::Synchrony::ResponseReceiver
22
- include EM::Deferrable
23
- include Goliath::Rack::Validator
24
-
25
- def initialize(env, db_name)
26
- @env = env
27
- @pending_queries = 0
28
- @db = env.config[db_name]
29
- end
30
-
31
- def db
32
- @db
33
- end
34
-
35
- def finished?
36
- response_received? && (@pending_queries == 0)
37
- end
38
-
39
- def enqueue(handle, req_id)
40
- # ... requests aren't deferrables so they're tracked in @pending_queries
41
- end
42
-
43
- if defined?(EM::Mongo::Cursor)
44
- def find(collection, selector={}, opts={}, &block)
45
- @pending_queries += 1
46
- db.collection(collection).afind(selector, opts).to_a.callback do |result|
47
- yield result
48
- @pending_queries -= 1
49
- self.succeed if finished?
50
- end
51
- end
52
- else
53
- def find(collection, selector={}, opts={}, &block)
54
- @pending_queries += 1
55
- db.collection(collection).afind(selector, opts) do |result|
56
- yield result
57
- @pending_queries -= 1
58
- self.succeed if finished?
59
- end
60
- end
61
- end
62
-
63
- def first(collection, selector={}, opts={}, &block)
64
- opts[:limit] = 1
65
- self.find(collection, selector, opts) do |result|
66
- yield result.first
67
- end
68
- end
69
-
70
- def insert(collection, *args)
71
- db.collection(collection).insert(*args)
72
- end
73
- def update(collection, *args)
74
- db.collection(collection).update(*args)
75
- end
76
- def save(collection, *args)
77
- db.collection(collection).save(*args)
78
- end
79
- def remove(collection, *args)
80
- db.collection(collection).remove(*args)
81
- end
82
- end
83
- end
84
- end
@@ -1,97 +0,0 @@
1
- module Goliath
2
- module Synchrony
3
-
4
- #
5
- # Note: This class is deprecated. Please instead use BarrierAroundware
6
- # (orchestrates multiple concurrent requests) or SimpleAroundware (like
7
- # AsyncMiddleware, but with a simpler interface).
8
- #
9
- # There are more notes on the lib/goliath/deprecated/async_aroundware docs.
10
- #
11
- module ResponseReceiver
12
- # The request environment, set in the initializer
13
- attr_reader :env
14
- # The response, set by the ResponseReceiver's downstream
15
- attr_accessor :status, :headers, :body
16
-
17
- # Override this method in your middleware to perform any preprocessing
18
- # (launching a deferred request, perhaps).
19
- #
20
- # @return [Array] array contains [status, headers, body]
21
- def pre_process
22
- Goliath::Connection::AsyncResponse
23
- end
24
-
25
- # Override this method in your middleware to perform any postprocessing.
26
- # This will only be invoked when all deferred requests (including the
27
- # response) have completed.
28
- #
29
- # @return [Array] array contains [status, headers, body]
30
- def post_process
31
- [status, headers, body]
32
- end
33
-
34
- # Virtual setter for the downstream middleware/endpoint response
35
- def downstream_resp=(status_headers_body)
36
- @status, @headers, @body = status_headers_body
37
- end
38
-
39
- # Invoked by the async_callback chain. Stores the [status, headers, body]
40
- # for post_process'ing
41
- def call resp
42
- return resp if resp.first == Goliath::Connection::AsyncResponse.first
43
- self.downstream_resp = resp
44
- check_progress(nil)
45
- end
46
-
47
- # Have we received a response?
48
- def response_received?
49
- !! @status
50
- end
51
-
52
- protected
53
-
54
- def check_progress(fiber)
55
- if finished?
56
- succeed
57
- # continue processing
58
- fiber.resume(self) if fiber && fiber.alive? && fiber != Fiber.current
59
- end
60
- end
61
- end
62
-
63
- #
64
- # Note: This class is deprecated. Please instead use BarrierAroundware
65
- # (orchestrates multiple concurrent requests) or SimpleAroundware (like
66
- # AsyncMiddleware, but with a simpler interface).
67
- #
68
- # There are more notes on the lib/goliath/deprecated/async_aroundware docs.
69
- #
70
- class MultiReceiver < EM::Synchrony::Multi
71
- include ResponseReceiver
72
-
73
- # Create a new MultiReceiver
74
- # @param env [Goliath::Env] the current environment
75
- def initialize env
76
- @env = env
77
- super()
78
- end
79
-
80
- alias_method :enqueue, :add
81
-
82
- def successes
83
- responses[:callback]
84
- end
85
-
86
- def failures
87
- responses[:errback]
88
- end
89
-
90
- # Finished if we received a response and the multi request is finished
91
- def finished?
92
- super && response_received?
93
- end
94
- end
95
-
96
- end
97
- end
@@ -1,169 +0,0 @@
1
- # encoding: utf-8
2
- require 'spec_helper'
3
- require File.join(File.dirname(__FILE__), '../../', 'examples/rack_routes')
4
-
5
- describe RackRoutes do
6
- let(:err) { Proc.new { fail "API request failed" } }
7
-
8
- context "when using maps" do
9
-
10
- it "ignores #response" do
11
- expect {
12
- with_api(RackRoutes) do
13
- get_request({:path => '/'}, err) {}
14
- end
15
- }.to_not raise_error
16
- end
17
-
18
- it 'fallback not found to missing' do
19
- with_api(RackRoutes) do
20
- get_request({:path => '/donkey'}, err) do |cb|
21
- cb.response_header.status.should == 404
22
- cb.response.should == 'Try /version /hello_world, /bonjour, or /hola'
23
- end
24
- end
25
- with_api(RackRoutes) do
26
- get_request({:path => '/'}, err) do |cb|
27
- cb.response_header.status.should == 404
28
- cb.response.should == 'Try /version /hello_world, /bonjour, or /hola'
29
- end
30
- end
31
- end
32
-
33
- it 'fallback not found to /' do
34
- with_api(RackRoutes) do
35
- get_request({:path => '/donkey'}, err) do |cb|
36
- cb.response_header.status.should == 404
37
- cb.response.should == 'Try /version /hello_world, /bonjour, or /hola'
38
- end
39
- end
40
- end
41
-
42
- it 'routes to the correct API' do
43
- with_api(RackRoutes) do
44
- get_request({:path => '/bonjour'}, err) do |c|
45
- c.response_header.status.should == 200
46
- c.response.should == 'bonjour!'
47
- end
48
- end
49
- end
50
-
51
- it 'routes to the correct API using regex filters' do
52
- with_api(RackRoutes) do
53
- get_request({:path => '/98'}, err) do |c|
54
- c.response_header.status.should == 200
55
- c.response.should == 'number 98!'
56
- end
57
- end
58
- end
59
-
60
- it 'routes to the correct API referencing params in the body of the buidler' do
61
- with_api(RackRoutes) do
62
- get_request({:path => '/123123'}, err) do |c|
63
- c.response_header.status.should == 200
64
- c.response.should == 'big number 123123!'
65
- end
66
- end
67
- end
68
-
69
- context 'sinatra style route definition' do
70
- it 'should honor the request method' do
71
- with_api(RackRoutes) do
72
- post_request({:path => '/hello_world'}, err) do |c|
73
- c.response_header.status.should == 200
74
- c.response.should == 'hello post world!'
75
- end
76
- end
77
- end
78
-
79
- it 'should reject other request methods' do
80
- with_api(RackRoutes) do
81
- put_request({:path => '/hello_world'}, err) do |c|
82
- c.response_header.status.should == 405
83
- c.response_header['ALLOW'].split(/, /).should == %w(GET HEAD POST)
84
- end
85
- end
86
- end
87
- end
88
-
89
- context 'routes defined with get' do
90
- it 'should allow get' do
91
- with_api(RackRoutes) do
92
- get_request({:path => '/hello_world'}, err) do |c|
93
- c.response_header.status.should == 200
94
- c.response.should == 'hello world!'
95
- end
96
- end
97
- end
98
- end
99
-
100
- context 'routes defined with head' do
101
- it 'should allow head' do
102
- with_api(RackRoutes) do
103
- head_request({:path => '/hello_world'}, err) do |c|
104
- c.response_header.status.should == 200
105
- c.response.should == 'hello world!'
106
- end
107
- end
108
- end
109
- end
110
-
111
- context "defined in blocks" do
112
- it 'uses middleware defined in the block' do
113
- with_api(RackRoutes) do
114
- post_request({:path => '/hola'}, err) do |c|
115
- # the /hola route only supports GET requests
116
- c.response_header.status.should == 405
117
- c.response.should == '[:error, "Invalid request method"]'
118
- c.response_header['ALLOW'].should == 'GET'
119
- end
120
- end
121
- end
122
-
123
- it "doesn't use middleware defined in the API" do
124
- with_api(RackRoutes) do
125
- get_request({:path => '/hola'}, err) do |cb|
126
- # it doesn't raise required param error
127
- cb.response_header.status.should == 200
128
- cb.response.should == "hola!"
129
- end
130
- end
131
- end
132
- end
133
-
134
- context "defined in classes" do
135
- it 'uses API middleware' do
136
- with_api(RackRoutes) do
137
- post_request({:path => '/aloha'}, err) do |c|
138
- # the /hola route only supports GET requests
139
- c.response_header.status.should == 405
140
- c.response.should == '[:error, "Invalid request method"]'
141
- c.response_header['ALLOW'].should == 'GET'
142
- end
143
- end
144
- end
145
- end
146
-
147
- context "with event handlers" do
148
- it "collects header events" do
149
- with_api(RackRoutes) do
150
- get_request({:path => '/headers'}, err) do |c|
151
- c.response_header.status.should == 200
152
- c.response.should == 'headers: {"Connection"=>"close", "Host"=>"localhost:9900", "User-Agent"=>"EventMachine HttpClient"}'
153
- end
154
- end
155
- end
156
-
157
- it "rejects POST request" do
158
- with_api(RackRoutes) do
159
- post_request({:path => '/headers'}, err) do |c|
160
- # the /headers route only supports GET requests
161
- c.response_header.status.should == 405
162
- c.response.should == '[:error, "Invalid request method"]'
163
- c.response_header['ALLOW'].should == 'GET'
164
- end
165
- end
166
- end
167
- end
168
- end
169
- end