rate_limit_mock_server 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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 2b9fb178144b8150f25d9b8c9bcbe5007157ff1fbd6017ba14f1ea757b3b9d59
4
+ data.tar.gz: e8519a29959d189058bffd6befdd8e3f85bf20f8f4b9089bc2582c7491e6f63a
5
+ SHA512:
6
+ metadata.gz: 0c1e2fac0497c9068e8e141040963d4761c58867d99de765a6c2a72b5aa259da195fc522a2d971f35946caf73c14763334378c1edc48b1a2f4c1d9ad5614771b
7
+ data.tar.gz: dd7ddd4668028866c2a8a5c6c3fe47d14d430179a97c5b15aefb000182207a8c7c30ee9eba4d863ff134dc2da03d7f4590b4e7508509a89aa5761e2ef26644a8
checksums.yaml.gz.sig ADDED
Binary file
data/.gitignore ADDED
@@ -0,0 +1,8 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ # Specify your gem's dependencies in rate_limit_mock_server.gemspec
6
+ gemspec
7
+
8
+ gem "rake", "~> 13.0"
9
+
10
+ gem "minitest", "~> 5.0"
data/Gemfile.lock ADDED
@@ -0,0 +1,34 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ rate_limit_mock_server (0.1.0)
5
+ sinatra
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ minitest (5.15.0)
11
+ mustermann (1.1.1)
12
+ ruby2_keywords (~> 0.0.1)
13
+ rack (2.2.3)
14
+ rack-protection (2.1.0)
15
+ rack
16
+ rake (13.0.6)
17
+ ruby2_keywords (0.0.5)
18
+ sinatra (2.1.0)
19
+ mustermann (~> 1.0)
20
+ rack (~> 2.2)
21
+ rack-protection (= 2.1.0)
22
+ tilt (~> 2.0)
23
+ tilt (2.0.10)
24
+
25
+ PLATFORMS
26
+ x86_64-linux
27
+
28
+ DEPENDENCIES
29
+ minitest (~> 5.0)
30
+ rake (~> 13.0)
31
+ rate_limit_mock_server!
32
+
33
+ BUNDLED WITH
34
+ 2.2.20
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2022 Sammy Henningsson
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,66 @@
1
+ # RateLimitMockServer
2
+
3
+ Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/rate_limit_mock_server`. To experiment with that code, run `bin/console` for an interactive prompt.
4
+
5
+ TODO: Delete this and the text above, and describe your gem
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'rate_limit_mock_server'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle install
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install rate_limit_mock_server
22
+
23
+ ## Usage
24
+ To start the server from code, do this:
25
+ ```ruby
26
+ require 'rate_limit_mock_server`
27
+
28
+ # Start the server on port 4567 and block the current thread
29
+ RateLimitMockServer.start
30
+ ```
31
+
32
+ Note, If you don't want the server to block the current thread, you can instead spawn a new thread for the server.
33
+ ```ruby
34
+ require 'rate_limit_mock_server`
35
+
36
+ thread = Thread.new do
37
+ # Start the server on port 4567 and block the current thread
38
+ RateLimitMockServer.start
39
+ end
40
+
41
+ # Add some sleep to allow the server to be started
42
+ sleep(2)
43
+
44
+ do_some
45
+ other_stuff
46
+ # ...
47
+
48
+ RateLimitMockServer.quit!
49
+ thread.join
50
+ ```
51
+
52
+ The server can be stopped by either `RateLimitMockServer.quit!` or by sending a GET to `http://localhost:4567/quit`.
53
+
54
+ ## Development
55
+
56
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
57
+
58
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
59
+
60
+ ## Contributing
61
+
62
+ Bug reports and pull requests are welcome on GitHub at https://github.com/sammyhenningsson/rate_limit_mock_server.
63
+
64
+ ## License
65
+
66
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rake/testtask"
5
+
6
+ Rake::TestTask.new(:test) do |t|
7
+ t.libs << "test"
8
+ t.libs << "lib"
9
+ t.test_files = FileList["test/**/*_test.rb"]
10
+ end
11
+
12
+ task default: :test
data/bin/console ADDED
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "bundler/setup"
5
+ require "rate_limit_mock_server"
6
+
7
+ # You can add fixtures and/or initialization code here to make experimenting
8
+ # with your gem easier. You can also use a different console, if you like.
9
+
10
+ # (If you use this, don't forget to add pry to your Gemfile!)
11
+ # require "pry"
12
+ # Pry.start
13
+
14
+ require "irb"
15
+ IRB.start(__FILE__)
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ $: << File.expand_path('../lib/', __dir__)
5
+
6
+ require 'rate_limit_mock_server'
7
+
8
+ RateLimitMockServer.start
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,22 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIDjjCCAnagAwIBAgIBATANBgkqhkiG9w0BAQsFADBGMRowGAYDVQQDDBFzYW1t
3
+ eS5oZW5uaW5nc3NvbjETMBEGCgmSJomT8ixkARkWA2hleTETMBEGCgmSJomT8ixk
4
+ ARkWA2NvbTAeFw0yMjA0MDYxOTAxMDJaFw0yNDA2MTQxOTAxMDJaMEYxGjAYBgNV
5
+ BAMMEXNhbW15Lmhlbm5pbmdzc29uMRMwEQYKCZImiZPyLGQBGRYDaGV5MRMwEQYK
6
+ CZImiZPyLGQBGRYDY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
7
+ r5IMLWZ/KG5wnpVrbWsgdQaxwS1Ct2/IGrEUbWzZOA8wC/hFurB0lU9ruSO1sLOy
8
+ UAOVQTWiu7YL6twmwy1UZfTa6Qwg8dPU6NPLLT8QyoupLLdZ5EjwA/INLEJVt76H
9
+ kEx/fNmdh911HoB4buWfT1PU/+1f72VMxz4j4NbV9SVCBjjwI1RrK+0lHrWy9e9c
10
+ yuEuGLb1JCKDWqYfpmh7bb8mAf6bYmSw+d1jkSneCp8NzoibC7a8a+YYSskPrcUH
11
+ RdD/BvhZUfiXuwdBJN8oOnxIiYK3XGo2AjKPDnvxkbaB4Yuidy7GAOttD9QUgnXW
12
+ UNl3i8t68yGcjFNImk+vZwIDAQABo4GGMIGDMAkGA1UdEwQCMAAwCwYDVR0PBAQD
13
+ AgSwMB0GA1UdDgQWBBS6SOPUJ3Z5rog4cMtl7TKbOzaNaTAkBgNVHREEHTAbgRlz
14
+ YW1teS5oZW5uaW5nc3NvbkBoZXkuY29tMCQGA1UdEgQdMBuBGXNhbW15Lmhlbm5p
15
+ bmdzc29uQGhleS5jb20wDQYJKoZIhvcNAQELBQADggEBAEcMp9iEErm3laanowRC
16
+ xrvBR1uUyb73oTNPE2A3vknsLhJ/4tpJPcPkxgvh2P3bdwP//JHU9EYRKHY22R+7
17
+ jS4iSTbD7PQr3xdD5cA9j36562Wmac9uNTxJ9amtTcdmQqSDo9NcECFn3IhD+ljf
18
+ knR95SHUDD4FNQGLzrTTB8daYjO4Dro7vqOfZGcgk26uqWLrgcvdfzFyhZ8XwwzO
19
+ Q3eW5l4nbscDR/o3jV8WX5Y+Gm2YptuRHWe2S9YI5YkHXtDzPDREv0GRJmaRmGCz
20
+ hDgtXQiNH/WrZi6kriR8NgvZIZobYz4qKW9nAuVEa3qqegirIKi6BtcHr1pWrWt1
21
+ FDc=
22
+ -----END CERTIFICATE-----
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rate_limit_mock_server/rate_limit_error'
4
+
5
+ module RateLimitMockServer
6
+ class Counter
7
+ class << self
8
+ def for(key, rps_limit)
9
+ counters[key] ||= Counter.new(rps_limit)
10
+ counters[key]
11
+ end
12
+
13
+ private
14
+
15
+ def counters
16
+ @counters ||= {}
17
+ end
18
+ end
19
+
20
+ def initialize(rps_limit)
21
+ @rps_limit = rps_limit
22
+ @window = []
23
+ end
24
+
25
+ def current
26
+ size
27
+ end
28
+
29
+ def increment
30
+ window << Time.now.to_f
31
+ window.shift while delta && 1.0 < delta
32
+ window.last
33
+ end
34
+
35
+ def increment!
36
+ increment
37
+ return if current <= rps_limit
38
+
39
+ raise RateLimitError.new(rate: current, limit: rps_limit)
40
+ end
41
+
42
+ private
43
+
44
+ def size
45
+ window.size
46
+ end
47
+
48
+ def delta
49
+ return if size < 2
50
+
51
+ window.last - window.first
52
+ end
53
+
54
+ attr_reader :rps_limit, :window
55
+ end
56
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RateLimitMockServer
4
+ class RateLimitError < StandardError
5
+ MESSAGE_TEMPLATE = 'Received requests @%0.1f rps! Max allowed: %d rps'
6
+
7
+ attr_reader :rate, :limit
8
+
9
+ def initialize(rate:, limit:)
10
+ @rate = rate
11
+ @limit = limit
12
+
13
+ super format(MESSAGE_TEMPLATE, rate, limit)
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'sinatra/base'
4
+ require 'rate_limit_mock_server/counter'
5
+ require 'rate_limit_mock_server/rate_limit_error'
6
+
7
+ module RateLimitMockServer
8
+ class Server < Sinatra::Base
9
+ set :show_exceptions, false
10
+
11
+ DEFAULT_RPS_LIMIT = 4
12
+
13
+ error do |err|
14
+ [500, "Something is bork: #{err.message}"]
15
+ end
16
+
17
+ error RateLimitError do |error|
18
+ [429, "Current rate for #{request.path_info}: #{error.rate} (allowed #{error.limit})\n"]
19
+ end
20
+
21
+ get '/quit' do
22
+ self.class.quit!
23
+ end
24
+
25
+ get '/limit_test' do
26
+ raise RateLimitError.new(rate: 1, limit: 0)
27
+ end
28
+
29
+ get %r{/(\d+)?} do
30
+ counter.increment!
31
+
32
+ [200, "Current rate for #{request.path_info}: #{counter.current}\n"]
33
+ end
34
+
35
+ def rps_limit
36
+ params['captures']&.first&.to_i || DEFAULT_RPS_LIMIT
37
+ end
38
+
39
+ def counter
40
+ Counter.for(request.path_info, rps_limit)
41
+ end
42
+
43
+ def user_agent
44
+ request.env['HTTP_USER_AGENT']
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RateLimitMockServer
4
+ VERSION = '0.1.0'
5
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rate_limit_mock_server/version'
4
+ require 'rate_limit_mock_server/server'
5
+
6
+ module RateLimitMockServer
7
+ def self.start
8
+ Server.run!
9
+ end
10
+
11
+ def self.quit!
12
+ Server.quit!
13
+ end
14
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'lib/rate_limit_mock_server/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'rate_limit_mock_server'
7
+ spec.version = RateLimitMockServer::VERSION
8
+ spec.authors = ['Sammy Henningsson']
9
+ spec.email = ['sammy.henningsson@hey.com']
10
+
11
+ spec.summary = 'A mock server for testing out rate limiting in clients'
12
+ spec.homepage = 'https://github.com/sammyhenningsson/rate_limit_mock_server'
13
+ spec.license = 'MIT'
14
+ spec.required_ruby_version = '>= 2.5.0'
15
+
16
+ spec.metadata['homepage_uri'] = spec.homepage
17
+ spec.metadata['source_code_uri'] = spec.homepage
18
+
19
+ spec.cert_chain = ['certs/sammyhenningsson.pem']
20
+ spec.signing_key = File.expand_path('~/.ssh/gem-private_key.pem')
21
+
22
+ # Specify which files should be added to the gem when it is released.
23
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
24
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
25
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{\A(?:test|spec|features)/}) }
26
+ end
27
+ spec.bindir = 'bin'
28
+ spec.executables = ['rate_limit_mock_server']
29
+ spec.require_paths = ['lib']
30
+
31
+ spec.add_runtime_dependency 'sinatra'
32
+ spec.add_development_dependency 'minitest'
33
+ end
data.tar.gz.sig ADDED
@@ -0,0 +1 @@
1
+ *��쐿�=#|��k��2��m v%�  �(O�Y�l:�[�8� ��N,�z|9n��2Rsy�j!�Μ���\߿N37�Fc�ZܓF��ywP��tO| ����&Q�Zt��M�m1��ku��z,i�T�y�%e$`��n���4�"��i���‘N]���ݷ�#/��vU�
metadata ADDED
@@ -0,0 +1,113 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rate_limit_mock_server
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Sammy Henningsson
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain:
11
+ - |
12
+ -----BEGIN CERTIFICATE-----
13
+ MIIDjjCCAnagAwIBAgIBATANBgkqhkiG9w0BAQsFADBGMRowGAYDVQQDDBFzYW1t
14
+ eS5oZW5uaW5nc3NvbjETMBEGCgmSJomT8ixkARkWA2hleTETMBEGCgmSJomT8ixk
15
+ ARkWA2NvbTAeFw0yMjA0MDYxOTAxMDJaFw0yNDA2MTQxOTAxMDJaMEYxGjAYBgNV
16
+ BAMMEXNhbW15Lmhlbm5pbmdzc29uMRMwEQYKCZImiZPyLGQBGRYDaGV5MRMwEQYK
17
+ CZImiZPyLGQBGRYDY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
18
+ r5IMLWZ/KG5wnpVrbWsgdQaxwS1Ct2/IGrEUbWzZOA8wC/hFurB0lU9ruSO1sLOy
19
+ UAOVQTWiu7YL6twmwy1UZfTa6Qwg8dPU6NPLLT8QyoupLLdZ5EjwA/INLEJVt76H
20
+ kEx/fNmdh911HoB4buWfT1PU/+1f72VMxz4j4NbV9SVCBjjwI1RrK+0lHrWy9e9c
21
+ yuEuGLb1JCKDWqYfpmh7bb8mAf6bYmSw+d1jkSneCp8NzoibC7a8a+YYSskPrcUH
22
+ RdD/BvhZUfiXuwdBJN8oOnxIiYK3XGo2AjKPDnvxkbaB4Yuidy7GAOttD9QUgnXW
23
+ UNl3i8t68yGcjFNImk+vZwIDAQABo4GGMIGDMAkGA1UdEwQCMAAwCwYDVR0PBAQD
24
+ AgSwMB0GA1UdDgQWBBS6SOPUJ3Z5rog4cMtl7TKbOzaNaTAkBgNVHREEHTAbgRlz
25
+ YW1teS5oZW5uaW5nc3NvbkBoZXkuY29tMCQGA1UdEgQdMBuBGXNhbW15Lmhlbm5p
26
+ bmdzc29uQGhleS5jb20wDQYJKoZIhvcNAQELBQADggEBAEcMp9iEErm3laanowRC
27
+ xrvBR1uUyb73oTNPE2A3vknsLhJ/4tpJPcPkxgvh2P3bdwP//JHU9EYRKHY22R+7
28
+ jS4iSTbD7PQr3xdD5cA9j36562Wmac9uNTxJ9amtTcdmQqSDo9NcECFn3IhD+ljf
29
+ knR95SHUDD4FNQGLzrTTB8daYjO4Dro7vqOfZGcgk26uqWLrgcvdfzFyhZ8XwwzO
30
+ Q3eW5l4nbscDR/o3jV8WX5Y+Gm2YptuRHWe2S9YI5YkHXtDzPDREv0GRJmaRmGCz
31
+ hDgtXQiNH/WrZi6kriR8NgvZIZobYz4qKW9nAuVEa3qqegirIKi6BtcHr1pWrWt1
32
+ FDc=
33
+ -----END CERTIFICATE-----
34
+ date: 2022-04-06 00:00:00.000000000 Z
35
+ dependencies:
36
+ - !ruby/object:Gem::Dependency
37
+ name: sinatra
38
+ requirement: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: '0'
43
+ type: :runtime
44
+ prerelease: false
45
+ version_requirements: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: '0'
50
+ - !ruby/object:Gem::Dependency
51
+ name: minitest
52
+ requirement: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: '0'
57
+ type: :development
58
+ prerelease: false
59
+ version_requirements: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: '0'
64
+ description:
65
+ email:
66
+ - sammy.henningsson@hey.com
67
+ executables:
68
+ - rate_limit_mock_server
69
+ extensions: []
70
+ extra_rdoc_files: []
71
+ files:
72
+ - ".gitignore"
73
+ - Gemfile
74
+ - Gemfile.lock
75
+ - LICENSE.txt
76
+ - README.md
77
+ - Rakefile
78
+ - bin/console
79
+ - bin/rate_limit_mock_server
80
+ - bin/setup
81
+ - certs/sammyhenningsson.pem
82
+ - lib/rate_limit_mock_server.rb
83
+ - lib/rate_limit_mock_server/counter.rb
84
+ - lib/rate_limit_mock_server/rate_limit_error.rb
85
+ - lib/rate_limit_mock_server/server.rb
86
+ - lib/rate_limit_mock_server/version.rb
87
+ - rate_limit_mock_server.gemspec
88
+ homepage: https://github.com/sammyhenningsson/rate_limit_mock_server
89
+ licenses:
90
+ - MIT
91
+ metadata:
92
+ homepage_uri: https://github.com/sammyhenningsson/rate_limit_mock_server
93
+ source_code_uri: https://github.com/sammyhenningsson/rate_limit_mock_server
94
+ post_install_message:
95
+ rdoc_options: []
96
+ require_paths:
97
+ - lib
98
+ required_ruby_version: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: 2.5.0
103
+ required_rubygems_version: !ruby/object:Gem::Requirement
104
+ requirements:
105
+ - - ">="
106
+ - !ruby/object:Gem::Version
107
+ version: '0'
108
+ requirements: []
109
+ rubygems_version: 3.3.6
110
+ signing_key:
111
+ specification_version: 4
112
+ summary: A mock server for testing out rate limiting in clients
113
+ test_files: []
metadata.gz.sig ADDED
Binary file