moesif_rack 1.4.19 → 1.5.1

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
  SHA256:
3
- metadata.gz: 9648d28da08853893881cd32fef5fcf61d4f8d2c6a573d06ced10bb4e01bda3c
4
- data.tar.gz: cebdf8b64372dd77a80520e8cbec1da161f623a6435a8ced10a700aa86e57113
3
+ metadata.gz: ed6afe67a6d8b2aa3c05b23a704d2ccfaadf9afdb078e9d66998f69fd7ed3f45
4
+ data.tar.gz: 3cb56517e37769f179aabf0f1621c0969259558a46fa8594c017f85098f77423
5
5
  SHA512:
6
- metadata.gz: 35bb379b52dc6f4323d5dc98154c5ba741e438ec1cf98030f06775405c405e4a34871b9435a9a3f89d0b32e6545c2f6ec88083e59d2c4e97c271e765200e89bc
7
- data.tar.gz: 72422bb99d80d78e91af4034ff4dd31f7f94c8424a498819a6767ce066045209e4dc8c1e9784a88377cf100e79fad3cb0733989f0869b449dedf60e91b916f60
6
+ metadata.gz: 91987307ffe2aaf10763dc39e0dce6acc1d91ed8f614144811b2a0d7c579b06d4f4f112cf6de10a983153aa81f45d5dac3450be5c38658af71728656d4426d5c
7
+ data.tar.gz: f6a677544fd723f0ab6842e5496586d93f22b8ddf77fc5ceb1c4fb98f770ce5443461a66f6c744f03b03a428acfa1c55c669d4f4f09841191c99842a40e614f6
@@ -3,134 +3,101 @@ require 'json'
3
3
  require 'time'
4
4
  require 'zlib'
5
5
  require 'stringio'
6
- require_relative './moesif_helpers.rb'
7
- require_relative './regex_config_helper.rb'
6
+ require_relative './moesif_helpers'
7
+ require_relative './regex_config_helper'
8
8
 
9
9
  class AppConfig
10
+ def initialize(debug)
11
+ @debug = debug
12
+ @moesif_helpers = MoesifHelpers.new(debug)
13
+ @regex_config_helper = RegexConfigHelper.new(debug)
14
+ end
10
15
 
11
- def initialize debug
12
- @debug = debug
13
- @moesif_helpers = MoesifHelpers.new(debug)
14
- @regex_config_helper = RegexConfigHelper.new(debug)
16
+ def get_config(api_controller)
17
+ # Get Application Config
18
+ config_api_response = api_controller.get_app_config
19
+ @moesif_helpers.log_debug('new config downloaded')
20
+ @moesif_helpers.log_debug(config_api_response.to_s)
21
+ config_api_response
22
+ rescue MoesifApi::APIException => e
23
+ if e.response_code.between?(401, 403)
24
+ @moesif_helpers.log_debug 'Unauthorized access getting application configuration. Please check your Appplication Id.'
15
25
  end
26
+ @moesif_helpers.log_debug 'Error getting application configuration, with status code:'
27
+ @moesif_helpers.log_debug e.response_code
28
+ rescue StandardError => e
29
+ @moesif_helpers.log_debug e.to_s
30
+ end
16
31
 
17
- def get_config(api_controller)
18
- # Get Application Config
19
- begin
20
- config_api_response = api_controller.get_app_config()
21
- @moesif_helpers.log_debug("new config downloaded")
22
- @moesif_helpers.log_debug(config_api_response.to_s)
23
- return config_api_response
24
- rescue MoesifApi::APIException => e
25
- if e.response_code.between?(401, 403)
26
- @moesif_helpers.log_debug 'Unauthorized access getting application configuration. Please check your Appplication Id.'
27
- end
28
- @moesif_helpers.log_debug 'Error getting application configuration, with status code:'
29
- @moesif_helpers.log_debug e.response_code
30
- rescue => e
31
- @moesif_helpers.log_debug e.to_s
32
- end
33
- rescue
34
- end
32
+ def parse_configuration(config_api_response)
33
+ # Parse configuration object and return Etag, sample rate and last updated time
35
34
 
