Class: Rack::Rewrite::Rule

Inherits:
Object
  • Object
show all
Defined in:
lib/rack/rewrite/rule.rb

Overview

:nodoc:

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(rule_type, from, to, options = {}) ⇒ Rule

:nodoc:



125
126
127
128
129
130
# File 'lib/rack/rewrite/rule.rb', line 125

def initialize(rule_type, from, to, options = {}) # :nodoc:
  @rule_type = rule_type
  @from = from
  @to = to
  @options = normalize_options(options)
end

Instance Attribute Details

#optionsObject (readonly)

Returns the value of attribute options.



123
124
125
# File 'lib/rack/rewrite/rule.rb', line 123

def options
  @options
end

#rule_typeObject (readonly)

Returns the value of attribute rule_type.



123
124
125
# File 'lib/rack/rewrite/rule.rb', line 123

def rule_type
  @rule_type
end

#toObject (readonly)

Returns the value of attribute to.



123
124
125
# File 'lib/rack/rewrite/rule.rb', line 123

def to
  @to
end

Instance Method Details

#apply!(env) ⇒ Object

Either (a) return a Rack response (short-circuiting the Rack stack), or
(b) alter env as necessary and return true



148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
# File 'lib/rack/rewrite/rule.rb', line 148

def apply!(env) # :nodoc:
  interpreted_to = interpret_to(env)
  additional_headers = {}
  if @options[:headers]
    additional_headers = if @options[:headers].respond_to?(:call)
                           @options[:headers].call || {}
                         else
                           @options[:headers] || {}
                         end
  end
  status = @options[:status] || 200
  case rule_type
  when :r301
    [301, { 'Location' => interpreted_to, 'Content-Type' => Rack::Mime.mime_type(::File.extname(interpreted_to)) }.merge!(additional_headers), [redirect_message(interpreted_to)]]
  when :r302
    [302, { 'Location' => interpreted_to, 'Content-Type' => Rack::Mime.mime_type(::File.extname(interpreted_to)) }.merge!(additional_headers), [redirect_message(interpreted_to)]]
  when :r303
    [303, { 'Location' => interpreted_to, 'Content-Type' => Rack::Mime.mime_type(::File.extname(interpreted_to)) }.merge!(additional_headers), [redirect_message(interpreted_to)]]
  when :r307
    [307, { 'Location' => interpreted_to, 'Content-Type' => Rack::Mime.mime_type(::File.extname(interpreted_to)) }.merge!(additional_headers), [redirect_message(interpreted_to)]]
  when :rewrite
    # return [200, {}, {:content => env.inspect}]
    env['REQUEST_URI'] = interpreted_to
    if (q_index = interpreted_to.index('?'))
      env['PATH_INFO'] = interpreted_to[0..(q_index - 1)]
      env['QUERY_STRING'] = interpreted_to[(q_index + 1)..-1]
    else
      env['PATH_INFO'] = interpreted_to
      env['QUERY_STRING'] = ''
    end
    true
  when :send_file
    [status, {
      'Content-Length' => ::File.size(interpreted_to).to_s,
      'Content-Type'   => Rack::Mime.mime_type(::File.extname(interpreted_to))
      }.merge!(additional_headers), [::File.read(interpreted_to)]]
  when :x_send_file
    [status, {
      'X-Sendfile'     => interpreted_to,
      'Content-Length' => ::File.size(interpreted_to).to_s,
      'Content-Type'   => Rack::Mime.mime_type(::File.extname(interpreted_to))
      }.merge!(additional_headers), []]
  when :send_data
    [status, {
      'Content-Length' => interpreted_to.bytesize,
      'Content-Type' => 'text/html'
    }.merge!(additional_headers), [interpreted_to]]
  else
    raise Exception, "Unsupported rule: #{rule_type}"
  end
end

#fromObject



140
141
142
143
144
# File 'lib/rack/rewrite/rule.rb', line 140

def from
  return @static_from if @static_from

  @from.respond_to?(:call) ? @from.call : @static_from = @from
end

#interpret_to(env) ⇒ Object (protected)

:nodoc:



202
203
204
205
206
207
208
# File 'lib/rack/rewrite/rule.rb', line 202

def interpret_to(env) # :nodoc:
  path = build_path_from_env(env)
  return interpret_to_proc(path, env) if to.is_a?(Proc)
  return computed_to(path) if compute_to?(path)

  to
end

#is_a_regexp?(obj) ⇒ Boolean (protected)

Returns:

  • (Boolean)


210
211
212
# File 'lib/rack/rewrite/rule.rb', line 210

def is_a_regexp?(obj)
  obj.is_a?(Regexp) || (Object.const_defined?(:Oniguruma) && obj.is_a?(Oniguruma::ORegexp))
end

#match_options?(env, path = build_path_from_env(env)) ⇒ Boolean (protected)

Returns:

  • (Boolean)


214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
# File 'lib/rack/rewrite/rule.rb', line 214

def match_options?(env, path = build_path_from_env(env))
  matches = []
  request = Rack::Request.new(env)

  # negative matches
  matches << !string_matches?(path, options[:not]) if options[:not]

  # positive matches
  matches << string_matches?(env['REQUEST_METHOD'], options[:method]) if options[:method]
  matches << string_matches?(request.host, options[:host]) if options[:host]
  matches << string_matches?(request.scheme, options[:scheme]) if options[:scheme]

  if options[:country]
    # US, CA, etc.  HTTP_CF_IPCOUNTRY is provided by cloudflare
    country = env['HTTP_CF_IPCOUNTRY'] || (request.respond_to?(:location) && request.location&.country)
    if country && country != 'XX'
      country = 'CA' if country.upcase == 'CANADA' # Make ISO
      matches << string_matches?(country, options[:country])
    end
  end

  matches.all?
end

#matches?(rack_env) ⇒ Boolean

:nodoc:

Returns:

  • (Boolean)


132
133
134
135
136
137
138
# File 'lib/rack/rewrite/rule.rb', line 132

def matches?(rack_env) # :nodoc:
  return false if options[:if].respond_to?(:call) && !options[:if].call(rack_env)

  path = build_path_from_env(rack_env)

  match_options?(rack_env) && string_matches?(path, from)
end