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:



118
119
120
# File 'lib/rack/rewrite/rule.rb', line 118

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

Instance Attribute Details

#optionsObject (readonly)

Returns the value of attribute options.



117
118
119
# File 'lib/rack/rewrite/rule.rb', line 117

def options
  @options
end

#rule_typeObject (readonly)

Returns the value of attribute rule_type.



117
118
119
# File 'lib/rack/rewrite/rule.rb', line 117

def rule_type
  @rule_type
end

#toObject (readonly)

Returns the value of attribute to.



117
118
119
# File 'lib/rack/rewrite/rule.rb', line 117

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



136
137
138
139
140
141
142
143
144
145
146
147
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
# File 'lib/rack/rewrite/rule.rb', line 136

def apply!(env) #:nodoc:
  interpreted_to = self.interpret_to(env)
  additional_headers = {}
  if @options[:headers]
    if @options[:headers].respond_to?(:call)
      additional_headers = @options[:headers].call || {}
    else
      additional_headers = @options[:headers] || {}
    end
  end
  status = @options[:status] || 200
  case self.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..interpreted_to.size-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.new("Unsupported rule: #{self.rule_type}")
  end
end

#fromObject



129
130
131
132
# File 'lib/rack/rewrite/rule.rb', line 129

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

#interpret_to(env) ⇒ Object (protected)

:nodoc:



189
190
191
192
193
194
# File 'lib/rack/rewrite/rule.rb', line 189

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

#is_a_regexp?(obj) ⇒ Boolean (protected)

Returns:

  • (Boolean)


196
197
198
# File 'lib/rack/rewrite/rule.rb', line 196

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)


200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
# File 'lib/rack/rewrite/rule.rb', line 200

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)


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

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)

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