36
- def parse_configuration(config_api_response)
37
- # Parse configuration object and return Etag, sample rate and last updated time
38
- begin
39
- # Rails return gzipped compressed response body, so decompressing it and getting JSON response body
40
- response_body = decompress_gzip_body(config_api_response)
41
- @moesif_helpers.log_debug(response_body.to_s)
42
-
43
- # Check if response body is not nil
44
- if !response_body.nil? then
45
- # Return Etag, sample rate and last updated time
46
- return response_body, config_api_response.headers[:x_moesif_config_etag], Time.now.utc
47
- else
48
- @moesif_helpers.log_debug 'Response body is nil, assuming default behavior'
49
- # Response body is nil, so assuming default behavior
50
- return nil, nil, Time.now.utc
51
- end
52
- rescue => exception
53
- @moesif_helpers.log_debug 'Error while parsing the configuration object, assuming default behavior'
54
- @moesif_helpers.log_debug exception.to_s
55
- # Assuming default behavior
56
- return nil, nil, Time.now.utc
57
- end
58
- end
35
+ # Rails return gzipped compressed response body, so decompressing it and getting JSON response body
36
+ response_body = @moesif_helpers.decompress_gzip_body(config_api_response)
37
+ @moesif_helpers.log_debug(response_body.to_json)
59
38
 
60
- def get_sampling_percentage(event_model, config_api_response, user_id, company_id)
61
- # Get sampling percentage
62
- begin
63
- # Check if response body is not nil
64
- if !config_api_response.nil? then
65
- @moesif_helpers.log_debug("Getting sample rate for user #{user_id} company #{company_id}")
66
- @moesif_helpers.log_debug(config_api_response.to_s)
67
-
68
- # Get Regex Sampling rate
69
- regex_config = config_api_response.fetch('regex_config', nil)
70
-
71
- if !regex_config.nil? and !event_model.nil?
72
- config_mapping = @regex_config_helper.prepare_config_mapping(event_model)
73
- regex_sample_rate = @regex_config_helper.fetch_sample_rate_on_regex_match(regex_config, config_mapping)
74
- if !regex_sample_rate.nil?
75
- return regex_sample_rate
76
- end
77
- end
78
-
79
- # Get user sample rate object
80
- user_sample_rate = config_api_response.fetch('user_sample_rate', nil)
81
-
82
- # Get company sample rate object
83
- company_sample_rate = config_api_response.fetch('company_sample_rate', nil)
84
-
85
- # Get sample rate for the user if exist
86
- if !user_id.nil? && !user_sample_rate.nil? && user_sample_rate.key?(user_id)
87
- return user_sample_rate.fetch(user_id)
88
- end
89
-
90
- # Get sample rate for the company if exist
91
- if !company_id.nil? && !company_sample_rate.nil? && company_sample_rate.key?(company_id)
92
- return company_sample_rate.fetch(company_id)
93
- end
94
-
95
- # Return sample rate
96
- return config_api_response.fetch('sample_rate', 100)
97
- else
98
- @moesif_helpers.log_debug 'Assuming default behavior as response body is nil - '
99
- return 100
100
- end
101
- rescue => exception
102
- @moesif_helpers.log_debug 'Error while geting sampling percentage, assuming default behavior'
103
- @moesif_helpers.log_debug exception.to_s
104
- return 100
105
- end
106
- end
39
+ # Check if response body is not nil
40
+ return response_body, config_api_response.headers[:x_moesif_config_etag], Time.now.utc unless response_body.nil?
107
41
 
