geo_redirect 0.4 → 0.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: cc53d6e770a29fb9a25ad601803bc220e9de5595
4
- data.tar.gz: ce7e9473fb1a032807256e361c72811ef06856c8
3
+ metadata.gz: 82d54b2c77fe8c90bc209fd0adcb1b01815a1cad
4
+ data.tar.gz: 3928b90c6060facb3365babf3b9222da9e31fec3
5
5
  SHA512:
6
- metadata.gz: 4b82b53e72d1ac2f59562433e6f4f30033115692484049253991507aa3871c4030751f382020976fda8b945425c9df93d7957a58534fa1f065b5e7f13b9b998e
7
- data.tar.gz: 467773cacba033e14b1f0ee811fc420095e9f650d7239db8caf10a6bc0ebf4948fb967a5fde8e6096b8d8223624d08d4c732047e2194efa5198ab85dbf8c5326
6
+ metadata.gz: 7571edc045457947731740163892ea1ce6b4ce957167d87f564eb605154aadb3823a03fc44d1e665491a843ed8c7c3ddc5d8d8c7732a4e22f230927b1f85e931
7
+ data.tar.gz: 5b802714a2b3b312ec50b43bf37052717083ab45b3f8fb373f2db979a19ce2dff39ef8fb54e57e534887d4ed432c62103d5b3c1fa83fa74e2aec75194e685003
data/.gitignore CHANGED
@@ -15,3 +15,6 @@ spec/reports
15
15
  test/tmp
16
16
  test/version_tmp
17
17
  tmp
18
+ .idea
19
+ .ruby-gemset
20
+ .ruby-version
data/.rubocop.yml CHANGED
@@ -7,10 +7,29 @@ Metrics/MethodLength:
7
7
  Max: 15
8
8
 
9
9
  Metrics/ClassLength:
10
- Max: 154
10
+ Max: 170
11
11
 
12
12
  Style/RescueModifier:
13
13
  Enabled: false
14
14
 
15
15
  Style/RegexpLiteral:
16
16
  Enabled: false
17
+
18
+ RSpec/InstanceVariable:
19
+ Enabled: false
20
+
21
+ Style/BlockDelimiters:
22
+ Exclude:
23
+ - 'spec/**/*'
24
+
25
+ Style/BlockEndNewline:
26
+ Exclude:
27
+ - 'spec/**/*'
28
+
29
+ Style/MultilineBlockLayout:
30
+ Exclude:
31
+ - 'spec/**/*'
32
+
33
+ RSpec/DescribeClass:
34
+ Exclude:
35
+ - 'spec/lib/tasks/*'
data/.travis.yml CHANGED
@@ -1,4 +1,13 @@
1
+ sudo: false
2
+ cache: bundler
1
3
  language: ruby
2
4
  rvm:
3
- - 2.0.0
4
5
  - 1.9.3
6
+ - 2.0.0
7
+ - 2.1
8
+ - 2.2
9
+ - jruby-19mode
10
+ - jruby-9.0.0.0
11
+ before_install: gem update --remote bundler
12
+ script:
13
+ - bundle exec rake ci
data/README.md CHANGED
@@ -90,6 +90,22 @@ and unzip it into `db/` in your project, **or** you could use the following
90
90
  It'd be a good idea to use this task on your (Capistrano or whatever) deployment
91
91
  scripts.
92
92
 
93
+ ### Excluding certain URLs from redirection
94
+
95
+ You may want certain URLs in your app to be ignored by GeoRedirect and to
96
+ respond normally to *all* incoming requests. You can configure this with the
97
+ `:exclude` option.
98
+
99
+ Rails.application.middleware.use GeoRedirect::Middleware, exclude: '/excluded_path'
100
+
101
+ The value of the option can be a string or an array of strings which represent
102
+ the path(s) to be excluded. Note that each string must be an exact match of the
103
+ path portion of the URL, including the leading slash.
104
+
105
+ Rails.application.middleware.use GeoRedirect::Middleware, exclude: '/exclude'
106
+
107
+ will match `www.myapp.com/exclude` but not `www.myapp.com/other/path/exclude`
108
+
93
109
  ### Custom paths
