moesif_rack 1.4.18 → 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: 4332e59f946cefea8c61e0e7f40136ba2fd45c4c96de9f133651622c734d62b7
4
- data.tar.gz: 5f7e29ac2f016a4c97d56a1276aafd42cabedf316cbe0a5a6f82069dcd813f18
3
+ metadata.gz: ed6afe67a6d8b2aa3c05b23a704d2ccfaadf9afdb078e9d66998f69fd7ed3f45
4
+ data.tar.gz: 3cb56517e37769f179aabf0f1621c0969259558a46fa8594c017f85098f77423
5
5
  SHA512:
6
- metadata.gz: 25b4d5ea39d166c3aee2da057460c2fd9027bd4a7d1a1510e45ec0436890de5ea910b28353f00a034f735d99b7d5c840879e537b3022759216218d6cc351a1bf
7
- data.tar.gz: d4e0e2014e5b78b1b1ca4be8cc8e10769ebe5d3ed3d6c91f96004587a6e474ac34470af7272da8922ccac5773206a8c44fe4f4d8657bdd90fa3f3fa444f09863
6
+ metadata.gz: 91987307ffe2aaf10763dc39e0dce6acc1d91ed8f614144811b2a0d7c579b06d4f4f112cf6de10a983153aa81f45d5dac3450be5c38658af71728656d4426d5c
7
+ data.tar.gz: f6a677544fd723f0ab6842e5496586d93f22b8ddf77fc5ceb1c4fb98f770ce5443461a66f6c744f03b03a428acfa1c55c669d4f4f09841191c99842a40e614f6
data/README.md CHANGED
@@ -255,8 +255,17 @@ Optional. Boolean. Default false. If true, it will print out debug messages. In
255
255
 
256
256
  Optional. Boolean. Default true. If false, will not log request and response body to Moesif.
257
257
 
258
+ #### __`batch_size`__
259
+ Optional. int, default 200, Maximum batch size when sending to Moesif.
260
+
261
+ #### __`batch_max_time`__
262
+ Optional. int in seconds Default 2. This is the maximum wait time (approximately) before triggering flushing of the queue and sending to Moesif.
263
+
264
+ #### __`event_queue_size`__
265
+ Optional. int, Default 1000, Maximum number of events to hold in queue before sending to Moesif. In case of network issues when not able to connect/send event to Moesif, skips adding new to event to queue to prevent memory overflow.
266
+
258
267
  #### __`capture_outgoing_requests`__
259
- Optional. boolean, Default `false`. Set to `true` to capture all outgoing API calls from your app to third parties like Stripe, Github or to your own dependencies while using [Net::HTTP](https://ruby-doc.org/stdlib-2.6.3/libdoc/net/http/rdoc/Net/HTTP.html) package. The options below is applied to outgoing API calls. When the request is outgoing, for options functions that take request and response as input arguments, the request and response objects passed in are [Request](https://www.rubydoc.info/stdlib/net/Net/HTTPRequest) request and [Response](https://www.rubydoc.info/stdlib/net/Net/HTTPResponse) response objects.
268
+ Optional. Boolean, Default `false`. Set to `true` to capture all outgoing API calls from your app to third parties like Stripe, Github or to your own dependencies while using [Net::HTTP](https://ruby-doc.org/stdlib-2.6.3/libdoc/net/http/rdoc/Net/HTTP.html) package. The options below is applied to outgoing API calls. When the request is outgoing, for options functions that take request and response as input arguments, the request and response objects passed in are [Request](https://www.rubydoc.info/stdlib/net/Net/HTTPRequest) request and [Response](https://www.rubydoc.info/stdlib/net/Net/HTTPResponse) response objects.
260
269
 
261
270
 
262
271
  ##### __`identify_user_outgoing`__
@@ -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