dnsimple 4.1.0 → 4.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop_dnsimple.yml +52 -2
- data/.travis.yml +4 -2
- data/CHANGELOG.md +5 -1
- data/README.md +17 -4
- data/lib/dnsimple/client.rb +31 -4
- data/lib/dnsimple/client/clients.rb +4 -0
- data/lib/dnsimple/client/collaborators.rb +5 -5
- data/lib/dnsimple/client/domains_delegation_signer_records.rb +122 -0
- data/lib/dnsimple/client/domains_dnssec.rb +57 -0
- data/lib/dnsimple/client/zones_records.rb +3 -3
- data/lib/dnsimple/struct.rb +2 -0
- data/lib/dnsimple/struct/delegation_signer_record.rb +31 -0
- data/lib/dnsimple/struct/dnssec.rb +10 -0
- data/lib/dnsimple/version.rb +1 -1
- data/spec/dnsimple/client/domains_delegation_signer_records_spec.rb +209 -0
- data/spec/dnsimple/client/domains_dnssec_spec.rb +122 -0
- data/spec/dnsimple/client/oauth_spec.rb +5 -5
- data/spec/fixtures.http/createDelegationSignerRecord/created.http +21 -0
- data/spec/fixtures.http/createDelegationSignerRecord/validation-error.http +19 -0
- data/spec/fixtures.http/deleteDelegationSignerRecord/success.http +17 -0
- data/spec/fixtures.http/disableDnssec/not-enabled.http +19 -0
- data/spec/fixtures.http/disableDnssec/success.http +17 -0
- data/spec/fixtures.http/enableDnssec/success.http +21 -0
- data/spec/fixtures.http/getDelegationSignerRecord/success.http +21 -0
- data/spec/fixtures.http/getDnssec/success.http +21 -0
- data/spec/fixtures.http/listDelegationSignerRecords/success.http +21 -0
- data/spec/fixtures.http/notfound-delegationsignerrecord.http +12 -0
- metadata +30 -2
@@ -13,11 +13,11 @@ module Dnsimple
|
|
13
13
|
# @example List records for the zone "example.com", provide a specific page
|
14
14
|
# client.zones.records(1010, "example.com", page: 2)
|
15
15
|
#
|
16
|
-
# @example List records for the zone "example.com",
|
16
|
+
# @example List records for the zone "example.com", sorting in ascending order
|
17
17
|
# client.zones.records(1010, "example.com", sort: "type:asc")
|
18
18
|
#
|
19
|
-
# @example List records for the zone "example.com",
|
20
|
-
# client.zones.records(1010, "example.com",
|
19
|
+
# @example List records for the zone "example.com", filtering by 'A' record type
|
20
|
+
# client.zones.records(1010, "example.com", filter: { type: 'A' })
|
21
21
|
#
|
22
22
|
# @param [Integer] account_id the account ID
|
23
23
|
# @param [String] zone_id the zone name
|
data/lib/dnsimple/struct.rb
CHANGED
@@ -18,6 +18,8 @@ require_relative 'struct/collaborator'
|
|
18
18
|
require_relative 'struct/contact'
|
19
19
|
require_relative 'struct/certificate'
|
20
20
|
require_relative 'struct/certificate_bundle'
|
21
|
+
require_relative 'struct/delegation_signer_record'
|
22
|
+
require_relative 'struct/dnssec'
|
21
23
|
require_relative 'struct/domain'
|
22
24
|
require_relative 'struct/domain_check'
|
23
25
|
require_relative 'struct/domain_premium_price'
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Dnsimple
|
2
|
+
module Struct
|
3
|
+
|
4
|
+
class DelegationSignerRecord < Base
|
5
|
+
# @return [Integer] The ID of the delegation signer record in DNSimple.
|
6
|
+
attr_accessor :id
|
7
|
+
|
8
|
+
# @return [Integer] The associated domain ID.
|
9
|
+
attr_accessor :domain_id
|
10
|
+
|
11
|
+
# @return [String] The signing algorithm used.
|
12
|
+
attr_accessor :algorithm
|
13
|
+
|
14
|
+
# @return [String] The digest value.
|
15
|
+
attr_accessor :digest
|
16
|
+
|
17
|
+
# @return [String] The digest type used.
|
18
|
+
attr_accessor :digest_type
|
19
|
+
|
20
|
+
# @return [String] The keytag for the associated DNSKEY.
|
21
|
+
attr_accessor :keytag
|
22
|
+
|
23
|
+
# @return [String] When the delegation signing record was created in DNSimple.
|
24
|
+
attr_accessor :created_at
|
25
|
+
|
26
|
+
# @return [String] When the delegation signing record was last updated in DNSimple.
|
27
|
+
attr_accessor :updated_at
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
data/lib/dnsimple/version.rb
CHANGED
@@ -0,0 +1,209 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Dnsimple::Client, ".domains" do
|
4
|
+
|
5
|
+
subject { described_class.new(base_url: "https://api.dnsimple.test", access_token: "a1b2c3").domains }
|
6
|
+
|
7
|
+
|
8
|
+
describe "#delegation_signer_records" do
|
9
|
+
let(:account_id) { 1010 }
|
10
|
+
let(:domain_id) { "example.com" }
|
11
|
+
|
12
|
+
before do
|
13
|
+
stub_request(:get, %r{/v2/#{account_id}/domains/#{domain_id}/ds_records}).
|
14
|
+
to_return(read_http_fixture("listDelegationSignerRecords/success.http"))
|
15
|
+
end
|
16
|
+
|
17
|
+
it "builds the correct request" do
|
18
|
+
subject.delegation_signer_records(account_id, domain_id)
|
19
|
+
|
20
|
+
expect(WebMock).to have_requested(:get, "https://api.dnsimple.test/v2/#{account_id}/domains/#{domain_id}/ds_records").
|
21
|
+
with(headers: { 'Accept' => 'application/json' })
|
22
|
+
end
|
23
|
+
|
24
|
+
it "supports pagination" do
|
25
|
+
subject.delegation_signer_records(account_id, domain_id, page: 2)
|
26
|
+
|
27
|
+
expect(WebMock).to have_requested(:get, "https://api.dnsimple.test/v2/#{account_id}/domains/#{domain_id}/ds_records?page=2")
|
28
|
+
end
|
29
|
+
|
30
|
+
it "supports extra request options" do
|
31
|
+
subject.delegation_signer_records(account_id, domain_id, query: { foo: "bar" })
|
32
|
+
|
33
|
+
expect(WebMock).to have_requested(:get, "https://api.dnsimple.test/v2/#{account_id}/domains/#{domain_id}/ds_records?foo=bar")
|
34
|
+
end
|
35
|
+
|
36
|
+
it "supports sorting" do
|
37
|
+
subject.delegation_signer_records(account_id, domain_id, sort: "id:asc,from:desc")
|
38
|
+
|
39
|
+
expect(WebMock).to have_requested(:get, "https://api.dnsimple.test/v2/#{account_id}/domains/#{domain_id}/ds_records?sort=id:asc,from:desc")
|
40
|
+
end
|
41
|
+
|
42
|
+
it "returns the delegation signer records" do
|
43
|
+
response = subject.delegation_signer_records(account_id, domain_id)
|
44
|
+
|
45
|
+
expect(response).to be_a(Dnsimple::PaginatedResponse)
|
46
|
+
expect(response.data).to be_a(Array)
|
47
|
+
expect(response.data.size).to eq(1)
|
48
|
+
|
49
|
+
response.data.each do |result|
|
50
|
+
expect(result).to be_a(Dnsimple::Struct::DelegationSignerRecord)
|
51
|
+
expect(result.id).to be_a(Integer)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
it "exposes the pagination information" do
|
56
|
+
response = subject.delegation_signer_records(account_id, domain_id)
|
57
|
+
|
58
|
+
expect(response.respond_to?(:page)).to be_truthy
|
59
|
+
expect(response.page).to eq(1)
|
60
|
+
expect(response.per_page).to be_a(Integer)
|
61
|
+
expect(response.total_entries).to be_a(Integer)
|
62
|
+
expect(response.total_pages).to be_a(Integer)
|
63
|
+
end
|
64
|
+
|
65
|
+
context "when the domain does not exist" do
|
66
|
+
it "raises NotFoundError" do
|
67
|
+
stub_request(:get, %r{/v2}).
|
68
|
+
to_return(read_http_fixture("notfound-domain.http"))
|
69
|
+
|
70
|
+
expect {
|
71
|
+
subject.delegation_signer_records(account_id, domain_id)
|
72
|
+
}.to raise_error(Dnsimple::NotFoundError)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
describe "#all_delegation_signer_records" do
|
78
|
+
before do
|
79
|
+
stub_request(:get, %r{/v2/#{account_id}/domains/#{domain_id}/ds_records}).
|
80
|
+
to_return(read_http_fixture("listDelegationSignerRecords/success.http"))
|
81
|
+
end
|
82
|
+
|
83
|
+
let(:account_id) { 1010 }
|
84
|
+
let(:domain_id) { "example.com" }
|
85
|
+
|
86
|
+
it "delegates to client.paginate" do
|
87
|
+
expect(subject).to receive(:paginate).with(:delegation_signer_records, account_id, domain_id, foo: "bar")
|
88
|
+
subject.all_delegation_signer_records(account_id, domain_id, foo: "bar")
|
89
|
+
end
|
90
|
+
|
91
|
+
it "supports sorting" do
|
92
|
+
subject.all_delegation_signer_records(account_id, domain_id, sort: "id:asc,from:desc")
|
93
|
+
|
94
|
+
expect(WebMock).to have_requested(:get, "https://api.dnsimple.test/v2/#{account_id}/domains/#{domain_id}/ds_records?page=1&per_page=100&sort=id:asc,from:desc")
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
describe "#create_delegation_signer_record" do
|
99
|
+
let(:account_id) { 1010 }
|
100
|
+
let(:domain_id) { "example.com" }
|
101
|
+
|
102
|
+
before do
|
103
|
+
stub_request(:post, %r{/v2/#{account_id}/domains/#{domain_id}/ds_records$}).
|
104
|
+
to_return(read_http_fixture("createDelegationSignerRecord/created.http"))
|
105
|
+
end
|
106
|
+
|
107
|
+
let(:attributes) { { algorithm: "13", digest: "ABC123", digest_type: "2", keytag: "1111" } }
|
108
|
+
|
109
|
+
it "builds the correct request" do
|
110
|
+
subject.create_delegation_signer_record(account_id, domain_id, attributes)
|
111
|
+
|
112
|
+
expect(WebMock).to have_requested(:post, "https://api.dnsimple.test/v2/#{account_id}/domains/#{domain_id}/ds_records").
|
113
|
+
with(body: attributes).
|
114
|
+
with(headers: { 'Accept' => 'application/json' })
|
115
|
+
end
|
116
|
+
|
117
|
+
it "returns the delegation signer record" do
|
118
|
+
response = subject.create_delegation_signer_record(account_id, domain_id, attributes)
|
119
|
+
expect(response).to be_a(Dnsimple::Response)
|
120
|
+
|
121
|
+
result = response.data
|
122
|
+
expect(result).to be_a(Dnsimple::Struct::DelegationSignerRecord)
|
123
|
+
expect(result.id).to be_a(Integer)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
describe "#delegation_signer_record" do
|
128
|
+
let(:account_id) { 1010 }
|
129
|
+
let(:domain_id) { "example.com" }
|
130
|
+
let(:ds_record_id) { 24 }
|
131
|
+
|
132
|
+
before do
|
133
|
+
stub_request(:get, %r{/v2/#{account_id}/domains/#{domain_id}/ds_records.+$}).
|
134
|
+
to_return(read_http_fixture("getDelegationSignerRecord/success.http"))
|
135
|
+
end
|
136
|
+
|
137
|
+
it "builds the correct request" do
|
138
|
+
subject.delegation_signer_record(account_id, domain_id, ds_record_id)
|
139
|
+
|
140
|
+
expect(WebMock).to have_requested(:get, "https://api.dnsimple.test/v2/#{account_id}/domains/#{domain_id}/ds_records/#{ds_record_id}").
|
141
|
+
with(headers: { 'Accept' => 'application/json' })
|
142
|
+
end
|
143
|
+
|
144
|
+
it "returns the delegation signer record" do
|
145
|
+
response = subject.delegation_signer_record(account_id, domain_id, ds_record_id)
|
146
|
+
expect(response).to be_a(Dnsimple::Response)
|
147
|
+
|
148
|
+
result = response.data
|
149
|
+
expect(result).to be_a(Dnsimple::Struct::DelegationSignerRecord)
|
150
|
+
expect(result.id).to eq(24)
|
151
|
+
expect(result.domain_id).to eq(1010)
|
152
|
+
expect(result.algorithm).to eq("8")
|
153
|
+
expect(result.digest).to eq("C1F6E04A5A61FBF65BF9DC8294C363CF11C89E802D926BDAB79C55D27BEFA94F")
|
154
|
+
expect(result.digest_type).to eq("2")
|
155
|
+
expect(result.keytag).to eq("44620")
|
156
|
+
expect(result.created_at).to eq("2017-03-03T13:49:58Z")
|
157
|
+
expect(result.updated_at).to eq("2017-03-03T13:49:58Z")
|
158
|
+
end
|
159
|
+
|
160
|
+
context "when the delegation signer record does not exist" do
|
161
|
+
it "raises NotFoundError" do
|
162
|
+
stub_request(:get, %r{/v2}).
|
163
|
+
to_return(read_http_fixture("notfound-delegationsignerrecord.http"))
|
164
|
+
|
165
|
+
expect {
|
166
|
+
subject.delegation_signer_record(account_id, domain_id, ds_record_id)
|
167
|
+
}.to raise_error(Dnsimple::NotFoundError)
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
describe "#delete_delegation_signer_record" do
|
173
|
+
let(:account_id) { 1010 }
|
174
|
+
let(:domain_id) { "example.com" }
|
175
|
+
let(:ds_record_id) { 1 }
|
176
|
+
|
177
|
+
before do
|
178
|
+
stub_request(:delete, %r{/v2/#{account_id}/domains/#{domain_id}/ds_records/#{ds_record_id}$}).
|
179
|
+
to_return(read_http_fixture("deleteDelegationSignerRecord/success.http"))
|
180
|
+
end
|
181
|
+
|
182
|
+
it "builds the correct request" do
|
183
|
+
subject.delete_delegation_signer_record(account_id, domain_id, ds_record_id)
|
184
|
+
|
185
|
+
expect(WebMock).to have_requested(:delete, "https://api.dnsimple.test/v2/#{account_id}/domains/#{domain_id}/ds_records/#{ds_record_id}").
|
186
|
+
with(headers: { 'Accept' => 'application/json' })
|
187
|
+
end
|
188
|
+
|
189
|
+
it "returns nothing" do
|
190
|
+
response = subject.delete_delegation_signer_record(account_id, domain_id, ds_record_id)
|
191
|
+
expect(response).to be_a(Dnsimple::Response)
|
192
|
+
|
193
|
+
result = response.data
|
194
|
+
expect(result).to be_nil
|
195
|
+
end
|
196
|
+
|
197
|
+
context "when the delegation signer record does not exist" do
|
198
|
+
it "raises NotFoundError" do
|
199
|
+
stub_request(:delete, %r{/v2}).
|
200
|
+
to_return(read_http_fixture("notfound-delegationsignerrecord.http"))
|
201
|
+
|
202
|
+
expect {
|
203
|
+
subject.delete_delegation_signer_record(account_id, domain_id, ds_record_id)
|
204
|
+
}.to raise_error(Dnsimple::NotFoundError)
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
end
|
@@ -0,0 +1,122 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Dnsimple::Client, ".domains" do
|
4
|
+
|
5
|
+
subject { described_class.new(base_url: "https://api.dnsimple.test", access_token: "a1b2c3").domains }
|
6
|
+
|
7
|
+
describe "#enable_dnssec" do
|
8
|
+
let(:account_id) { 1010 }
|
9
|
+
let(:domain_id) { "example.com" }
|
10
|
+
|
11
|
+
before do
|
12
|
+
stub_request(:post, %r{/v2/#{account_id}/domains/#{domain_id}/dnssec}).
|
13
|
+
to_return(read_http_fixture("enableDnssec/success.http"))
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
it "builds the correct request" do
|
18
|
+
subject.enable_dnssec(account_id, domain_id)
|
19
|
+
|
20
|
+
expect(WebMock).to have_requested(:post, "https://api.dnsimple.test/v2/#{account_id}/domains/#{domain_id}/dnssec").
|
21
|
+
with(headers: { 'Accept' => 'application/json' })
|
22
|
+
end
|
23
|
+
|
24
|
+
it "returns the dnssec status" do
|
25
|
+
response = subject.enable_dnssec(account_id, domain_id)
|
26
|
+
expect(response).to be_a(Dnsimple::Response)
|
27
|
+
|
28
|
+
result = response.data
|
29
|
+
expect(result).to be_a(Dnsimple::Struct::Dnssec)
|
30
|
+
expect(result.enabled).to be_truthy
|
31
|
+
end
|
32
|
+
|
33
|
+
context "when the domain does not exist" do
|
34
|
+
it "raises NotFoundError" do
|
35
|
+
stub_request(:post, %r{/v2}).
|
36
|
+
to_return(read_http_fixture("notfound-domain.http"))
|
37
|
+
|
38
|
+
expect {
|
39
|
+
subject.enable_dnssec(account_id, domain_id)
|
40
|
+
}.to raise_error(Dnsimple::NotFoundError)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "#disable_dnssec" do
|
47
|
+
let(:account_id) { 1010 }
|
48
|
+
let(:domain_id) { "example.com" }
|
49
|
+
|
50
|
+
before do
|
51
|
+
stub_request(:delete, %r{/v2/#{account_id}/domains/#{domain_id}/dnssec}).
|
52
|
+
to_return(read_http_fixture("disableDnssec/success.http"))
|
53
|
+
end
|
54
|
+
|
55
|
+
|
56
|
+
it "builds the correct request" do
|
57
|
+
subject.disable_dnssec(account_id, domain_id)
|
58
|
+
|
59
|
+
expect(WebMock).to have_requested(:delete, "https://api.dnsimple.test/v2/#{account_id}/domains/#{domain_id}/dnssec").
|
60
|
+
with(headers: { 'Accept' => 'application/json' })
|
61
|
+
end
|
62
|
+
|
63
|
+
it "returns nothing" do
|
64
|
+
response = subject.disable_dnssec(account_id, domain_id)
|
65
|
+
expect(response).to be_a(Dnsimple::Response)
|
66
|
+
|
67
|
+
result = response.data
|
68
|
+
expect(result).to be_nil
|
69
|
+
end
|
70
|
+
|
71
|
+
context "when the domain does not exist" do
|
72
|
+
it "raises NotFoundError" do
|
73
|
+
stub_request(:delete, %r{/v2}).
|
74
|
+
to_return(read_http_fixture("notfound-domain.http"))
|
75
|
+
|
76
|
+
expect {
|
77
|
+
subject.disable_dnssec(account_id, domain_id)
|
78
|
+
}.to raise_error(Dnsimple::NotFoundError)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
describe "#get_dnssec" do
|
84
|
+
let(:account_id) { 1010 }
|
85
|
+
let(:domain_id) { "example.com" }
|
86
|
+
|
87
|
+
before do
|
88
|
+
stub_request(:get, %r{/v2/#{account_id}/domains/#{domain_id}/dnssec}).
|
89
|
+
to_return(read_http_fixture("getDnssec/success.http"))
|
90
|
+
end
|
91
|
+
|
92
|
+
|
93
|
+
it "builds the correct request" do
|
94
|
+
subject.get_dnssec(account_id, domain_id)
|
95
|
+
|
96
|
+
expect(WebMock).to have_requested(:get, "https://api.dnsimple.test/v2/#{account_id}/domains/#{domain_id}/dnssec").
|
97
|
+
with(headers: { 'Accept' => 'application/json' })
|
98
|
+
end
|
99
|
+
|
100
|
+
it "returns the dnssec status" do
|
101
|
+
response = subject.get_dnssec(account_id, domain_id)
|
102
|
+
expect(response).to be_a(Dnsimple::Response)
|
103
|
+
|
104
|
+
result = response.data
|
105
|
+
expect(result).to be_a(Dnsimple::Struct::Dnssec)
|
106
|
+
expect(result.enabled).to be_truthy
|
107
|
+
end
|
108
|
+
|
109
|
+
context "when the domain does not exist" do
|
110
|
+
it "raises NotFoundError" do
|
111
|
+
stub_request(:get, %r{/v2}).
|
112
|
+
to_return(read_http_fixture("notfound-domain.http"))
|
113
|
+
|
114
|
+
expect {
|
115
|
+
subject.get_dnssec(account_id, domain_id)
|
116
|
+
}.to raise_error(Dnsimple::NotFoundError)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
end
|
121
|
+
|
122
|
+
end
|
@@ -2,13 +2,14 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe Dnsimple::Client, ".oauth" do
|
4
4
|
|
5
|
-
subject { described_class.new(base_url: "https://api.dnsimple.test"
|
5
|
+
subject { described_class.new(base_url: "https://api.dnsimple.test").oauth }
|
6
6
|
|
7
7
|
|
8
8
|
describe "#exchange_authorization_for_token" do
|
9
9
|
let(:client_id) { "super-client" }
|
10
10
|
let(:client_secret) { "super-secret" }
|
11
11
|
let(:code) { "super-code" }
|
12
|
+
let(:state) { "super-state" }
|
12
13
|
|
13
14
|
before do
|
14
15
|
stub_request(:post, %r{/v2/oauth/access_token$}).
|
@@ -16,15 +17,15 @@ describe Dnsimple::Client, ".oauth" do
|
|
16
17
|
end
|
17
18
|
|
18
19
|
it "builds the correct request" do
|
19
|
-
subject.exchange_authorization_for_token(code, client_id, client_secret)
|
20
|
+
subject.exchange_authorization_for_token(code, client_id, client_secret, state: state)
|
20
21
|
|
21
22
|
expect(WebMock).to have_requested(:post, "https://api.dnsimple.test/v2/oauth/access_token").
|
22
|
-
with(body: { client_id: client_id, client_secret: client_secret, code: code, grant_type: "authorization_code" }).
|
23
|
+
with(body: { client_id: client_id, client_secret: client_secret, code: code, state: state, grant_type: "authorization_code" }).
|
23
24
|
with(headers: { 'Accept' => 'application/json' })
|
24
25
|
end
|
25
26
|
|
26
27
|
it "returns oauth token" do
|
27
|
-
result = subject.exchange_authorization_for_token(code, client_id, client_secret)
|
28
|
+
result = subject.exchange_authorization_for_token(code, client_id, client_secret, state: state)
|
28
29
|
|
29
30
|
expect(result).to be_a(Dnsimple::Struct::OauthToken)
|
30
31
|
expect(result.access_token).to eq("zKQ7OLqF5N1gylcJweA9WodA000BUNJD")
|
@@ -33,7 +34,6 @@ describe Dnsimple::Client, ".oauth" do
|
|
33
34
|
end
|
34
35
|
|
35
36
|
context "when state and redirect_uri are provided" do
|
36
|
-
let(:state) { "super-state" }
|
37
37
|
let(:redirect_uri) { "super-redirect-uri" }
|
38
38
|
|
39
39
|
it "builds the correct request" do
|