108
- def decompress_gzip_body(config_api_response)
109
- # Decompress gzip response body
110
- begin
111
- # Check if the content-encoding header exist and is of type zip
112
- if config_api_response.headers.key?(:content_encoding) && config_api_response.headers[:content_encoding].eql?( 'gzip' ) then
113
-
114
- # Create a GZipReader object to read data
115
- gzip_reader = Zlib::GzipReader.new(StringIO.new(config_api_response.raw_body.to_s))
116
-
117
- # Read the body
118
- uncompressed_string = gzip_reader.read
119
-
120
- # Return the parsed body
121
- return JSON.parse( uncompressed_string )
122
- else
123
- @moesif_helpers.log_debug 'Content Encoding is of type other than gzip, returning nil'
124
- return nil
125
- end
126
- rescue => exception
127
- @moesif_helpers.log_debug 'Error while decompressing the response body'
128
- @moesif_helpers.log_debug exception.to_s
129
- return nil
130
- end
131
- end
42
+ # Return Etag, sample rate and last updated time
43
+
44
+ @moesif_helpers.log_debug 'Response body is nil, assuming default behavior'
45
+ # Response body is nil, so assuming default behavior
46
+ [nil, nil, Time.now.utc]
47
+ rescue StandardError => e
48
+ @moesif_helpers.log_debug 'Error while parsing the configuration object, assuming default behavior'
49
+ @moesif_helpers.log_debug e.to_s
50
+ # Assuming default behavior
51
+ [nil, nil, Time.now.utc]
52
+ end
53
+
54
+ def get_sampling_percentage(event_model, config_api_response, user_id, company_id)
55
+ # Get sampling percentage
56
+
57
+ # Check if response body is not nil
58
+ if !config_api_response.nil?
59
+ @moesif_helpers.log_debug("Getting sample rate for user #{user_id} company #{company_id}")
60
+ @moesif_helpers.log_debug(config_api_response.to_s)
132
61
 
133
- def calculate_weight(sample_rate)
134
- return sample_rate == 0 ? 1 : (100 / sample_rate).floor
62
+ # Get Regex Sampling rate
63
+ regex_config = config_api_response.fetch('regex_config', nil)
64
+
65
+ if !regex_config.nil? and !event_model.nil?
66
+ config_mapping = @regex_config_helper.prepare_config_mapping(event_model)
67
+ regex_sample_rate = @regex_config_helper.fetch_sample_rate_on_regex_match(regex_config,
68
+ config_mapping)
69
+ return regex_sample_rate unless regex_sample_rate.nil?
70
+ end
71
+
72
+ # Get user sample rate object
73
+ user_sample_rate = config_api_response.fetch('user_sample_rate', nil)
74
+
75
+ # Get company sample rate object
76
+ company_sample_rate = config_api_response.fetch('company_sample_rate', nil)
77
+
78
+ # Get sample rate for the user if exist
79
+ if !user_id.nil? && !user_sample_rate.nil? && user_sample_rate.key?(user_id)
80
+ return user_sample_rate.fetch(user_id)
81
+ end
82
+
83
+ # Get sample rate for the company if exist
84
+ if !company_id.nil? && !company_sample_rate.nil? && company_sample_rate.key?(company_id)
85
+ return company_sample_rate.fetch(company_id)
86
+ end
87
+
88
+ # Return sample rate
89
+ config_api_response.fetch('sample_rate', 100)
90
+ else
91
+ @moesif_helpers.log_debug 'Assuming default behavior as response body is nil - '
92
+ 100
135
93
  end
94
+ rescue StandardError => e
95
+ @moesif_helpers.log_debug 'Error while geting sampling percentage, assuming default behavior'
96
+ @moesif_helpers.log_debug e.to_s
97
+ 100
98
+ end
99
+
100
+ def calculate_weight(sample_rate)
101
+ sample_rate == 0 ? 1 : (100 / sample_rate).floor
102
+ end
136
103
  end
@@ -1,119 +1,78 @@
1
-
2
1
  def is_ip?(value)
3
- ipv4 = /^(?:(?:\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])\.){3}(?:\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])$/
4
- ipv6 = /^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$/
5
- # We use !! to convert the return value to a boolean
6
- !!(value =~ ipv4 or value=~ ipv6)
2
+ ipv4 = /^(?:(?:\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])\.){3}(?:\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])$/
3
+ ipv6 = /^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$/
4
+ # We use !! to convert the return value to a boolean
5
+ !!(value =~ ipv4 or value =~ ipv6)
7
6
  end
8
7
 
9
8
  def get_client_ip_from_x_forwarded_for(value)