94
110
 
95
111
  The default paths for these files are:
data/Rakefile CHANGED
@@ -1,6 +1,9 @@
1
1
  require 'bundler/gem_tasks'
2
2
  require 'rspec/core/rake_task'
3
+ require 'rubocop/rake_task'
3
4
 
4
5
  RSpec::Core::RakeTask.new(:spec)
6
+ RuboCop::RakeTask.new(:style)
5
7
 
6
- task default: [:spec]
8
+ task ci: [:spec, :style]
9
+ task default: [:ci]
data/geo_redirect.gemspec CHANGED
@@ -4,21 +4,24 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
  require 'geo_redirect/version'
5
5
 
6
6
  Gem::Specification.new do |gem|
7
- gem.name = 'geo_redirect'
8
- gem.version = GeoRedirect::VERSION
9
- gem.authors = ['Sagie Maoz']
10
- gem.email = ['sagie@waze.com']
11
- gem.description = 'Geo-location based redirector'
12
- gem.summary = 'Rack middleware to redirect clients to hostnames based on geo-location'
13
- gem.homepage = ''
7
+ gem.name = 'geo_redirect'
8
+ gem.version = GeoRedirect::VERSION
9
+ gem.authors = ['Sagie Maoz']
10
+ gem.email = ['sagie@waze.com']
11
+ gem.description = 'Geo-location based redirector'
12
+ gem.summary =
13
+ 'Rack middleware to redirect clients to hostnames based on geo-location'
14
+ gem.homepage = ''
14
15
 
15
16
  gem.add_dependency 'rake'
16
17
  gem.add_dependency 'geoip'
17
18
 
18
- gem.add_development_dependency 'rspec', '~> 3.1.0'
19
- gem.add_development_dependency 'rack', '~> 1.6.0'
20
- gem.add_development_dependency 'rack-test', '~> 0.6.3'
21
- gem.add_development_dependency 'simplecov', '~> 0.9.1'
19
+ gem.add_development_dependency 'rspec', '~> 3.1.0'
20
+ gem.add_development_dependency 'rack', '~> 1.6.0'
21
+ gem.add_development_dependency 'rack-test', '~> 0.6.3'
22
+ gem.add_development_dependency 'simplecov', '~> 0.9.1'
23
+ gem.add_development_dependency 'rubocop', '~> 0.33.0'
24
+ gem.add_development_dependency 'rubocop-rspec', '~> 1.3.0'
22
25
 
23
26
  gem.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
24
27
  gem.executables = gem.files.grep(%r{^bin/}).map { |f| File.basename(f) }
@@ -7,14 +7,15 @@ module GeoRedirect
7
7
 
8
8
  def initialize(app, options = {})
9
9
  # Some defaults
10
- options[:db] ||= DEFAULT_DB_PATH
10
+ options[:db] ||= DEFAULT_DB_PATH
11
11
  options[:config] ||= DEFAULT_CONFIG_PATH
12
12
 
13
13
  @app = app
14
14
 
15
- @logger = init_logger(options[:logfile]) if options[:logfile]
16
- @db = init_db(options[:db])
17
- @config = init_config(options[:config])
15
+ @logger = init_logger(options[:logfile]) if options[:logfile]
16
+ @db = init_db(options[:db])
17
+ @config = init_config(options[:config])
18
+ @excludes = Array(options[:exclude])
18
19
 
19
20
  log 'Initialized middleware'
20
21
  end
@@ -60,9 +61,17 @@ module GeoRedirect
60
61
 
61
62
  def skip_redirect?
62
63
  url = URI.parse(@request.url)
64
+ query_includes_skip_geo?(url) || path_excluded?(url)
65
+ end
66
+
67
+ def query_includes_skip_geo?(url)
63
68
  Rack::Utils.parse_query(url.query).key? 'skip_geo'
64
69
  end
