slowweb 0.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.
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
+