goliath 0.9.1 → 0.9.2
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.
- data/.gitignore +1 -0
- data/HISTORY +50 -0
- data/README.md +2 -0
- data/examples/activerecord/srv.rb +1 -3
- data/examples/async_aroundware_demo.rb +81 -0
- data/examples/async_upload.rb +1 -2
- data/examples/auth_and_rate_limit.rb +143 -0
- data/examples/chunked_streaming.rb +37 -0
- data/examples/conf_test.rb +1 -3
- data/examples/config/auth_and_rate_limit.rb +30 -0
- data/examples/config/template.rb +8 -0
- data/examples/content_stream.rb +1 -3
- data/examples/echo.rb +8 -6
- data/examples/env_use_statements.rb +17 -0
- data/examples/gziped.rb +1 -3
- data/examples/public/stylesheets/style.css +296 -0
- data/examples/rack_routes.rb +65 -3
- data/examples/rasterize/rasterize.js +15 -0
- data/examples/rasterize/rasterize.rb +36 -0
- data/examples/rasterize/rasterize_and_shorten.rb +37 -0
- data/examples/stream.rb +2 -2
- data/examples/template.rb +48 -0
- data/examples/test_rig.rb +125 -0
- data/examples/valid.rb +4 -2
- data/examples/views/debug.haml +4 -0
- data/examples/views/joke.markdown +13 -0
- data/examples/views/layout.erb +12 -0
- data/examples/views/layout.haml +39 -0
- data/examples/views/root.haml +28 -0
- data/goliath.gemspec +10 -3
- data/lib/goliath.rb +0 -36
- data/lib/goliath/api.rb +137 -26
- data/lib/goliath/application.rb +71 -21
- data/lib/goliath/connection.rb +4 -2
- data/lib/goliath/constants.rb +1 -0
- data/lib/goliath/env.rb +40 -1
- data/lib/goliath/goliath.rb +30 -15
- data/lib/goliath/headers.rb +2 -2
- data/lib/goliath/plugins/latency.rb +8 -2
- data/lib/goliath/rack.rb +18 -0
- data/lib/goliath/rack/async_aroundware.rb +56 -0
- data/lib/goliath/rack/async_middleware.rb +93 -0
- data/lib/goliath/rack/builder.rb +42 -0
- data/lib/goliath/rack/default_response_format.rb +3 -15
- data/lib/goliath/rack/formatters.rb +11 -0
- data/lib/goliath/rack/formatters/html.rb +2 -18
- data/lib/goliath/rack/formatters/json.rb +2 -17
- data/lib/goliath/rack/formatters/plist.rb +32 -0
- data/lib/goliath/rack/formatters/xml.rb +23 -31
- data/lib/goliath/rack/formatters/yaml.rb +27 -0
- data/lib/goliath/rack/jsonp.rb +1 -13
- data/lib/goliath/rack/params.rb +55 -27
- data/lib/goliath/rack/render.rb +13 -22
- data/lib/goliath/rack/templates.rb +357 -0
- data/lib/goliath/rack/tracer.rb +11 -12
- data/lib/goliath/rack/validation.rb +12 -0
- data/lib/goliath/rack/validation/default_params.rb +0 -2
- data/lib/goliath/rack/validation/numeric_range.rb +11 -2
- data/lib/goliath/rack/validation/request_method.rb +3 -2
- data/lib/goliath/rack/validation/required_param.rb +13 -11
- data/lib/goliath/rack/validation/required_value.rb +11 -15
- data/lib/goliath/rack/validator.rb +51 -0
- data/lib/goliath/request.rb +34 -20
- data/lib/goliath/response.rb +3 -2
- data/lib/goliath/runner.rb +5 -11
- data/lib/goliath/server.rb +2 -1
- data/lib/goliath/synchrony/mongo_receiver.rb +64 -0
- data/lib/goliath/synchrony/response_receiver.rb +64 -0
- data/lib/goliath/test_helper.rb +39 -21
- data/lib/goliath/validation.rb +2 -0
- data/lib/goliath/{rack/validation_error.rb → validation/error.rb} +0 -16
- data/lib/goliath/validation/standard_http_errors.rb +31 -0
- data/lib/goliath/version.rb +1 -1
- data/spec/integration/http_log_spec.rb +16 -16
- data/spec/integration/rack_routes_spec.rb +144 -0
- data/spec/integration/reloader_spec.rb +4 -4
- data/spec/integration/template_spec.rb +54 -0
- data/spec/integration/trace_spec.rb +23 -0
- data/spec/integration/valid_spec.rb +21 -0
- data/spec/spec_helper.rb +3 -1
- data/spec/unit/api_spec.rb +30 -0
- data/spec/unit/rack/builder_spec.rb +40 -0
- data/spec/unit/rack/formatters/plist_spec.rb +51 -0
- data/spec/unit/rack/formatters/yaml_spec.rb +53 -0
- data/spec/unit/rack/params_spec.rb +22 -0
- data/spec/unit/rack/render_spec.rb +10 -5
- data/spec/unit/rack/validation/numeric_range_spec.rb +8 -1
- data/spec/unit/rack/validation/request_method_spec.rb +8 -8
- data/spec/unit/rack/validation/required_param_spec.rb +19 -15
- data/spec/unit/rack/validation/required_value_spec.rb +10 -13
- data/spec/unit/server_spec.rb +4 -4
- data/spec/unit/validation/standard_http_errors_spec.rb +21 -0
- metadata +177 -35
- data/spec/unit/rack/validation_error_spec.rb +0 -40
data/.gitignore
CHANGED
data/HISTORY
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
HISTORY
|
2
|
+
=======
|
3
|
+
|
4
|
+
v0.9.1 (Apr 12, 2011)
|
5
|
+
---------------------
|
6
|
+
- Added extra messaging around the class not matching the file name (Carlos Brando)
|
7
|
+
|
8
|
+
- Fix issue with POST parameters not being parsed by Goliath::Rack::Params
|
9
|
+
- Added support for multipart encoded POST bodies
|
10
|
+
- Added support for parsing nested query string parameters (Nolan Evans)
|
11
|
+
- Added support for parsing application/json POST bodies
|
12
|
+
- Content-Types outside of multipart, urlencoded and application/json will not be parsed automatically.
|
13
|
+
|
14
|
+
- added 'run as user' option
|
15
|
+
- SERVER_NAME and SERVER_PORT are set to values in HOST header
|
16
|
+
|
17
|
+
- Cleaned up spec examples (Justin Ko)
|
18
|
+
|
19
|
+
- moved logger into 'rack.logger' key to be more Rack compliant (Env#logger added to
|
20
|
+
keep original API consistent)
|
21
|
+
- add command line option for specifying config file
|
22
|
+
- HTTP_CONTENT_LENGTH and HTTP_CONTENT_TYPE were changed to CONTENT_TYPE and CONTENT_LENGTH
|
23
|
+
to be more Rack compliant
|
24
|
+
- fix issue with loading config file in development mode
|
25
|
+
|
26
|
+
- Rack::Reloader will be loaded automatically by the framework in development mode.
|
27
|
+
|
28
|
+
|
29
|
+
v0.9.0 (Mar 9, 2011)
|
30
|
+
--------------------
|
31
|
+
(Initial Public Release)
|
32
|
+
|
33
|
+
Goliath is an open source version of the non-blocking (asynchronous) Ruby web server framework
|
34
|
+
powering PostRank. It is a lightweight framework designed to meet the following goals: bare
|
35
|
+
metal performance, Rack API and middleware support, simple configuration, fully asynchronous
|
36
|
+
processing, and readable and maintainable code (read: no callbacks).
|
37
|
+
|
38
|
+
The framework is powered by an EventMachine reactor, a high-performance HTTP parser and Ruby 1.9
|
39
|
+
runtime. One major advantage Goliath has over other asynchronous frameworks is the fact that by
|
40
|
+
leveraging Ruby fibers, it can untangle the complicated callback-based code into a format we are
|
41
|
+
all familiar and comfortable with: linear execution, which leads to more maintainable and readable code.
|
42
|
+
|
43
|
+
While MRI is the recommend platform, Goliath has been tested to run on JRuby and Rubinius.
|
44
|
+
|
45
|
+
Goliath has been in production at PostRank for over a year, serving a sustained 500 requests/s for
|
46
|
+
internal and external applications. Many of the Goliath processes have been running for months at
|
47
|
+
a time (read: no memory leaks) and have served hundreds of gigabytes of data without restarts. To
|
48
|
+
scale up and provide failover and redundancy, our individual Goliath servers at PostRank are usually
|
49
|
+
deployed behind a reverse proxy (such as HAProxy).
|
50
|
+
|
data/README.md
CHANGED
@@ -73,6 +73,8 @@ Goliath has been in production at PostRank for over a year, serving a sustained
|
|
73
73
|
* [Stage left: Enter Goliath - HTTP Proxy + MongoDB](http://everburning.com/news/stage-left-enter-goliath/)
|
74
74
|
* [InfoQ: Meet the Goliath of Ruby Application Servers](http://www.infoq.com/articles/meet-goliath)
|
75
75
|
* [Node.jsはコールバック・スパゲティを招くか](http://el.jibun.atmarkit.co.jp/rails/2011/03/nodejs-d123.html)
|
76
|
+
* [Goliath on LinuxFr.org (french)](http://linuxfr.org/news/en-vrac-spécial-ruby-jruby-sinatra-et-goliath)
|
77
|
+
* [Goliath et ses amis (slides in french)](http://nono.github.com/Presentations/20110416_Goliath/)
|
76
78
|
|
77
79
|
## Discussion and Support
|
78
80
|
|
@@ -21,9 +21,7 @@ end
|
|
21
21
|
class Srv < Goliath::API
|
22
22
|
use Goliath::Rack::Params
|
23
23
|
use Goliath::Rack::DefaultMimeType
|
24
|
-
use Goliath::Rack::
|
25
|
-
use Goliath::Rack::Render
|
26
|
-
use Goliath::Rack::ValidationError
|
24
|
+
use Goliath::Rack::Render, 'json'
|
27
25
|
|
28
26
|
use Goliath::Rack::Validation::RequiredParam, {:key => 'id', :type => 'ID'}
|
29
27
|
use Goliath::Rack::Validation::NumericRange, {:key => 'id', :min => 1}
|
@@ -0,0 +1,81 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$: << File.dirname(__FILE__)+'/../lib'
|
3
|
+
|
4
|
+
require 'goliath'
|
5
|
+
require 'em-synchrony/em-http'
|
6
|
+
require 'yajl/json_gem'
|
7
|
+
|
8
|
+
#
|
9
|
+
# Here's a way to make an asynchronous request in the middleware, and only
|
10
|
+
# proceed with the response when both the endpoint and our middleware's
|
11
|
+
# responses have completed.
|
12
|
+
#
|
13
|
+
# To run this, start the 'test_rig.rb' server on port 9002:
|
14
|
+
#
|
15
|
+
# ./examples/test_rig.rb -sv -p 9002
|
16
|
+
#
|
17
|
+
# And then start this server on port 9000:
|
18
|
+
#
|
19
|
+
# ./async_aroundware_demo.rb -sv -p 9000
|
20
|
+
#
|
21
|
+
# Now curl the async_aroundware_demo_multi:
|
22
|
+
#
|
23
|
+
# $ time curl 'http://127.0.0.1:9000/?delay_1=1.0&delay_2=1.5'
|
24
|
+
# { "results": {
|
25
|
+
# "sleep_2": { "delay": 1.5, "actual": 1.5085558891296387 },
|
26
|
+
# "sleep_1": { "delay": 1.0, "actual": 1.0098700523376465 }
|
27
|
+
# } }
|
28
|
+
#
|
29
|
+
# The requests are run concurrently:
|
30
|
+
#
|
31
|
+
# $ ./examples/async_aroundware_demo.rb -sv -p 9000 -e prod &
|
32
|
+
# [68463:INFO] 2011-05-03 23:13:03 :: Starting server on 0.0.0.0:9000 in production mode. Watch out for stones.
|
33
|
+
# $ ab -n10 -c10 'http://127.0.0.1:9000/?delay_1=1.5&delay_2=2.0'
|
34
|
+
# Connection Times (ms)
|
35
|
+
# min mean[+/-sd] median max
|
36
|
+
# Connect: 0 0 0.1 0 0
|
37
|
+
# Processing: 2027 2111 61.6 2112 2204
|
38
|
+
# Waiting: 2027 2111 61.5 2112 2204
|
39
|
+
# Total: 2027 2112 61.5 2113 2204
|
40
|
+
#
|
41
|
+
#
|
42
|
+
|
43
|
+
BASE_URL = 'http://localhost:9002/'
|
44
|
+
|
45
|
+
class MyResponseReceiver < Goliath::Synchrony::MultiReceiver
|
46
|
+
def pre_process
|
47
|
+
# Request with delay_1 and drop_1 -- note: 'aget', because we want execution to continue
|
48
|
+
req = EM::HttpRequest.new(BASE_URL).aget(:query => { :delay => env.params['delay_1'], :drop => env.params['drop_1'] })
|
49
|
+
add :sleep_1, req
|
50
|
+
end
|
51
|
+
|
52
|
+
def post_process
|
53
|
+
# unify the results with the results of the API call
|
54
|
+
responses[:callback].each{|name, resp| body[:results][name] = JSON.parse(resp.response) }
|
55
|
+
responses[:errback ].each{|name, err| body[:errors][name] = err.error }
|
56
|
+
[status, headers, JSON.generate(body)]
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
class AsyncAroundwareDemo < Goliath::API
|
61
|
+
use Goliath::Rack::Params
|
62
|
+
use Goliath::Rack::Validation::NumericRange, {:key => 'delay_1', :default => 1.0, :max => 5.0, :min => 0.0, :as => Float}
|
63
|
+
use Goliath::Rack::Validation::NumericRange, {:key => 'delay_2', :default => 0.5, :max => 5.0, :min => 0.0, :as => Float}
|
64
|
+
#
|
65
|
+
use Goliath::Rack::AsyncAroundware, MyResponseReceiver
|
66
|
+
|
67
|
+
def response(env)
|
68
|
+
# Request with delay_2 and drop_2 -- note: 'get', because we want execution to proceed linearly
|
69
|
+
resp = EM::HttpRequest.new(BASE_URL).get(:query => { :delay => env.params['delay_2'], :drop => env.params['drop_2'] })
|
70
|
+
|
71
|
+
body = { :results => {}, :errors => {} }
|
72
|
+
|
73
|
+
if resp.response_header.status.to_i != 0
|
74
|
+
body[:results][:sleep_2] = JSON.parse(resp.response)
|
75
|
+
else
|
76
|
+
body[:errors ][:sleep_2] = resp.error
|
77
|
+
end
|
78
|
+
|
79
|
+
[200, { }, body]
|
80
|
+
end
|
81
|
+
end
|
data/examples/async_upload.rb
CHANGED
@@ -7,8 +7,7 @@ require 'yajl'
|
|
7
7
|
class AsyncUpload < Goliath::API
|
8
8
|
use Goliath::Rack::Params # parse & merge query and body parameters
|
9
9
|
use Goliath::Rack::DefaultMimeType # cleanup accepted media types
|
10
|
-
use Goliath::Rack::
|
11
|
-
use Goliath::Rack::Render # auto-negotiate response format
|
10
|
+
use Goliath::Rack::Render, 'json' # auto-negotiate response format
|
12
11
|
|
13
12
|
def on_headers(env, headers)
|
14
13
|
env.logger.info 'received headers: ' + headers.inspect
|
@@ -0,0 +1,143 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$: << File.join(File.dirname(__FILE__), '../lib')
|
3
|
+
require 'goliath'
|
4
|
+
require 'em-mongo'
|
5
|
+
require 'em-http'
|
6
|
+
require 'em-synchrony/em-http'
|
7
|
+
require 'yajl/json_gem'
|
8
|
+
|
9
|
+
require 'goliath/synchrony/mongo_receiver' # has the aroundware logic for talking to mongodb
|
10
|
+
require File.join(File.dirname(__FILE__), 'http_log') # Use the HttpLog as our actual endpoint, but include this in the middleware
|
11
|
+
|
12
|
+
# Usage:
|
13
|
+
#
|
14
|
+
# First launch a dummy responder, like hello_world.rb or test_rig.rb:
|
15
|
+
# ruby ./examples/hello_world.rb -sv -p 8080 -e prod &
|
16
|
+
#
|
17
|
+
# Then launch this script
|
18
|
+
# ruby ./examples/auth_and_rate_limit.rb -sv -p 9000 --config $PWD/examples/config/auth_and_rate_limit.rb
|
19
|
+
#
|
20
|
+
|
21
|
+
# Tracks and enforces account and rate limit policies.
|
22
|
+
#
|
23
|
+
# Before the request:
|
24
|
+
#
|
25
|
+
# * validates the apikey exists
|
26
|
+
# * launches requests for the account and current usage (hourly rate limit, etc)
|
27
|
+
#
|
28
|
+
# It then passes the request down the middleware chain; execution resumes only
|
29
|
+
# when both the remote request and the auth info have returned.
|
30
|
+
#
|
31
|
+
# After remote request and auth info return:
|
32
|
+
#
|
33
|
+
# * Check the account exists and is valid
|
34
|
+
# * Check the rate limit is OK
|
35
|
+
#
|
36
|
+
# If it passes all those checks, the request goes through; otherwise we raise an
|
37
|
+
# error that Goliath::Rack::Validator turns into a 4xx response
|
38
|
+
#
|
39
|
+
# WARNING: Since this passes ALL requests through to the responder, it's only
|
40
|
+
# suitable for idempotent requests (GET, typically). You may need to handle
|
41
|
+
# POST/PUT/DELETE requests differently.
|
42
|
+
#
|
43
|
+
#
|
44
|
+
class AuthReceiver < Goliath::Synchrony::MongoReceiver
|
45
|
+
include Goliath::Validation
|
46
|
+
include Goliath::Rack::Validator
|
47
|
+
attr_accessor :account_info, :usage_info
|
48
|
+
|
49
|
+
# time period to aggregate stats over, in seconds
|
50
|
+
TIMEBIN_SIZE = 60 * 60
|
51
|
+
|
52
|
+
class MissingApikeyError < BadRequestError ; end
|
53
|
+
class RateLimitExceededError < ForbiddenError ; end
|
54
|
+
class InvalidApikeyError < UnauthorizedError ; end
|
55
|
+
|
56
|
+
def pre_process
|
57
|
+
validate_apikey!
|
58
|
+
first('AccountInfo', { :_id => apikey }){|res| self.account_info = res }
|
59
|
+
first('UsageInfo', { :_id => usage_id }){|res| self.usage_info = res }
|
60
|
+
env.trace('pre_process_end')
|
61
|
+
end
|
62
|
+
|
63
|
+
def post_process
|
64
|
+
env.trace('post_process_beg')
|
65
|
+
env.logger.info [account_info, usage_info].inspect
|
66
|
+
self.account_info ||= {}
|
67
|
+
self.usage_info ||= {}
|
68
|
+
|
69
|
+
inject_headers
|
70
|
+
|
71
|
+
EM.next_tick do
|
72
|
+
safely(env){ charge_usage }
|
73
|
+
end
|
74
|
+
|
75
|
+
safely(env, headers) do
|
76
|
+
check_apikey!
|
77
|
+
check_rate_limit!
|
78
|
+
|
79
|
+
env.trace('post_process_end')
|
80
|
+
[status, headers, body]
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
# ===========================================================================
|
85
|
+
|
86
|
+
def validate_apikey!
|
87
|
+
if apikey.to_s.empty?
|
88
|
+
raise MissingApikeyError
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def check_apikey!
|
93
|
+
unless account_info['valid'] == true
|
94
|
+
raise InvalidApikeyError
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def check_rate_limit!
|
99
|
+
return true if usage_info['calls'].to_f <= account_info['max_call_rate'].to_f
|
100
|
+
raise RateLimitExceededError
|
101
|
+
end
|
102
|
+
|
103
|
+
def charge_usage
|
104
|
+
update('UsageInfo', { :_id => usage_id },
|
105
|
+
{ '$inc' => { :calls => 1 } }, :upsert => true)
|
106
|
+
end
|
107
|
+
|
108
|
+
def inject_headers
|
109
|
+
headers.merge!({
|
110
|
+
'X-RateLimit-MaxRequests' => account_info['max_call_rate'].to_s,
|
111
|
+
'X-RateLimit-Requests' => usage_info['calls'].to_s,
|
112
|
+
'X-RateLimit-Reset' => timebin_end.to_s,
|
113
|
+
})
|
114
|
+
end
|
115
|
+
|
116
|
+
# ===========================================================================
|
117
|
+
|
118
|
+
def apikey
|
119
|
+
env.params['_apikey']
|
120
|
+
end
|
121
|
+
|
122
|
+
def usage_id
|
123
|
+
"#{apikey}-#{timebin}"
|
124
|
+
end
|
125
|
+
|
126
|
+
def timebin
|
127
|
+
@timebin ||= timebin_beg
|
128
|
+
end
|
129
|
+
|
130
|
+
def timebin_beg
|
131
|
+
((Time.now.to_i / TIMEBIN_SIZE).floor * TIMEBIN_SIZE)
|
132
|
+
end
|
133
|
+
|
134
|
+
def timebin_end
|
135
|
+
timebin_beg + TIMEBIN_SIZE
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
class AuthAndRateLimit < HttpLog
|
140
|
+
use Goliath::Rack::Tracer, 'X-Tracer'
|
141
|
+
use Goliath::Rack::Params # parse & merge query and body parameters
|
142
|
+
use Goliath::Rack::AsyncAroundware, AuthReceiver, 'api_auth_db'
|
143
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$:<< '../lib' << 'lib'
|
3
|
+
|
4
|
+
#
|
5
|
+
# A simple HTTP streaming API which returns a 200 response for any GET request
|
6
|
+
# and then emits numbers 1 through 10 in 1 second intervals using Chunked
|
7
|
+
# transfer encoding, and finally closes the connection.
|
8
|
+
#
|
9
|
+
# Chunked transfer streaming works transparently with both browsers and
|
10
|
+
# streaming consumers.
|
11
|
+
#
|
12
|
+
|
13
|
+
require 'goliath'
|
14
|
+
|
15
|
+
class ChunkedStreaming < Goliath::API
|
16
|
+
def on_close(env)
|
17
|
+
env.logger.info "Connection closed."
|
18
|
+
end
|
19
|
+
|
20
|
+
def response(env)
|
21
|
+
i = 0
|
22
|
+
pt = EM.add_periodic_timer(1) do
|
23
|
+
env.chunked_stream_send("#{i}\n")
|
24
|
+
i += 1
|
25
|
+
end
|
26
|
+
|
27
|
+
EM.add_timer(10) do
|
28
|
+
pt.cancel
|
29
|
+
|
30
|
+
env.chunked_stream_send("!! BOOM !!\n")
|
31
|
+
env.chunked_stream_close
|
32
|
+
end
|
33
|
+
|
34
|
+
headers = { 'Content-Type' => 'text/plain', 'X-Stream' => 'Goliath' }
|
35
|
+
chunked_streaming_response(200, headers)
|
36
|
+
end
|
37
|
+
end
|
data/examples/conf_test.rb
CHANGED
@@ -11,9 +11,7 @@ require 'goliath'
|
|
11
11
|
|
12
12
|
class ConfTest < Goliath::API
|
13
13
|
use Goliath::Rack::Params
|
14
|
-
use Goliath::Rack::
|
15
|
-
use Goliath::Rack::Formatters::JSON
|
16
|
-
use Goliath::Rack::Render
|
14
|
+
use Goliath::Rack::Render, 'json'
|
17
15
|
|
18
16
|
def options_parser(opts, options)
|
19
17
|
options[:test] = 0
|
@@ -0,0 +1,30 @@
|
|
1
|
+
import 'http_log'
|
2
|
+
|
3
|
+
environment(:development) do
|
4
|
+
|
5
|
+
config['api_auth_db'] = EventMachine::Synchrony::ConnectionPool.new(:size => 20) do
|
6
|
+
conn = EM::Mongo::Connection.new('localhost', 27017, 1, {:reconnect_in => 1})
|
7
|
+
conn.db('buzzkill_test')
|
8
|
+
end
|
9
|
+
|
10
|
+
# for demo purposes, some dummy accounts
|
11
|
+
timebin = ((Time.now.to_i / 3600).floor * 3600)
|
12
|
+
|
13
|
+
# This user's calls should all go through
|
14
|
+
config['api_auth_db'].collection('AccountInfo').save({
|
15
|
+
:_id => 'i_am_awesome', 'valid' => true, 'max_call_rate' => 1_000_000 })
|
16
|
+
|
17
|
+
# this user's account is disabled
|
18
|
+
config['api_auth_db'].collection('AccountInfo').save({
|
19
|
+
:_id => 'i_am_lame', 'valid' => false, 'max_call_rate' => 1_000 })
|
20
|
+
|
21
|
+
# this user has not been seen, but will very quickly hit their limit
|
22
|
+
config['api_auth_db'].collection('AccountInfo').save({
|
23
|
+
:_id => 'i_am_limited', 'valid' => true, 'max_call_rate' => 10 })
|
24
|
+
|
25
|
+
# fakes a user with a bunch of calls already made this hour -- two more = no yuo
|
26
|
+
config['api_auth_db'].collection('AccountInfo').save({
|
27
|
+
:_id => 'i_am_busy', 'valid' => true, 'max_call_rate' => 1_000 })
|
28
|
+
config['api_auth_db'].collection('UsageInfo').save({
|
29
|
+
:_id => "i_am_busy-#{timebin}", 'calls' => 999 })
|
30
|
+
end
|
data/examples/content_stream.rb
CHANGED
@@ -12,12 +12,10 @@ require 'goliath'
|
|
12
12
|
# rabbitmqctl set_permissions -p /test test ".*" ".*" ".*"
|
13
13
|
|
14
14
|
class ContentStream < Goliath::API
|
15
|
-
use Goliath::Rack::Formatters::JSON
|
16
15
|
use Goliath::Rack::Params
|
17
16
|
|
18
|
-
use Goliath::Rack::Render
|
17
|
+
use Goliath::Rack::Render, 'json'
|
19
18
|
use Goliath::Rack::Heartbeat
|
20
|
-
use Goliath::Rack::ValidationError
|
21
19
|
use Goliath::Rack::Validation::RequestMethod, %w(GET)
|
22
20
|
|
23
21
|
def on_close(env)
|
data/examples/echo.rb
CHANGED
@@ -4,18 +4,20 @@ $:<< '../lib' << 'lib'
|
|
4
4
|
require 'goliath'
|
5
5
|
require 'goliath/plugins/latency'
|
6
6
|
|
7
|
-
# Goliath uses multi-
|
7
|
+
# Goliath uses multi-json, so pick your favorite JSON serializer
|
8
8
|
# require 'json'
|
9
9
|
require 'yajl'
|
10
10
|
|
11
11
|
class Echo < Goliath::API
|
12
|
-
use Goliath::Rack::
|
12
|
+
use Goliath::Rack::Tracer # log trace statistics
|
13
13
|
use Goliath::Rack::DefaultMimeType # cleanup accepted media types
|
14
|
-
use Goliath::Rack::
|
15
|
-
use Goliath::Rack::
|
14
|
+
use Goliath::Rack::Render, 'json' # auto-negotiate response format
|
15
|
+
use Goliath::Rack::Params # parse & merge query and body parameters
|
16
16
|
use Goliath::Rack::Heartbeat # respond to /status with 200, OK (monitoring, etc)
|
17
|
-
use Goliath::Rack::ValidationError # catch and render validation errors
|
18
17
|
|
18
|
+
# If you are using Golaith version <=0.9.1 you need to Goliath::Rack::ValidationError
|
19
|
+
# to prevent the request from remaining open after an error occurs
|
20
|
+
#use Goliath::Rack::ValidationError
|
19
21
|
use Goliath::Rack::Validation::RequestMethod, %w(GET POST) # allow GET and POST requests only
|
20
22
|
use Goliath::Rack::Validation::RequiredParam, {:key => 'echo'} # must provide ?echo= query or body param
|
21
23
|
|
@@ -30,4 +32,4 @@ class Echo < Goliath::API
|
|
30
32
|
def response(env)
|
31
33
|
[200, {}, process_request]
|
32
34
|
end
|
33
|
-
end
|
35
|
+
end
|