65
70
 
71
+ def path_excluded?(url)
72
+ @excludes.any? { |exclude| url.path == exclude }
73
+ end
74
+
66
75
  def handle_force
67
76
  url = URI.parse(@request.url)
68
77
  host = host_by_hostname(url.host)
@@ -173,10 +182,10 @@ module GeoRedirect
173
182
  ip = request_ip
174
183
  log "Handling GeoIP lookup: IP #{ip}"
175
184
 
176
- res = @db.country(ip)
177
- code = res[:country_code]
185
+ country = @db.country(ip)
186
+ code = country[:country_code]
178
187
 
179
- res[:country_code2] unless code.nil? || code.zero?
188
+ country[:country_code2] unless code.nil? || code.zero?
180
189
  end
181
190
 
182
191
  def redirect_url(hostname)
@@ -199,7 +208,7 @@ module GeoRedirect
199
208
  def should_redirect?(hostname, same_host)
200
209
  return true if hostname.nil? || same_host
201
210
 
202
- hostname_ends_with = %r{#{hostname.gsub(".", "\.")}$}
211
+ hostname_ends_with = %r{#{hostname.tr('.', '\.')}$}
203
212
  (@request.host =~ hostname_ends_with).nil?
204
213
  end
205
214
  end
@@ -1,3 +1,3 @@
1
1
  module GeoRedirect
2
- VERSION = '0.4'
2
+ VERSION = '0.5'
3
3
  end
@@ -0,0 +1,267 @@
1
+ require 'spec_helper'
2
+ require 'tempfile'
3
+ require 'logger'
4
+
5
+ describe GeoRedirect::Middleware do
6
+ include GeoRedirect::Support
7
+ include Rack::Test::Methods
8
+
9
+ let(:config) { YAML.load_file(fixture_path('config.yml')) }
10
+
11
+ describe '#load_config' do
12
+ it 'reads a config file' do
13
+ mock_app
14
+ expect(@app.config).to eq(config)
15
+ end
16
+
17
+ it 'errors on not-found config file' do
18
+ mock_app config: nonexisting_file_path
19
+ log_should_include('ERROR')
20
+ log_should_include('Could not load GeoRedirect config YML file')
21
+ end
22
+
23
+ it 'errors on a mal-formatted config file' do
24
+ mock_app config: fixture_path('config.bad.yml')
25
+ log_should_include('ERROR')
26
+ log_should_include('Could not load GeoRedirect config YML file')
27
+ end
28
+ end
29
+
30
+ describe '#load_db' do
31
+ it 'reads a db file' do
32
+ mock_app
33
+ expect(@app.db).to be_a(GeoIP)
34
+ end
35
+
36
+ it 'errors on not-found db file' do
37
+ mock_app db: nonexisting_file_path
38
+ log_should_include('ERROR')
39
+ log_should_include('Could not load GeoIP database file.')
40
+ end
41
+
42
+ # this example is disabled, as it seems that
43
+ # GeoIP does not let me know if a db file is proper.
44
+ # it "errors on mal-formatted db file" do
45
+ # pending "GeoIP does not raise on bad files"
46
+ # mock_app :db => fixture_path("config.yml")
47
+ # log_should_include("ERROR")
48
+ # log_should_include("Could not load GeoIP database file.")
49
+ # end
50
+ end
51
+
52
+ describe '#log' do
53
+ describe 'with valid logfile path' do
54
+ before { mock_app }
55
+
56
+ it 'initiates a log file' do
57
+ expect(@app.instance_variable_get(:"@logger")).to be_kind_of Logger
58
+ end
59
+
60
+ it 'prints to log file' do
61
+ message = 'Testing GeoRedirect logger'
62
+ @app.send(:log, [message])
63
+ log_should_include(message)
64
+ end
65
+ end
66
+
67
+ it 'ignores invalid logfile path' do
68
+ mock_app logfile: '/no_such_file'
69
+ expect(@app.instance_variable_get(:"@logger")).to be_nil
70
+ end
71
+ end
72
+
73
+ describe '#host_by_country' do
74
+ before { mock_app }
75
+ subject { @app.host_by_country(country) }
76
+
77
+ context 'when country is valid' do
78
+ let(:country) { 'US' }
79
+ it { is_expected.to eq(:us) }
80
+ end
81
+
82
+ context 'when country is invalid' do
83
+ let(:country) { 'WHATEVER' }
84
+ it { is_expected.to eq(:default) }
85
+ end
86
+ end
87
+
88
+ describe 'host_by_hostname' do
89
+ before { mock_app }
90
+ subject { @app.host_by_hostname(hostname) }
91
+
92
+ context 'when hostname is valid' do
93
+ let(:hostname) { 'biz.waze.co.il' }
94
+ it { is_expected.to eq(:il) }
95
+ end
96
+
97
+ context 'when hostname is invalid' do
98
+ let(:hostname) { 'something.else.org' }
99
+ it { is_expected.to eq(:default) }
100
+ end
101
+ end
102
+
103
+ describe 'redirect logic' do
104
+ let(:app_options) { {} }
105
+ let(:request_ip) { '5.5.5.5' }
106
+ let(:request_path) { '/' }
107
+ let(:request_args) { {} }
108
+ let(:request_session) { nil }
109
+ let(:country) { { country_code: 5, country_code2: country_code } }
110
+ let(:env) do
111
+ {
112
+ 'REMOTE_ADDR' => request_ip,
113
+ 'HTTP_HOST' => 'biz.waze.co.il',
114
+ 'rack.session' => {
115
+ 'geo_redirect' => request_session,
116
+ 'geo_redirect.country' => (country_code if request_session)
117
+ }
118
+ }
119
+ end
120
+
121
+ before do
122
+ mock_app(app_options)
123
+ allow(@app.db).to receive(:country).with(request_ip).and_return(country)
124
+ get request_path, request_args, env
125
+ end
126
+
127
+ subject(:session) { last_request.env['rack.session'] }
128
+ subject { last_response }
129
+
130
+ matcher :redirect_to do |expected|
131
+ match do |response|
132
+ url_scheme = last_request.env['rack.url_scheme']
133
+ url = "#{url_scheme}://#{config[expected][:host]}"
134
+
135
+ response.body.include?('Moved Permanently') &&
136
+ response.status == 301 &&
137
+ response.headers['Location'].start_with?(url)
138
+ end
139
+ end
140
+
141
+ matcher :not_redirect do
142
+ match do |response|
143
+ response.body.include?('Hello world!') &&
144
+ response.ok?
145
+ end
146
+ end
147
+
148
+ matcher :remember do |host|
149
+ match do
150
+ session && session['geo_redirect'] == host
151
+ end
152
+ end
153
+
154
+ matcher :remember_country do |country|
155
+ match do
156
+ session && session['geo_redirect.country'] == country
157
+ end
158
+ end
159
+
160
+ describe 'without session memory' do
161
+ describe 'for a foreign source' do
162
+ let(:country_code) { 'US' }
163
+ it { is_expected.to redirect_to :us }
164
+ it { is_expected.to remember :us }
165
+ it { is_expected.to remember_country 'US' }
166
+ end
167
+
168
+ describe 'for a local source' do
169
+ let(:country_code) { 'IL' }
170
+ it { is_expected.to not_redirect }
171
+ it { is_expected.to remember :il }
172
+ it { is_expected.to remember_country 'IL' }
173
+ end
174
+
175
+ describe 'for an unknown source' do
176
+ let(:country_code) { 'SOMEWHERE OVER THE RAINBOW' }
177
+ it { is_expected.to redirect_to :default }
178
+ it { is_expected.to remember :default }
179
+ it { is_expected.to remember_country 'SOMEWHERE OVER THE RAINBOW' }
180
+ end
181
+ end
182
+
183
+ describe 'with valid session memory' do
184
+ let(:request_session) { :default }
185
+ let(:country_code) { 'US' }
186
+ it { is_expected.to redirect_to :default }
187
+ it { is_expected.to remember :default }
188
+ it { is_expected.to remember_country 'US' }
189
+ end
190
+
191
+ describe 'with invalid session memory' do
192
+ let(:request_session) { 'foo' }
193
+ let(:country_code) { 'US' }
194
+
195
+ it 'removes invalid session data' do
196
+ expect(session['geo_redirect']).not_to eq('foo')
197
+ end
198
+
199
+ it { is_expected.to redirect_to :us }
200
+ it { is_expected.to remember :us }
201
+ it { is_expected.to remember_country 'US' }
202
+ end
203
+
204
+ describe 'with forced redirect flag' do
205
+ let(:country_code) { 'US' }
206
+ let(:request_args) { { redirect: 1 } }
207
+
208
+ it { is_expected.to redirect_to :il }
209
+ it 'rewrites the flag out' do
210
+ expect(subject.headers['Location']).not_to include('redirect=1')
211
+ end
212
+
213
+ it { is_expected.to remember :il }
214
+ it { is_expected.to remember_country nil }
215
+ end
216
+
217
+ describe 'with skip flag' do
218
+ let(:country_code) { 'US' }
219
+ let(:request_args) { { skip_geo: true } }
220
+ it { is_expected.to not_redirect }
221
+ it { is_expected.to remember nil }
222
+ it { is_expected.to remember_country nil }
223
+ end
224
+
225
+ describe 'with no recognizable IP' do
226
+ let(:country_code) { nil }
227
+ it { is_expected.to not_redirect }
228
+ it { is_expected.to remember nil }
229
+ it { is_expected.to remember_country nil }
230
+ end
231
+
232
+ describe 'with an exclude option set' do
233
+ let(:app_options) { { exclude: ['/exclude_me', '/exclude_me/too'] } }
234
+
235
+ context 'when the request URL matches one of the excluded paths' do
236
+ let(:country_code) { 'US' }
237
+ let(:request_path) { '/exclude_me?query_param=value' }
238
+
239
+ it { is_expected.to not_redirect }
240
+ it { is_expected.to remember nil }
241
+ it { is_expected.to remember_country nil }
242
+ end
243
+
244
+ context 'when the request URL does not match one of the excluded paths' do
245
+ let(:country_code) { 'US' }
246
+ let(:request_path) { '/dont_exclude_me?query_param=value' }
247
+
248
+ it { is_expected.to redirect_to :us }
249
+ it { is_expected.to remember :us }
250
+ it { is_expected.to remember_country 'US' }
251
+ end
252
+ end
253
+
254
+ describe 'with a single excluded path' do
255
+ let(:app_options) { { exclude: '/exclude_me' } }
256
+
257
+ context 'when the request URL matches one of the excluded paths' do
258
+ let(:country_code) { 'US' }
259
+ let(:request_path) { '/exclude_me?query_param=value' }
260
+
261
+ it { is_expected.to not_redirect }
262
+ it { is_expected.to remember nil }
263
+ it { is_expected.to remember_country nil }
264
+ end
265
+ end
266
+ end
267
+ end
@@ -0,0 +1,11 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'geo_redirect:fetch_db' do
4
+ include_context 'rake'
5
+
6
+ it 'downloads a GeoIP db to a location' do
7
+ dbfile = Tempfile.new('db')
8
+ subject.invoke(dbfile.path)
9
+ expect(dbfile.size).to be > 0
10
+ end
11
+ end
data/spec/spec_helper.rb CHANGED
@@ -14,7 +14,6 @@ Dir[File.join(current_dir, 'support/**/*.rb')].each { |f| require f }
14
14
 
15
15
  # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
16
16
  RSpec.configure do |config|
17
- config.treat_symbols_as_metadata_keys_with_true_values = true
18
17
  config.run_all_when_everything_filtered = true
19
18
  config.filter_run :focus
20
19
 
@@ -34,7 +34,7 @@ module GeoRedirect
34
34
 
35
35
  def log_should_include(message)
36
36
  @logfile.rewind
37
- @logfile.read.should include(message)
37
+ expect(@logfile.read).to include(message)
38
38
  end
39
39
  end
40
40
  end
metadata CHANGED
@@ -1,99 +1,127 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: geo_redirect
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.4'
4
+ version: '0.5'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sagie Maoz
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-01-12 00:00:00.000000000 Z
11
+ date: 2015-08-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - '>='
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: '0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - '>='
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: geoip
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - '>='
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
33
  version: '0'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - '>='
38
+ - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rspec
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - ~>
45
+ - - "~>"
46
46
  - !ruby/object:Gem::Version
47
47
  version: 3.1.0
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - ~>
52
+ - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: 3.1.0
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: rack
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - ~>
59
+ - - "~>"
60
60
  - !ruby/object:Gem::Version
61
61
  version: 1.6.0
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - ~>
66
+ - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: 1.6.0
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rack-test
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - ~>
73
+ - - "~>"
74
74
  - !ruby/object:Gem::Version
75
75
  version: 0.6.3
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - ~>
80
+ - - "~>"
81
81
  - !ruby/object:Gem::Version
82
82
  version: 0.6.3
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: simplecov
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - ~>
87
+ - - "~>"
88
88
  - !ruby/object:Gem::Version
89
89
  version: 0.9.1
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
- - - ~>
94
+ - - "~>"
95
95
  - !ruby/object:Gem::Version
96
96
  version: 0.9.1
97
+ - !ruby/object:Gem::Dependency
98
+ name: rubocop
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: 0.33.0
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: 0.33.0
111
+ - !ruby/object:Gem::Dependency
112
+ name: rubocop-rspec
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: 1.3.0
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: 1.3.0
97
125
  description: Geo-location based redirector
98
126
  email:
99
127
  - sagie@waze.com
@@ -101,10 +129,10 @@ executables: []
101
129
  extensions: []
102
130
  extra_rdoc_files: []
103
131
  files:
104
- - .gitignore
105
- - .rspec
106
- - .rubocop.yml
107
- - .travis.yml
132
+ - ".gitignore"
133
+ - ".rspec"
134
+ - ".rubocop.yml"
135
+ - ".travis.yml"
108
136
  - Gemfile
109
137
  - LICENSE.txt
110
138
  - README.md
@@ -118,7 +146,8 @@ files:
118
146
  - spec/fixtures/GeoIP.dat
119
147
  - spec/fixtures/config.bad.yml
120
148
  - spec/fixtures/config.yml
121
- - spec/geo_redirect_spec.rb
149
+ - spec/lib/geo_redirect/middleware_spec.rb
150
+ - spec/lib/tasks/geo_redirect_spec.rb
122
151
  - spec/spec_helper.rb
123
152
  - spec/support/geo_redirect.rb
124
153
  - spec/support/rake.rb
@@ -131,17 +160,17 @@ require_paths:
131
160
  - lib
132
161
  required_ruby_version: !ruby/object:Gem::Requirement
133
162
  requirements:
134
- - - '>='
163
+ - - ">="
135
164
  - !ruby/object:Gem::Version
136
165
  version: '0'
137
166
  required_rubygems_version: !ruby/object:Gem::Requirement
138
167
  requirements:
139
- - - '>='
168
+ - - ">="
140
169
  - !ruby/object:Gem::Version
141
170
  version: '0'
142
171
  requirements: []
143
172
  rubyforge_project:
144
- rubygems_version: 2.4.5
173
+ rubygems_version: 2.4.8
145
174
  signing_key:
146
175
  specification_version: 4
147
176
  summary: Rack middleware to redirect clients to hostnames based on geo-location
@@ -149,7 +178,9 @@ test_files:
149
178
  - spec/fixtures/GeoIP.dat
150
179
  - spec/fixtures/config.bad.yml
151
180
  - spec/fixtures/config.yml
152
- - spec/geo_redirect_spec.rb
181
+ - spec/lib/geo_redirect/middleware_spec.rb
182
+ - spec/lib/tasks/geo_redirect_spec.rb
153
183
  - spec/spec_helper.rb
154
184
  - spec/support/geo_redirect.rb
155
185
  - spec/support/rake.rb
186
+ has_rdoc:
@@ -1,241 +0,0 @@
1
- require 'spec_helper'
2
- require 'tempfile'
3
- require 'logger'
4
-
5
- describe 'geo_redirect' do
6
- include GeoRedirect::Support
7
- include Rack::Test::Methods
8
-
9
- def session
10
- last_request.env['rack.session'] || {}
11
- end
12
-
13
- def url_scheme
14
- last_request.env['rack.url_scheme']
15
- end
16
-
17
- let(:config) { YAML.load_file(fixture_path('config.yml')) }
18
-
19
- describe '#load_config' do
20
- it 'reads a config file' do
21
- mock_app
22
- expect(@app.config).to eq(config)
23
- end
24
-
25
- it 'errors on not-found config file' do
26
- mock_app config: nonexisting_file_path
27
- log_should_include('ERROR')
28
- log_should_include('Could not load GeoRedirect config YML file')
29
- end
30
-
31
- it 'errors on a mal-formatted config file' do
32
- mock_app config: fixture_path('config.bad.yml')
33
- log_should_include('ERROR')
34
- log_should_include('Could not load GeoRedirect config YML file')
35
- end
36
- end
37
-
38
- describe '#load_db' do
39
- it 'reads a db file' do
40
- mock_app
41
- expect(@app.db).to be_a(GeoIP)
42
- end
43
-
44
- it 'errors on not-found db file' do
45
- mock_app db: nonexisting_file_path
46
- log_should_include('ERROR')
47
- log_should_include('Could not load GeoIP database file.')
48
- end
49
-
50
- # this example is disabled, as it seems that
51
- # GeoIP does not let me know if a db file is proper.
52
- # it "errors on mal-formatted db file" do
53
- # pending "GeoIP does not raise on bad files"
54
- # mock_app :db => fixture_path("config.yml")
55
- # log_should_include("ERROR")
56
- # log_should_include("Could not load GeoIP database file.")
57
- # end
58
- end
59
-
60
- describe '#log' do
61
- describe 'with valid logfile path' do
62
- before { mock_app }
63
-
64
- it 'initiates a log file' do
65
- @app.instance_variable_get(:"@logger").should be_kind_of Logger
66
- end
67
-
68
- it 'prints to log file' do
69
- message = 'Testing GeoRedirect logger'
70
- @app.send(:log, [message])
71
- log_should_include(message)
72
- end
73
- end
74
-
75
- it 'ignores invalid logfile path' do
76
- mock_app logfile: '/no_such_file'
77
- expect(@app.instance_variable_get(:"@logger")).to be_nil
78
- end
79
- end
80
-
81
- describe '#host_by_country' do
82
- before { mock_app }
83
- subject { @app.host_by_country(country) }
84
-
85
- context 'when country is valid' do
86
- let(:country) { 'US' }
87
- it { is_expected.to eq(:us) }
88
- end
89
-
90
- context 'when country is invalid' do
91
- let(:country) { 'WHATEVER' }
92
- it { is_expected.to eq(:default) }
93
- end
94
- end
95
-
96
- describe 'host_by_hostname' do
97
- before { mock_app }
98
- subject { @app.host_by_hostname(hostname) }
99
-
100
- context 'when hostname is valid' do
101
- let(:hostname) { 'biz.waze.co.il' }
102
- it { is_expected.to eq(:il) }
103
- end
104
-
105
- context 'when hostname is invalid' do
106
- let(:hostname) { 'something.else.org' }
107
- it { is_expected.to eq(:default) }
108
- end
109
- end
110
-
111
- describe 'redirect logic' do
112
- before :each do
113
- mock_app
114
- end
115
-
116
- def mock_request_from(code, options = {})
117
- ip = '5.5.5.5'
118
-
119
- if code.nil?
120
- country = nil
121
- else
122
- country = GeoIP::Country.stub(country_code2: code,
123
- country_code: 5)
124
- end
125
- @app.db.stub(:country).with(ip).and_return(country)
126
-
127
- env = { 'REMOTE_ADDR' => ip, 'HTTP_HOST' => 'biz.waze.co.il' }
128
-
129
- if options[:session]
130
- env['rack.session'] ||= {}
131
- env['rack.session']['geo_redirect'] = options[:session]
132
- env['rack.session']['geo_redirect.country'] = code
133
- end
134
-
135
- args = {}
136
- args[:redirect] = 1 if options[:force]
137
- args[:skip_geo] = true if options[:skip]
138
-
139
- get '/', args, env
140
- end
141
-
142
- def should_redirect_to(host)
143
- last_response.body.should include('Moved Permanently')
144
- last_response.status.should eq(301)
145
- last_response.headers.should have_key('Location')
146
- url = "#{url_scheme}://#{config[host][:host]}"
147
- last_response.headers['Location'].should start_with(url)
148
- end
149
-
150
- def should_not_redirect
151
- last_response.body.should include('Hello world!')
152
- last_response.should be_ok
153
- end
154
-
155
- def should_remember(host)
156
- session['geo_redirect'].should eq(host)
157
- end
158
-
159
- def should_remember_country(country)
160
- session['geo_redirect.country'].should eq(country)
161
- end
162
-
163
- describe 'without session memory' do
164
- describe 'for a foreign source' do
165
- before { mock_request_from 'US' }
166
- it { should_redirect_to :us }
167
- it { should_remember :us }
168
- it { should_remember_country 'US' }
169
- end
170
-
171
- describe 'for a local source' do
172
- before { mock_request_from 'IL' }
173
- it { should_not_redirect }
174
- it { should_remember :il }
175
- it { should_remember_country 'IL' }
176
- end
177
-
178
- describe 'for an unknown source' do
179
- before { mock_request_from 'SOMEWHERE OVER THE RAINBOW' }
180
- it { should_redirect_to :default }
181
- it { should_remember :default }
182
- it { should_remember_country 'SOMEWHERE OVER THE RAINBOW' }
183
- end
184
- end
185
-
186
- describe 'with valid session memory' do
187
- before { mock_request_from 'US', session: :default }
188
- it { should_redirect_to :default }
189
- it { should_remember :default }
190
- it { should_remember_country 'US' }
191
- end
192
-
193
- describe 'with invalid session memory' do
194
- before { mock_request_from 'US', session: 'foo' }
195
-
196
- it 'removes invalid session data' do
197
- expect(session['geo_redirect']).not_to eq('foo')
198
- end
199
-
200
- it { should_redirect_to :us }
201
- it { should_remember :us }
202
- it { should_remember_country 'US' }
203
- end
204
-
205
- describe 'with forced redirect flag' do
206
- before { mock_request_from 'US', force: true }
207
-
208
- it { should_redirect_to :il }
209
- it 'rewrites the flag out' do
210
- expect(last_response.headers['Location']).not_to include('redirect=1')
211
- end
212
-
213
- it { should_remember :il }
214
- it { should_remember_country nil }
215
- end
216
-
217
- describe 'with skip flag' do
218
- before { mock_request_from 'US', skip: true }
219
- it { should_not_redirect }
220
- it { should_remember nil }
221
- it { should_remember_country nil }
222
- end
223
-
224
- describe 'with no recognizable IP' do
225
- before { mock_request_from nil }
226
- it { should_not_redirect }
227
- it { should_remember nil }
228
- it { should_remember_country nil }
229
- end
230
- end
231
- end
232
-
233
- describe 'geo_redirect:fetch_db' do
234
- include_context 'rake'
235
-
236
- it 'downloads a GeoIP db to a location' do
237
- dbfile = Tempfile.new('db')
238
- subject.invoke(dbfile.path)
239
- expect(dbfile.size).to be > 0
240
- end
241
- end