Class: Rack::OverridePath

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

Constant Summary collapse

DEFAULT_BODY =
''
DEFAULT_DELAY =
0
DEFAULT_HEADERS =
{}.freeze
DEFAULT_STATUS =
200
OVERRIDE_KEYS =
%w[body delay headers status].freeze

Instance Method Summary collapse

Constructor Details

#initialize(app) ⇒ OverridePath

Returns a new instance of OverridePath.



14
15
16
17
# File 'lib/rack/override_path.rb', line 14

def initialize(app)
  @app = app
  @overridden_paths = []
end

Instance Method Details

#at_least_one_override_key?(payload) ⇒ Boolean

Returns:

  • (Boolean)


78
79
80
# File 'lib/rack/override_path.rb', line 78

def at_least_one_override_key?(payload)
  !(payload.keys & OVERRIDE_KEYS).empty?
end

#call(env) ⇒ Object



19
20
21
22
23
24
25
26
27
28
29
30
# File 'lib/rack/override_path.rb', line 19

def call(env)
  req = request(env)
  if override_path?(req)
    override_path(req)
  elsif path_overridden?(req.path) && override_matches_method?(req)
    handle_override(req.path, env)
  elsif get_override?(req)
    get_override(req)
  else
    @app.call(env)
  end
end

#get_override(_req) ⇒ Object



41
42
43
# File 'lib/rack/override_path.rb', line 41

def get_override(_req)
  [200, { 'Content-Type' => 'application/json' }, [@overridden_paths.to_json]]
end

#get_override?(req) ⇒ Boolean

Returns:

  • (Boolean)


37
38
39
# File 'lib/rack/override_path.rb', line 37

def get_override?(req)
  req.path == '/override/path' && req.get?
end

#handle_override(path, env) ⇒ Object



94
95
96
97
98
99
# File 'lib/rack/override_path.rb', line 94

def handle_override(path, env)
  o = override(path)
  handle_override_delay(o['delay']) if o['delay']
  status, headers, body = @app.call(env) unless o['body']
  handle_override_response(o, status, headers, body)
end

#handle_override_delay(delay) ⇒ Object



101
102
103
# File 'lib/rack/override_path.rb', line 101

def handle_override_delay(delay)
  sleep delay
end

#handle_override_response(override, status, headers, body) ⇒ Object



105
106
107
108
109
110
# File 'lib/rack/override_path.rb', line 105

def handle_override_response(override, status, headers, body)
  response_status = override['status'] || status || DEFAULT_STATUS
  response_headers = override['headers'] || headers || DEFAULT_HEADERS
  response_body = override['body'] || body || DEFAULT_BODY
  [response_status, response_headers, prepare_response_body_for_rack(response_body)]
end

#literal_path(path) ⇒ Object



56
57
58
# File 'lib/rack/override_path.rb', line 56

def literal_path(path)
  "^#{path}$"
end

#literal_path?(path) ⇒ Boolean

Returns:

  • (Boolean)


52
53
54
# File 'lib/rack/override_path.rb', line 52

def literal_path?(path)
  path[0] == '/'
end

#override(path) ⇒ Object



45
46
47
48
49
50
# File 'lib/rack/override_path.rb', line 45

def override(path)
  @overridden_paths.find do |override|
    override_path = literal_path?(override['path']) ? literal_path(override['path']) : override['path']
    path.match(Regexp.new(override_path))
  end
end

#override_matches_method?(req) ⇒ Boolean

Returns:

  • (Boolean)


32
33
34
35
# File 'lib/rack/override_path.rb', line 32

def override_matches_method?(req)
  o = override(req.path)
  o['method'].nil? ? true : o['method'].downcase == req.request_method.downcase
end

#override_path(req) ⇒ Object



64
65
66
67
68
69
70
71
72
# File 'lib/rack/override_path.rb', line 64

def override_path(req)
  payload = request_body_json(req)
  if valid?(payload)
    @overridden_paths.prepend(payload)
    override_path_successful_response(payload)
  else
    override_path_failed_response_no_body
  end
end

#override_path?(req) ⇒ Boolean

Returns:

  • (Boolean)


60
61
62
# File 'lib/rack/override_path.rb', line 60

def override_path?(req)
  req.path == '/override/path' && req.post?
end

#override_path_failed_response_no_bodyObject



86
87
88
# File 'lib/rack/override_path.rb', line 86

def override_path_failed_response_no_body
  [400, { 'Content-Type' => 'application/json' }, [{ 'message' => 'No body provided' }.to_json]]
end

#override_path_successful_response(payload) ⇒ Object



82
83
84
# File 'lib/rack/override_path.rb', line 82

def override_path_successful_response(payload)
  [200, { 'Content-Type' => 'application/json' }, [payload.to_json]]
end

#path_overridden?(path) ⇒ Boolean

Returns:

  • (Boolean)


90
91
92
# File 'lib/rack/override_path.rb', line 90

def path_overridden?(path)
  override(path).nil? ? false : true
end

#prepare_response_body_for_rack(response_body) ⇒ Object



112
113
114
115
# File 'lib/rack/override_path.rb', line 112

def prepare_response_body_for_rack(response_body)
  response_body = response_body.is_a?(Hash) ? response_body.to_json : response_body
  response_body.is_a?(Array) ? response_body : [response_body]
end

#request(env) ⇒ Object



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

def request(env)
  Rack::Request.new(env)
end

#request_body(req) ⇒ Object



127
128
129
130
131
132
# File 'lib/rack/override_path.rb', line 127

def request_body(req)
  req.body.rewind
  req.body.read
rescue StandardError => _e
  ''
end

#request_body_json(req) ⇒ Object



121
122
123
124
125
# File 'lib/rack/override_path.rb', line 121

def request_body_json(req)
  JSON.parse(request_body(req))
rescue StandardError => _e
  nil
end

#valid?(payload) ⇒ Boolean

Returns:

  • (Boolean)


74
75
76
# File 'lib/rack/override_path.rb', line 74

def valid?(payload)
  payload&.key?('path') && at_least_one_override_key?(payload)
end