10
- begin
11
- value = value.encode('utf-8')
12
-
13
- if value.to_s.empty?
14
- return nil
15
- end
16
-
17
- if !value.instance_of?(String)
18
- puts ("Expected a string, got - " + value.class.to_s)
19
- else
20
- # x-forwarded-for may return multiple IP addresses in the format:
21
- # "client IP, proxy 1 IP, proxy 2 IP"
22
- # Therefore, the right-most IP address is the IP address of the most recent proxy
23
- # and the left-most IP address is the IP address of the originating client.
24
- # source: http://docs.aws.amazon.com/elasticloadbalancing/latest/classic/x-forwarded-headers.html
25
- # Azure Web App's also adds a port for some reason, so we'll only use the first part (the IP)
26
- forwardedIps = []
27
-
28
- value.gsub(/\s+/, "").split(',').each do |e|
29
- if e.include?(':')
30
- splitted = e.split(':')
31
- if splitted.length == 2
32
- forwardedIps << splitted.first
33
- end
34
- end
35
- forwardedIps << e
36
- end
37
-
38
- # Sometimes IP addresses in this header can be 'unknown' (http://stackoverflow.com/a/11285650).
39
- # Therefore taking the left-most IP address that is not unknown
40
- # A Squid configuration directive can also set the value to "unknown" (http://www.squid-cache.org/Doc/config/forwarded_for/)
41
- return forwardedIps.find {|e| is_ip?(e) }
42
- end
43
- rescue
44
- return value.encode('utf-8')
9
+ value = value.encode('utf-8')
10
+
11
+ return nil if value.to_s.empty?
12
+
13
+ if !value.instance_of?(String)
14
+ puts('Expected a string, got - ' + value.class.to_s)
15
+ else
16
+ # x-forwarded-for may return multiple IP addresses in the format:
17
+ # "client IP, proxy 1 IP, proxy 2 IP"
18
+ # Therefore, the right-most IP address is the IP address of the most recent proxy
19
+ # and the left-most IP address is the IP address of the originating client.
20
+ # source: http://docs.aws.amazon.com/elasticloadbalancing/latest/classic/x-forwarded-headers.html
21
+ # Azure Web App's also adds a port for some reason, so we'll only use the first part (the IP)
22
+ forwardedIps = []
23
+
24
+ value.gsub(/\s+/, '').split(',').each do |e|
25
+ if e.include?(':')
26
+ splitted = e.split(':')
27
+ forwardedIps << splitted.first if splitted.length == 2
28
+ end
29
+ forwardedIps << e
45
30
  end
31
+
32
+ # Sometimes IP addresses in this header can be 'unknown' (http://stackoverflow.com/a/11285650).
33
+ # Therefore taking the left-most IP address that is not unknown
34
+ # A Squid configuration directive can also set the value to "unknown" (http://www.squid-cache.org/Doc/config/forwarded_for/)
35
+ forwardedIps.find { |e| is_ip?(e) }
36
+ end
37
+ rescue StandardError
38
+ value.encode('utf-8')
46
39
  end
47
40
 
48
41
  def get_client_address(env)
49
- begin
50
- # Standard headers used by Amazon EC2, Heroku, and others.
51
- if env.key?('HTTP_X_CLIENT_IP')
52
- if is_ip?(env['HTTP_X_CLIENT_IP'])
53
- return env['HTTP_X_CLIENT_IP']
54
- end
55
- end
42
+ # Standard headers used by Amazon EC2, Heroku, and others.
43
+ return env['HTTP_X_CLIENT_IP'] if env.key?('HTTP_X_CLIENT_IP') && is_ip?(env['HTTP_X_CLIENT_IP'])
56
44
 
57
- # Load-balancers (AWS ELB) or proxies.
58
- if env.key?('HTTP_X_FORWARDED_FOR')
59
- xForwardedFor = get_client_ip_from_x_forwarded_for(env['HTTP_X_FORWARDED_FOR'])
60
- if is_ip?(xForwardedFor)
61
- return xForwardedFor
62
- end
63
- end
45
+ # Load-balancers (AWS ELB) or proxies.
46
+ if env.key?('HTTP_X_FORWARDED_FOR')
47
+ xForwardedFor = get_client_ip_from_x_forwarded_for(env['HTTP_X_FORWARDED_FOR'])
48
+ return xForwardedFor if is_ip?(xForwardedFor)
49
+ end
64
50
 
