1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
|
# frozen_string_literal: true
require 'rest-client'
module QA
module Support
module Api
HTTP_STATUS_OK = 200
HTTP_STATUS_CREATED = 201
HTTP_STATUS_NO_CONTENT = 204
HTTP_STATUS_ACCEPTED = 202
HTTP_STATUS_NOT_FOUND = 404
HTTP_STATUS_SERVER_ERROR = 500
def post(url, payload, args = {})
default_args = {
method: :post,
url: url,
payload: payload,
verify_ssl: false
}
RestClient::Request.execute(
default_args.merge(args)
)
rescue RestClient::ExceptionWithResponse => e
return_response_or_raise(e)
end
def get(url, args = {})
default_args = {
method: :get,
url: url,
verify_ssl: false
}
RestClient::Request.execute(
default_args.merge(args)
)
rescue RestClient::ExceptionWithResponse => e
return_response_or_raise(e)
end
def put(url, payload = nil)
RestClient::Request.execute(
method: :put,
url: url,
payload: payload,
verify_ssl: false)
rescue RestClient::ExceptionWithResponse => e
return_response_or_raise(e)
end
def delete(url)
RestClient::Request.execute(
method: :delete,
url: url,
verify_ssl: false)
rescue RestClient::ExceptionWithResponse => e
return_response_or_raise(e)
end
def head(url)
RestClient::Request.execute(
method: :head,
url: url,
verify_ssl: false)
rescue RestClient::ExceptionWithResponse => e
return_response_or_raise(e)
end
def parse_body(response)
JSON.parse(response.body, symbolize_names: true)
end
def return_response_or_raise(error)
raise error unless error.respond_to?(:response) && error.response
error.response
end
def auto_paginated_response(url, attempts: 0)
pages = []
with_paginated_response_body(url, attempts: attempts) { |response| pages << response }
pages.flatten
end
def with_paginated_response_body(url, attempts: 0)
not_ok_error = lambda do |resp|
raise "Failed to GET #{QA::Runtime::API::Request.masked_url(url)} - (#{resp.code}): `#{resp}`."
end
loop do
response = if attempts > 0
Retrier.retry_on_exception(max_attempts: attempts, log: false) do
get(url).tap { |resp| not_ok_error.call(resp) if resp.code != HTTP_STATUS_OK }
end
else
get(url).tap { |resp| not_ok_error.call(resp) if resp.code != HTTP_STATUS_OK }
end
page, pages = response.headers.values_at(:x_page, :x_total_pages)
api_endpoint = url.match(%r{v4/(\S+)\?})[1]
QA::Runtime::Logger.debug("Fetching page (#{page}/#{pages}) for '#{api_endpoint}' ...") unless pages.to_i <= 1
yield parse_body(response)
next_link = pagination_links(response).find { |link| link[:rel] == 'next' }
break unless next_link
url = next_link[:url]
end
end
def pagination_links(response)
link = response.headers[:link]
return unless link
link.split(',').map do |link|
match = link.match(/<(?<url>.*)>; rel="(?<rel>\w+)"/)
break nil unless match
{ url: match[:url], rel: match[:rel] }
end.compact
end
end
end
end
|