slowweb 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md ADDED
@@ -0,0 +1,47 @@
1
+ Slow Web - An HTTP Request Governor
2
+ ===================================
3
+
4
+ ## DESCRIPTION
5
+
6
+ Slow Web is a way to limit the number of requests to a domain within a certain
7
+ period of time.
8
+
9
+ For example, the GitHub API only allows for 60 requests per minute. Slow Web can
10
+ monitor the number of calls to that domain and will sleep on the next request
11
+ that is over the limit.
12
+
13
+ Slow Web follows the rules of [Semantic Versioning](http://semver.org/).
14
+
15
+
16
+ ## RUNNING
17
+
18
+ To install Slow Web, simply install the gem:
19
+
20
+ $ [sudo] gem install slowweb
21
+
22
+ And specify the domain to limit.
23
+
24
+ require 'slowweb'
25
+ SlowWeb.limit('github.com', 10, 60)
26
+
27
+ This restricts the `github.com` domain to only allowing `10` requests every
28
+ `60` seconds (or one minute).
29
+
30
+
31
+ ## CONTRIBUTE
32
+
33
+ If you'd like to contribute to SlowWeb, start by forking the repository
34
+ on GitHub:
35
+
36
+ http://github.com/benbjohnson/slowweb
37
+
38
+ Then follow these steps to send your changes:
39
+
40
+ 1. Clone down your fork
41
+ 1. Create a topic branch to contain your change
42
+ 1. Code
43
+ 1. All code must have MiniTest::Unit test coverage.
44
+ 1. If you are adding new functionality, document it in the README
45
+ 1. If necessary, rebase your commits into logical chunks, without errors
46
+ 1. Push the branch up to GitHub
47
+ 1. Send me a pull request for your branch
data/lib/slow_web.rb ADDED
@@ -0,0 +1,58 @@
1
+ require 'slow_web/version'
2
+ require 'slow_web/limit'
3
+ require 'slow_web/ext/net_http'
4
+
5
+ class SlowWeb
6
+ ##############################################################################
7
+ # Static Initialization
8
+ ##############################################################################
9
+
10
+ # A look up of limits by host.
11
+ @limits = {}
12
+
13
+
14
+ ##############################################################################
15
+ # Static Methods
16
+ ##############################################################################
17
+
18
+ # Limits the number of requests that can occur within a specified number of
19
+ # seconds.
20
+ #
21
+ # @param [String] host the host to restrict.
22
+ # @param [Fixnum] count the number of requests that can occur within a time period.
23
+ # @param [Fixnum] period the number of seconds in the time period.
24
+ #
25
+ # @return [SlowWeb::Limit] the limit object.
26
+ def self.limit(host, count, period)
27
+ raise "Limit already exists for this host: #{host}" if @limits[host]
28
+
29
+ limit = Limit.new(host, count, period)
30
+ @limits[host] = limit
31
+ return limit
32
+ end
33
+
34
+ # Retrieves the limit object for a given host.
35
+ #
36
+ # @param [String] host the host associated with the limit.
37
+ #
38
+ # @return [SlowWeb::Limit] the limit object.
39
+ def self.get_limit(host)
40
+ return @limits[host]
41
+ end
42
+
43
+ # A flag stating if the limit for a given host has been exceeded.
44
+ #
45
+ # @param [String] host the host that is being limited.
46
+ #
47
+ # @return [Boolean] a flag stating if the limit has been exceeded.
48
+ def self.limit_exceeded?(host)
49
+ limit = @limits[host]
50
+ return !limit.nil? && limit.exceeded?
51
+ end
52
+
53
+
54
+ # Removes all limits.
55
+ def self.reset
56
+ @limits = {}
57
+ end
58
+ end
@@ -0,0 +1,25 @@
1
+ require 'net/http'
2
+ require 'net/https'
3
+
4
+ module Net
5
+ class HTTP
6
+ def request_with_slowweb(request, body = nil, &block)
7
+ host = self.address
8
+ limit = SlowWeb.get_limit(host)
9
+
10
+ # Wait until the request limit is no longer exceeded
11
+ while limit.exceeded?
12
+ sleep 1
13
+ end
14
+
15
+ # Add request to limiter
16
+ limit.add_request(request)
17
+
18
+ # Continue with the original request
19
+ request_without_slowweb(request, body, &block)
20
+ end
21
+
22
+ alias_method :request_without_slowweb, :request
23
+ alias_method :request, :request_with_slowweb
24
+ end
25
+ end
@@ -0,0 +1,75 @@
1
+ require 'slow_web/version'
2
+
3
+ class SlowWeb
4
+ class Limit
5
+ ############################################################################
6
+ # Constructor
7
+ ############################################################################
8
+
9
+ # @param [String] host the host to restrict.
10
+ # @param [Fixnum] count the number of requests that can occur within a time
11
+ # period.
12
+ # @param [Fixnum] period the number of seconds in the time period.
13
+ def initialize(host, count, period)
14
+ @host = host
15
+ @count = count
16
+ @period = period
17
+
18
+ @requests = []
19
+ end
20
+
21
+
22
+ ############################################################################
23
+ # Public Attributes
24
+ ############################################################################
25
+
26
+ # The host to restrict.
27
+ attr_accessor :host
28
+
29
+ # The number of requests that are allowed within the time period.
30
+ attr_accessor :count
31
+
32
+ # The number of seconds in the time period.
33
+ attr_accessor :period
34
+
35
+ # The number of requests that have occurred within the current period.
36
+ def current_request_count
37
+ normalize_requests()
38
+ return @requests.length
39
+ end
40
+
41
+ # A flag stating if the number of requests within the period has been met.
42
+ def exceeded?
43
+ return current_request_count >= count
44
+ end
45
+
46
+
47
+ ############################################################################
48
+ # Public Methods
49
+ ############################################################################
50
+
51
+ # Adds a request that is associated with this limit
52
+ #
53
+ # @param [Net::HTTPRequest] request the request associated with this limit.
54
+ def add_request(request)
55
+ @requests << {:obj => request, :time => Time.now}
56
+ normalize_requests()
57
+ nil
58
+ end
59
+
60
+
61
+ ############################################################################
62
+ # Private Methods
63
+ ############################################################################
64
+
65
+ private
66
+
67
+ # Removes all items in the request list that are outside of the current
68
+ # period.
69
+ def normalize_requests
70
+ @requests = @requests.find_all do |request|
71
+ (Time.now-request[:time]) < period
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,3 @@
1
+ class SlowWeb
2
+ VERSION = '0.1.0'
3
+ end
data/lib/slowweb.rb ADDED
@@ -0,0 +1 @@
1
+ require 'slow_web'
metadata ADDED
@@ -0,0 +1,104 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: slowweb
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - Ben Johnson
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-01-27 00:00:00 -07:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: rspec
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ hash: 31
30
+ segments:
31
+ - 2
32
+ - 4
33
+ - 0
34
+ version: 2.4.0
35
+ type: :development
36
+ version_requirements: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ name: fakeweb
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ hash: 27
46
+ segments:
47
+ - 1
48
+ - 3
49
+ - 0
50
+ version: 1.3.0
51
+ type: :development
52
+ version_requirements: *id002
53
+ description:
54
+ email:
55
+ - benbjohnson@yahoo.com
56
+ executables: []
57
+
58
+ extensions: []
59
+
60
+ extra_rdoc_files: []
61
+
62
+ files:
63
+ - lib/slow_web/ext/net_http.rb
64
+ - lib/slow_web/limit.rb
65
+ - lib/slow_web/version.rb
66
+ - lib/slow_web.rb
67
+ - lib/slowweb.rb
68
+ - README.md
69
+ has_rdoc: true
70
+ homepage: http://github.com/benbjohnson/slowweb
71
+ licenses: []
72
+
73
+ post_install_message:
74
+ rdoc_options: []
75
+
76
+ require_paths:
77
+ - lib
78
+ required_ruby_version: !ruby/object:Gem::Requirement
79
+ none: false
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ hash: 3
84
+ segments:
85
+ - 0
86
+ version: "0"
87
+ required_rubygems_version: !ruby/object:Gem::Requirement
88
+ none: false
89
+ requirements:
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ hash: 3
93
+ segments:
94
+ - 0
95
+ version: "0"
96
+ requirements: []
97
+
98
+ rubyforge_project:
99
+ rubygems_version: 1.4.1
100
+ signing_key:
101
+ specification_version: 3
102
+ summary: An HTTP Request Governor
103
+ test_files: []
104
+