65
- # Cloudflare.
66
- # @see https://support.cloudflare.com/hc/en-us/articles/200170986-How-does-Cloudflare-handle-HTTP-Request-headers-
67
- # CF-Connecting-IP - applied to every request to the origin.
68
- if env.key?('HTTP_CF_CONNECTING_IP')
69
- if is_ip?(env['HTTP_CF_CONNECTING_IP'])
70
- return env['HTTP_CF_CONNECTING_IP']
71
- end
72
- end
51
+ # Cloudflare.
52
+ # @see https://support.cloudflare.com/hc/en-us/articles/200170986-How-does-Cloudflare-handle-HTTP-Request-headers-
53
+ # CF-Connecting-IP - applied to every request to the origin.
54
+ return env['HTTP_CF_CONNECTING_IP'] if env.key?('HTTP_CF_CONNECTING_IP') && is_ip?(env['HTTP_CF_CONNECTING_IP'])
73
55
 
74
- # Akamai and Cloudflare: True-Client-IP.
75
- if env.key?('HTTP_TRUE_CLIENT_IP')
76
- if is_ip?(env['HTTP_TRUE_CLIENT_IP'])
77
- return env['HTTP_TRUE_CLIENT_IP']
78
- end
79
- end
56
+ # Akamai and Cloudflare: True-Client-IP.
57
+ return env['HTTP_TRUE_CLIENT_IP'] if env.key?('HTTP_TRUE_CLIENT_IP') && is_ip?(env['HTTP_TRUE_CLIENT_IP'])
80
58
 
81
- # Default nginx proxy/fcgi; alternative to x-forwarded-for, used by some proxies.
82
- if env.key?('HTTP_X_REAL_IP')
83
- if is_ip?(env['HTTP_X_REAL_IP'])
84
- return env['HTTP_X_REAL_IP']
85
- end
86
- end
59
+ # Default nginx proxy/fcgi; alternative to x-forwarded-for, used by some proxies.
60
+ return env['HTTP_X_REAL_IP'] if env.key?('HTTP_X_REAL_IP') && is_ip?(env['HTTP_X_REAL_IP'])
87
61
 
88
- # (Rackspace LB and Riverbed's Stingray)
89
- # http://www.rackspace.com/knowledge_center/article/controlling-access-to-linux-cloud-sites-based-on-the-client-ip-address
90
- # https://splash.riverbed.com/docs/DOC-1926
91
- if env.key?('HTTP_X_CLUSTER_CLIENT_IP')
92
- if is_ip?(env['HTTP_X_CLUSTER_CLIENT_IP'])
93
- return env['HTTP_X_CLUSTER_CLIENT_IP']
94
- end
95
- end
62
+ # (Rackspace LB and Riverbed's Stingray)
63
+ # http://www.rackspace.com/knowledge_center/article/controlling-access-to-linux-cloud-sites-based-on-the-client-ip-address
64
+ # https://splash.riverbed.com/docs/DOC-1926
65
+ if env.key?('HTTP_X_CLUSTER_CLIENT_IP') && is_ip?(env['HTTP_X_CLUSTER_CLIENT_IP'])
66
+ return env['HTTP_X_CLUSTER_CLIENT_IP']
67
+ end
96
68
 
97
- if env.key?('HTTP_X_FORWARDED')
98
- if is_ip?(env['HTTP_X_FORWARDED'])
99
- return env['HTTP_X_FORWARDED']
100
- end
101
- end
69
+ return env['HTTP_X_FORWARDED'] if env.key?('HTTP_X_FORWARDED') && is_ip?(env['HTTP_X_FORWARDED'])
102
70
 
103
- if env.key?('HTTP_FORWARDED_FOR')
104
- if is_ip?(env['HTTP_FORWARDED_FOR'])
105
- return env['HTTP_FORWARDED_FOR']
106
- end
107
- end
71
+ return env['HTTP_FORWARDED_FOR'] if env.key?('HTTP_FORWARDED_FOR') && is_ip?(env['HTTP_FORWARDED_FOR'])
108
72
 
109
- if env.key?('HTTP_FORWARDED')
110
- if is_ip?(env['HTTP_FORWARDED'])
111
- return env['HTTP_FORWARDED']
112
- end
113
- end
73
+ return env['HTTP_FORWARDED'] if env.key?('HTTP_FORWARDED') && is_ip?(env['HTTP_FORWARDED'])
114
74
 
115
- return env['REMOTE_ADDR']
116
- rescue
117
- return env['REMOTE_ADDR']
118
- end
119
- end
75
+ env['REMOTE_ADDR']
76
+ rescue StandardError
77
+ env['REMOTE_ADDR']
78
+ end