@@ -264,17 +264,20 @@ h2 .scenario, a span.label.scenario { |
||
264 | 264 |
width: 200px; |
265 | 265 |
} |
266 | 266 |
|
267 |
-$services: twitter 37signals github tumblr dropbox wunderlist; |
|
268 |
-$service-colors: #55acee #8fc857 #444444 #2c4762 #007EE5 #ED5F27; |
|
267 |
+$service-colors: ( |
|
268 |
+ twitter: #55acee, |
|
269 |
+ 37signals: #8fc857, |
|
270 |
+ github: #444444, |
|
271 |
+ tumblr: #2c4762, |
|
272 |
+ dropbox: #007EE5, |
|
273 |
+ wunderlist: #ED5F27 |
|
274 |
+); |
|
269 | 275 |
|
270 | 276 |
@mixin services { |
271 |
- @each $service in $services { |
|
272 |
- $i: index($services, $service); |
|
273 |
- $service-color: nth($service-colors, $i); |
|
274 |
- |
|
277 |
+ @each $service, $color in $service-colors { |
|
275 | 278 |
&.service-#{$service} { |
276 | 279 |
color: #fff; |
277 |
- background-color: $service-color; |
|
280 |
+ background-color: $color; |
|
278 | 281 |
} |
279 | 282 |
} |
280 | 283 |
} |
@@ -2,8 +2,7 @@ module Agents |
||
2 | 2 |
class PostAgent < Agent |
3 | 3 |
include WebRequestConcern |
4 | 4 |
|
5 |
- cannot_create_events! |
|
6 |
- |
|
5 |
+ can_dry_run! |
|
7 | 6 |
default_schedule "never" |
8 | 7 |
|
9 | 8 |
description <<-MD |
@@ -15,6 +14,9 @@ module Agents |
||
15 | 14 |
|
16 | 15 |
By default, non-GETs will be sent with form encoding (`application/x-www-form-urlencoded`). Change `content_type` to `json` to send JSON instead. Change `content_type` to `xml` to send XML, where the name of the root element may be specified using `xml_root`, defaulting to `post`. |
17 | 16 |
|
17 |
+ If `emit_events` is set to `true`, the server response will be emitted as an Event and can be fed to a WebsiteAgent for parsing (using its `data_from_event` and `type` options). No data processing |
|
18 |
+ will be attempted by this Agent, so the Event's "body" value will always be raw text. |
|
19 |
+ |
|
18 | 20 |
Other Options: |
19 | 21 |
|
20 | 22 |
* `headers` - When present, it should be a hash of headers to send with the request. |
@@ -23,7 +25,17 @@ module Agents |
||
23 | 25 |
* `user_agent` - A custom User-Agent name (default: "Faraday v#{Faraday::VERSION}"). |
24 | 26 |
MD |
25 | 27 |
|
26 |
- event_description "Does not produce events." |
|
28 |
+ event_description <<-MD |
|
29 |
+ Events look like this: |
|
30 |
+ { |
|
31 |
+ "status": 200, |
|
32 |
+ "headers": { |
|
33 |
+ "Content-Type": "text/html", |
|
34 |
+ ... |
|
35 |
+ }, |
|
36 |
+ "body": "<html>Some data...</html>" |
|
37 |
+ } |
|
38 |
+ MD |
|
27 | 39 |
|
28 | 40 |
def default_options |
29 | 41 |
{ |
@@ -35,7 +47,8 @@ module Agents |
||
35 | 47 |
'key' => 'value', |
36 | 48 |
'something' => 'the event contained {{ somekey }}' |
37 | 49 |
}, |
38 |
- 'headers' => {} |
|
50 |
+ 'headers' => {}, |
|
51 |
+ 'emit_events' => 'false' |
|
39 | 52 |
} |
40 | 53 |
end |
41 | 54 |
|
@@ -56,6 +69,10 @@ module Agents |
||
56 | 69 |
errors.add(:base, "if provided, payload must be a hash") |
57 | 70 |
end |
58 | 71 |
|
72 |
+ if options.has_key?('emit_events') && boolify(options['emit_events']).nil? |
|
73 |
+ errors.add(:base, "if provided, emit_events must be true or false") |
|
74 |
+ end |
|
75 |
+ |
|
59 | 76 |
unless %w[post get put delete patch].include?(method) |
60 | 77 |
errors.add(:base, "method must be 'post', 'get', 'put', 'delete', or 'patch'") |
61 | 78 |
end |
@@ -112,9 +129,13 @@ module Agents |
||
112 | 129 |
error "Invalid method '#{method}'" |
113 | 130 |
end |
114 | 131 |
|
115 |
- faraday.run_request(method.to_sym, url, body, headers) { |request| |
|
132 |
+ response = faraday.run_request(method.to_sym, url, body, headers) { |request| |
|
116 | 133 |
request.params.update(params) if params |
117 | 134 |
} |
135 |
+ |
|
136 |
+ if boolify(interpolated['emit_events']) |
|
137 |
+ create_event payload: { body: response.body, headers: response.headers, status: response.status } |
|
138 |
+ end |
|
118 | 139 |
end |
119 | 140 |
end |
120 | 141 |
end |
@@ -59,6 +59,8 @@ module Agents |
||
59 | 59 |
"description": { "path": "results.data[*].description" } |
60 | 60 |
} |
61 | 61 |
|
62 |
+ The `extract` option can be skipped for the JSON type, causing the full JSON response to be returned. |
|
63 |
+ |
|
62 | 64 |
# Scraping Text |
63 | 65 |
|
64 | 66 |
When parsing text, each sub-hash should contain a `regexp` and `index`. Output text is matched against the regular expression repeatedly from the beginning through to the end, collecting a captured group specified by `index` in each match. Each index should be either an integer or a string name which corresponds to <code>(?<<em>name</em>>...)</code>. For example, to parse lines of <code><em>word</em>: <em>definition</em></code>, the following should work: |
@@ -50,7 +50,7 @@ describe Agents::PostAgent do |
||
50 | 50 |
raise "unexpected Content-Type: #{content_type}" |
51 | 51 |
end |
52 | 52 |
end |
53 |
- { status: 200, body: "ok" } |
|
53 |
+ { status: 200, body: "<html>a webpage!</html>", headers: { 'Content-Type' => 'text/html' } } |
|
54 | 54 |
} |
55 | 55 |
end |
56 | 56 |
|
@@ -186,6 +186,40 @@ describe Agents::PostAgent do |
||
186 | 186 |
|
187 | 187 |
expect(@sent_requests[:get][0].data).to eq(@checker.options['payload'].to_query) |
188 | 188 |
end |
189 |
+ |
|
190 |
+ describe "emitting events" do |
|
191 |
+ context "when emit_events is not set to true" do |
|
192 |
+ it "does not emit events" do |
|
193 |
+ expect { |
|
194 |
+ @checker.check |
|
195 |
+ }.not_to change { @checker.events.count } |
|
196 |
+ end |
|
197 |
+ end |
|
198 |
+ |
|
199 |
+ context "when emit_events is set to true" do |
|
200 |
+ before do |
|
201 |
+ @checker.options['emit_events'] = 'true' |
|
202 |
+ @checker.save! |
|
203 |
+ end |
|
204 |
+ |
|
205 |
+ it "emits the response status" do |
|
206 |
+ expect { |
|
207 |
+ @checker.check |
|
208 |
+ }.to change { @checker.events.count }.by(1) |
|
209 |
+ expect(@checker.events.last.payload['status']).to eq 200 |
|
210 |
+ end |
|
211 |
+ |
|
212 |
+ it "emits the body" do |
|
213 |
+ @checker.check |
|
214 |
+ expect(@checker.events.last.payload['body']).to eq '<html>a webpage!</html>' |
|
215 |
+ end |
|
216 |
+ |
|
217 |
+ it "emits the response headers" do |
|
218 |
+ @checker.check |
|
219 |
+ expect(@checker.events.last.payload['headers']).to eq({ 'Content-Type' => 'text/html' }) |
|
220 |
+ end |
|
221 |
+ end |
|
222 |
+ end |
|
189 | 223 |
end |
190 | 224 |
|
191 | 225 |
describe "#working?" do |
@@ -286,5 +320,22 @@ describe Agents::PostAgent do |
||
286 | 320 |
@checker.options['headers'] = { "Authorization" => "foo bar" } |
287 | 321 |
expect(@checker).to be_valid |
288 | 322 |
end |
323 |
+ |
|
324 |
+ it "requires emit_events to be true or false" do |
|
325 |
+ @checker.options['emit_events'] = 'what?' |
|
326 |
+ expect(@checker).not_to be_valid |
|
327 |
+ |
|
328 |
+ @checker.options.delete('emit_events') |
|
329 |
+ expect(@checker).to be_valid |
|
330 |
+ |
|
331 |
+ @checker.options['emit_events'] = 'true' |
|
332 |
+ expect(@checker).to be_valid |
|
333 |
+ |
|
334 |
+ @checker.options['emit_events'] = 'false' |
|
335 |
+ expect(@checker).to be_valid |
|
336 |
+ |
|
337 |
+ @checker.options['emit_events'] = true |
|
338 |
+ expect(@checker).to be_valid |
|
339 |
+ end |
|
289 | 340 |
end |
290 | 341 |
end |