mirror of
https://github.com/Fishwaldo/huginn.git
synced 2025-03-15 19:31:26 +00:00
Expand HTTP status agent (#1521)
* Add WIP support for HTTP headers * Actually pass the header to check_this_url * Fix an unmerged hunk * Fix some syntax errors * Fix an outdated variable name * Comment on which sections do what * Get rid of (another) unmerged hunk * Show a form element for the header field * Fix event emitter conditional * Adjust tests for header logic * Test for not returning a header * Refactor payload generation * Rename 'header' to 'headers' * Add multiple header support * Update HttpStatusAgent docs * Fix (some) failing tests * Fix remaining tests * Add specs for HttpStatusAgent's header code * Super tiny cleanups
This commit is contained in:
parent
371bfa34b7
commit
3c8d6655a3
2 changed files with 82 additions and 18 deletions
|
@ -12,11 +12,12 @@ module Agents
|
|||
|
||||
form_configurable :url
|
||||
form_configurable :disable_redirect_follow, type: :array, values: ['true', 'false']
|
||||
form_configurable :headers_to_save
|
||||
|
||||
description <<-MD
|
||||
The HttpStatusAgent will check a url and emit the resulting HTTP status code with the time that it waited for a reply.
|
||||
The HttpStatusAgent will check a url and emit the resulting HTTP status code with the time that it waited for a reply. Additionally, it will optionally emit the value of one or more specified headers.
|
||||
|
||||
Specify a `Url` and the Http Status Agent will produce an event with the http status code.
|
||||
Specify a `Url` and the Http Status Agent will produce an event with the HTTP status code. If you specify one or more `Headers to save` (comma-delimited) as well, that header or headers' value(s) will be included in the event.
|
||||
|
||||
The `disable redirect follow` option causes the Agent to not follow HTTP redirects. For example, setting this to `true` will cause an agent that receives a 301 redirect to `http://yahoo.com` to return a status of 301 instead of following the redirect and returning 200.
|
||||
MD
|
||||
|
@ -26,8 +27,11 @@ module Agents
|
|||
|
||||
{
|
||||
"url": "...",
|
||||
"status": "..."
|
||||
"elapsed_time": "..."
|
||||
"status": "...",
|
||||
"elapsed_time": "...",
|
||||
"headers": {
|
||||
"...": "..."
|
||||
}
|
||||
}
|
||||
MD
|
||||
|
||||
|
@ -46,29 +50,47 @@ module Agents
|
|||
errors.add(:base, "a url must be specified") unless options['url'].present?
|
||||
end
|
||||
|
||||
def header_array(str)
|
||||
(str || '').split(',').map(&:strip)
|
||||
end
|
||||
|
||||
def check
|
||||
check_this_url interpolated[:url]
|
||||
check_this_url interpolated[:url], header_array(interpolated[:headers_to_save])
|
||||
end
|
||||
|
||||
def receive(incoming_events)
|
||||
incoming_events.each do |event|
|
||||
interpolate_with(event) do
|
||||
check_this_url interpolated[:url]
|
||||
check_this_url interpolated[:url], header_array(interpolated[:headers_to_save])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def check_this_url(url)
|
||||
def check_this_url(url, local_headers)
|
||||
# Track time
|
||||
measured_result = TimeTracker.track { ping(url) }
|
||||
|
||||
payload = { 'url' => url, 'response_received' => false, 'elapsed_time' => measured_result.elapsed_time }
|
||||
|
||||
# Deal with failures
|
||||
if measured_result.result
|
||||
create_event payload: { 'url' => url, 'status' => measured_result.status.to_s, 'response_received' => true, 'elapsed_time' => measured_result.elapsed_time }
|
||||
payload.merge!({ 'response_received' => true, 'status' => measured_result.status.to_s })
|
||||
# Deal with headers
|
||||
if local_headers.present?
|
||||
header_results = measured_result.result.headers.select {|header, value| local_headers.include?(header)}
|
||||
# Fill in headers that we wanted, but weren't returned
|
||||
local_headers.each { |header| header_results[header] = nil unless header_results.has_key?(header) }
|
||||
payload.merge!({ 'headers' => header_results })
|
||||
end
|
||||
create_event payload: payload
|
||||
memory['last_status'] = measured_result.status.to_s
|
||||
else
|
||||
create_event payload: { 'url' => url, 'response_received' => false, 'elapsed_time' => measured_result.elapsed_time }
|
||||
create_event payload: payload
|
||||
memory['last_status'] = nil
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def ping(url)
|
||||
|
|
|
@ -7,6 +7,7 @@ describe 'HttpStatusAgent' do
|
|||
a.service = services(:generic)
|
||||
a.user = users(:jane)
|
||||
a.options['url'] = 'http://google.com'
|
||||
a.options['headers_to_save'] = 'Server'
|
||||
a.save!
|
||||
|
||||
def a.interpolate_with(e, &block)
|
||||
|
@ -76,11 +77,12 @@ describe 'HttpStatusAgent' do
|
|||
before do
|
||||
|
||||
def agent.interpolated
|
||||
@interpolated ||= { :url => SecureRandom.uuid }
|
||||
@interpolated ||= { :url => SecureRandom.uuid, :headers_to_save => '' }
|
||||
end
|
||||
|
||||
def agent.check_this_url url
|
||||
def agent.check_this_url url, local_headers
|
||||
@url = url
|
||||
@local_headers = local_headers
|
||||
end
|
||||
|
||||
def agent.checked_url
|
||||
|
@ -103,10 +105,12 @@ describe 'HttpStatusAgent' do
|
|||
let(:successful_url) { SecureRandom.uuid }
|
||||
|
||||
let(:status_code) { 200 }
|
||||
let(:header) { SecureRandom.uuid }
|
||||
let(:header_value) { SecureRandom.uuid }
|
||||
|
||||
let(:event_with_a_successful_ping) do
|
||||
agent.faraday.set(successful_url, Struct.new(:status).new(status_code))
|
||||
Event.new.tap { |e| e.payload = { url: successful_url } }
|
||||
agent.faraday.set(successful_url, Struct.new(:status, :headers).new(status_code, {}))
|
||||
Event.new.tap { |e| e.payload = { url: successful_url, headers_to_save: "" } }
|
||||
end
|
||||
|
||||
let(:events) do
|
||||
|
@ -138,6 +142,11 @@ describe 'HttpStatusAgent' do
|
|||
expect(agent.the_created_events[0][:payload]['elapsed_time']).not_to be_nil
|
||||
end
|
||||
|
||||
it "should not return a header" do
|
||||
agent.receive events
|
||||
expect(agent.the_created_events[0][:payload]['headers']).to be_nil
|
||||
end
|
||||
|
||||
describe "but the status code is not 200" do
|
||||
let(:status_code) { 500 }
|
||||
|
||||
|
@ -160,8 +169,8 @@ describe 'HttpStatusAgent' do
|
|||
describe "but the ping returns a status code of 0" do
|
||||
|
||||
let(:event_with_a_successful_ping) do
|
||||
agent.faraday.set(successful_url, Struct.new(:status).new(0))
|
||||
Event.new.tap { |e| e.payload = { url: successful_url } }
|
||||
agent.faraday.set(successful_url, Struct.new(:status, :headers).new(0, {}))
|
||||
Event.new.tap { |e| e.payload = { url: successful_url, headers_to_save: "" } }
|
||||
end
|
||||
|
||||
it "should create one event" do
|
||||
|
@ -190,8 +199,8 @@ describe 'HttpStatusAgent' do
|
|||
describe "but the ping returns a status code of -1" do
|
||||
|
||||
let(:event_with_a_successful_ping) do
|
||||
agent.faraday.set(successful_url, Struct.new(:status).new(-1))
|
||||
Event.new.tap { |e| e.payload = { url: successful_url } }
|
||||
agent.faraday.set(successful_url, Struct.new(:status, :headers).new(-1, {}))
|
||||
Event.new.tap { |e| e.payload = { url: successful_url, headers_to_save: "" } }
|
||||
end
|
||||
|
||||
it "should create one event" do
|
||||
|
@ -214,7 +223,7 @@ describe 'HttpStatusAgent' do
|
|||
describe "and with one event with a failing ping" do
|
||||
|
||||
let(:failing_url) { SecureRandom.uuid }
|
||||
let(:event_with_a_failing_ping) { Event.new.tap { |e| e.payload = { url: failing_url } } }
|
||||
let(:event_with_a_failing_ping) { Event.new.tap { |e| e.payload = { url: failing_url, headers_to_save: "" } } }
|
||||
|
||||
let(:events) do
|
||||
[event_with_a_successful_ping, event_with_a_failing_ping]
|
||||
|
@ -249,6 +258,39 @@ describe 'HttpStatusAgent' do
|
|||
|
||||
end
|
||||
|
||||
describe "with a header specified" do
|
||||
let(:event_with_a_successful_ping) do
|
||||
agent.faraday.set(successful_url, Struct.new(:status, :headers).new(status_code, {header => header_value}))
|
||||
Event.new.tap { |e| e.payload = { url: successful_url, headers_to_save: header } }
|
||||
end
|
||||
|
||||
it "should return the header value" do
|
||||
agent.receive events
|
||||
expect(agent.the_created_events[0][:payload]['headers']).not_to be_nil
|
||||
expect(agent.the_created_events[0][:payload]['headers'][header]).to eq(header_value)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
describe "with existing and non-existing headers specified" do
|
||||
let(:nonexistant_header) { SecureRandom.uuid }
|
||||
|
||||
let(:event_with_a_successful_ping) do
|
||||
agent.faraday.set(successful_url, Struct.new(:status, :headers).new(status_code, {header => header_value}))
|
||||
Event.new.tap { |e| e.payload = { url: successful_url, headers_to_save: header + "," + nonexistant_header } }
|
||||
end
|
||||
|
||||
it "should return the existing header's value" do
|
||||
agent.receive events
|
||||
expect(agent.the_created_events[0][:payload]['headers'][header]).to eq(header_value)
|
||||
end
|
||||
|
||||
it "should return nil for the nonexistant header" do
|
||||
agent.receive events
|
||||
expect(agent.the_created_events[0][:payload]['headers'][nonexistant_header]).to be_nil
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
describe "validations" do
|
||||
|
|
Loading…
Add table
Reference in a new issue