@@ -25,7 +25,10 @@ hideSchedule = -> |
||
| 25 | 25 |
$(".schedule-region select").hide()
|
| 26 | 26 |
$(".schedule-region .cannot-be-scheduled").show()
|
| 27 | 27 |
|
| 28 |
-showSchedule = -> |
|
| 28 |
+showSchedule = (defaultSchedule = null) -> |
|
| 29 |
+ $(".schedule-region select").show()
|
|
| 30 |
+ if defaultSchedule? |
|
| 31 |
+ $(".schedule-region select").val(defaultSchedule).change()
|
|
| 29 | 32 |
$(".schedule-region select").show()
|
| 30 | 33 |
$(".schedule-region .cannot-be-scheduled").hide()
|
| 31 | 34 |
|
@@ -145,7 +148,7 @@ $(document).ready -> |
||
| 145 | 148 |
$(".event-descriptions").html("").hide()
|
| 146 | 149 |
$.getJSON "/agents/type_details", { type: $(@).val() }, (json) =>
|
| 147 | 150 |
if json.can_be_scheduled |
| 148 |
- showSchedule() |
|
| 151 |
+ showSchedule(json.default_schedule) |
|
| 149 | 152 |
else |
| 150 | 153 |
hideSchedule() |
| 151 | 154 |
|
@@ -34,6 +34,7 @@ class AgentsController < ApplicationController |
||
| 34 | 34 |
agent = Agent.build_for_type(params[:type], current_user, {})
|
| 35 | 35 |
render :json => {
|
| 36 | 36 |
:can_be_scheduled => agent.can_be_scheduled?, |
| 37 |
+ :default_schedule => agent.default_schedule, |
|
| 37 | 38 |
:can_receive_events => agent.can_receive_events?, |
| 38 | 39 |
:can_create_events => agent.can_create_events?, |
| 39 | 40 |
:options => agent.default_options, |
@@ -5,10 +5,14 @@ module Agents |
||
| 5 | 5 |
default_schedule "never" |
| 6 | 6 |
|
| 7 | 7 |
description <<-MD |
| 8 |
- A PostAgent receives events from other agents (or runs periodically), merges those events with the contents of `payload`, and sends the results as POST (or GET) requests to a specified url. |
|
| 8 |
+ A PostAgent receives events from other agents (or runs periodically), merges those events with the [Liquid-interpolated](https://github.com/cantino/huginn/wiki/Formatting-Events-using-Liquid) contents of `payload`, and sends the results as POST (or GET) requests to a specified url. To skip merging in the incoming event, but still send the interpolated payload, set `no_merge` to `true`. |
|
| 9 | 9 |
|
| 10 | 10 |
The `post_url` field must specify where you would like to send requests. Please include the URI scheme (`http` or `https`). |
| 11 | 11 |
|
| 12 |
+ The `method` used can be any of `get`, `post`, `put`, `patch`, and `delete`. |
|
| 13 |
+ |
|
| 14 |
+ By default, non-GETs will be sent with form encoding (`application/x-www-form-urlencoded`). Change `content_type` to `json` to send JSON instead. |
|
| 15 |
+ |
|
| 12 | 16 |
The `headers` field is optional. When present, it should be a hash of headers to send with the request. |
| 13 | 17 |
MD |
| 14 | 18 |
|
@@ -17,10 +21,12 @@ module Agents |
||
| 17 | 21 |
def default_options |
| 18 | 22 |
{
|
| 19 | 23 |
'post_url' => "http://www.example.com", |
| 20 |
- 'expected_receive_period_in_days' => 1, |
|
| 24 |
+ 'expected_receive_period_in_days' => '1', |
|
| 25 |
+ 'content_type' => 'form', |
|
| 21 | 26 |
'method' => 'post', |
| 22 | 27 |
'payload' => {
|
| 23 |
- 'key' => 'value' |
|
| 28 |
+ 'key' => 'value', |
|
| 29 |
+ 'something' => 'the event contained {{ somekey }}'
|
|
| 24 | 30 |
}, |
| 25 | 31 |
'headers' => {}
|
| 26 | 32 |
} |
@@ -47,8 +53,12 @@ module Agents |
||
| 47 | 53 |
errors.add(:base, "if provided, payload must be a hash") |
| 48 | 54 |
end |
| 49 | 55 |
|
| 50 |
- unless %w[post get].include?(method) |
|
| 51 |
- errors.add(:base, "method must be 'post' or 'get'") |
|
| 56 |
+ unless %w[post get put delete patch].include?(method) |
|
| 57 |
+ errors.add(:base, "method must be 'post', 'get', 'put', 'delete', or 'patch'") |
|
| 58 |
+ end |
|
| 59 |
+ |
|
| 60 |
+ if options['no_merge'].present? && !%[true false].include?(options['no_merge'].to_s) |
|
| 61 |
+ errors.add(:base, "if provided, no_merge must be 'true' or 'false'") |
|
| 52 | 62 |
end |
| 53 | 63 |
|
| 54 | 64 |
unless headers.is_a?(Hash) |
@@ -58,7 +68,12 @@ module Agents |
||
| 58 | 68 |
|
| 59 | 69 |
def receive(incoming_events) |
| 60 | 70 |
incoming_events.each do |event| |
| 61 |
- handle (interpolated(event.payload)['payload'].presence || {}).merge(event.payload)
|
|
| 71 |
+ outgoing = interpolated(event.payload)['payload'].presence || {}
|
|
| 72 |
+ if interpolated['no_merge'].to_s == 'true' |
|
| 73 |
+ handle outgoing |
|
| 74 |
+ else |
|
| 75 |
+ handle outgoing.merge(event.payload) |
|
| 76 |
+ end |
|
| 62 | 77 |
end |
| 63 | 78 |
end |
| 64 | 79 |
|
@@ -76,7 +91,13 @@ module Agents |
||
| 76 | 91 |
|
| 77 | 92 |
def handle(data) |
| 78 | 93 |
if method == 'post' |
| 79 |
- post_data(data) |
|
| 94 |
+ post_data(data, Net::HTTP::Post) |
|
| 95 |
+ elsif method == 'put' |
|
| 96 |
+ post_data(data, Net::HTTP::Put) |
|
| 97 |
+ elsif method == 'delete' |
|
| 98 |
+ post_data(data, Net::HTTP::Delete) |
|
| 99 |
+ elsif method == 'patch' |
|
| 100 |
+ post_data(data, Net::HTTP::Patch) |
|
| 80 | 101 |
elsif method == 'get' |
| 81 | 102 |
get_data(data) |
| 82 | 103 |
else |
@@ -84,10 +105,17 @@ module Agents |
||
| 84 | 105 |
end |
| 85 | 106 |
end |
| 86 | 107 |
|
| 87 |
- def post_data(data) |
|
| 108 |
+ def post_data(data, request_type = Net::HTTP::Post) |
|
| 88 | 109 |
uri = generate_uri |
| 89 |
- req = Net::HTTP::Post.new(uri.request_uri, headers) |
|
| 90 |
- req.form_data = data |
|
| 110 |
+ req = request_type.new(uri.request_uri, headers) |
|
| 111 |
+ |
|
| 112 |
+ if interpolated['content_type'] == 'json' |
|
| 113 |
+ req.set_content_type('application/json', 'charset' => 'utf-8')
|
|
| 114 |
+ req.body = data.to_json |
|
| 115 |
+ else |
|
| 116 |
+ req.form_data = data |
|
| 117 |
+ end |
|
| 118 |
+ |
|
| 91 | 119 |
Net::HTTP.start(uri.hostname, uri.port, :use_ssl => uri.scheme == "https") { |http| http.request(req) }
|
| 92 | 120 |
end |
| 93 | 121 |
|
@@ -25,11 +25,25 @@ describe Agents::PostAgent do |
||
| 25 | 25 |
'somekey' => 'value' |
| 26 | 26 |
} |
| 27 | 27 |
} |
| 28 |
+ @requests = 0 |
|
| 29 |
+ @sent_requests = { Net::HTTP::Get => [], Net::HTTP::Post => [], Net::HTTP::Put => [], Net::HTTP::Delete => [], Net::HTTP::Patch => [] }
|
|
| 28 | 30 |
|
| 29 |
- @sent_posts = [] |
|
| 30 |
- @sent_gets = [] |
|
| 31 |
- stub.any_instance_of(Agents::PostAgent).post_data { |data| @sent_posts << data }
|
|
| 32 |
- stub.any_instance_of(Agents::PostAgent).get_data { |data| @sent_gets << data }
|
|
| 31 |
+ stub.any_instance_of(Agents::PostAgent).post_data { |data, type| @requests += 1; @sent_requests[type] << data }
|
|
| 32 |
+ stub.any_instance_of(Agents::PostAgent).get_data { |data| @requests += 1; @sent_requests[Net::HTTP::Get] << data }
|
|
| 33 |
+ end |
|
| 34 |
+ |
|
| 35 |
+ describe "making requests" do |
|
| 36 |
+ it "can make requests of each type" do |
|
| 37 |
+ { 'get' => Net::HTTP::Get, 'put' => Net::HTTP::Put,
|
|
| 38 |
+ 'post' => Net::HTTP::Post, 'patch' => Net::HTTP::Patch, |
|
| 39 |
+ 'delete' => Net::HTTP::Delete }.each.with_index do |(verb, type), index| |
|
| 40 |
+ @checker.options['method'] = verb |
|
| 41 |
+ @checker.should be_valid |
|
| 42 |
+ @checker.check |
|
| 43 |
+ @requests.should == index + 1 |
|
| 44 |
+ @sent_requests[type].length.should == 1 |
|
| 45 |
+ end |
|
| 46 |
+ end |
|
| 33 | 47 |
end |
| 34 | 48 |
|
| 35 | 49 |
describe "#receive" do |
@@ -45,11 +59,11 @@ describe Agents::PostAgent do |
||
| 45 | 59 |
lambda {
|
| 46 | 60 |
lambda {
|
| 47 | 61 |
@checker.receive([@event, event1]) |
| 48 |
- }.should change { @sent_posts.length }.by(2)
|
|
| 49 |
- }.should_not change { @sent_gets.length }
|
|
| 62 |
+ }.should change { @sent_requests[Net::HTTP::Post].length }.by(2)
|
|
| 63 |
+ }.should_not change { @sent_requests[Net::HTTP::Get].length }
|
|
| 50 | 64 |
|
| 51 |
- @sent_posts[0].should == @event.payload.merge('default' => 'value')
|
|
| 52 |
- @sent_posts[1].should == event1.payload |
|
| 65 |
+ @sent_requests[Net::HTTP::Post][0].should == @event.payload.merge('default' => 'value')
|
|
| 66 |
+ @sent_requests[Net::HTTP::Post][1].should == event1.payload |
|
| 53 | 67 |
end |
| 54 | 68 |
|
| 55 | 69 |
it "can make GET requests" do |
@@ -58,10 +72,19 @@ describe Agents::PostAgent do |
||
| 58 | 72 |
lambda {
|
| 59 | 73 |
lambda {
|
| 60 | 74 |
@checker.receive([@event]) |
| 61 |
- }.should change { @sent_gets.length }.by(1)
|
|
| 62 |
- }.should_not change { @sent_posts.length }
|
|
| 75 |
+ }.should change { @sent_requests[Net::HTTP::Get].length }.by(1)
|
|
| 76 |
+ }.should_not change { @sent_requests[Net::HTTP::Post].length }
|
|
| 63 | 77 |
|
| 64 |
- @sent_gets[0].should == @event.payload.merge('default' => 'value')
|
|
| 78 |
+ @sent_requests[Net::HTTP::Get][0].should == @event.payload.merge('default' => 'value')
|
|
| 79 |
+ end |
|
| 80 |
+ |
|
| 81 |
+ it "can skip merging the incoming event when no_merge is set, but it still interpolates" do |
|
| 82 |
+ @checker.options['no_merge'] = 'true' |
|
| 83 |
+ @checker.options['payload'] = {
|
|
| 84 |
+ 'key' => 'it said: {{ someotherkey.somekey }}'
|
|
| 85 |
+ } |
|
| 86 |
+ @checker.receive([@event]) |
|
| 87 |
+ @sent_requests[Net::HTTP::Post].first.should == { 'key' => 'it said: value' }
|
|
| 65 | 88 |
end |
| 66 | 89 |
end |
| 67 | 90 |
|
@@ -69,9 +92,9 @@ describe Agents::PostAgent do |
||
| 69 | 92 |
it "sends options['payload'] as a POST request" do |
| 70 | 93 |
lambda {
|
| 71 | 94 |
@checker.check |
| 72 |
- }.should change { @sent_posts.length }.by(1)
|
|
| 95 |
+ }.should change { @sent_requests[Net::HTTP::Post].length }.by(1)
|
|
| 73 | 96 |
|
| 74 |
- @sent_posts[0].should == @checker.options['payload'] |
|
| 97 |
+ @sent_requests[Net::HTTP::Post][0].should == @checker.options['payload'] |
|
| 75 | 98 |
end |
| 76 | 99 |
|
| 77 | 100 |
it "sends options['payload'] as a GET request" do |
@@ -79,10 +102,10 @@ describe Agents::PostAgent do |
||
| 79 | 102 |
lambda {
|
| 80 | 103 |
lambda {
|
| 81 | 104 |
@checker.check |
| 82 |
- }.should change { @sent_gets.length }.by(1)
|
|
| 83 |
- }.should_not change { @sent_posts.length }
|
|
| 105 |
+ }.should change { @sent_requests[Net::HTTP::Get].length }.by(1)
|
|
| 106 |
+ }.should_not change { @sent_requests[Net::HTTP::Post].length }
|
|
| 84 | 107 |
|
| 85 |
- @sent_gets[0].should == @checker.options['payload'] |
|
| 108 |
+ @sent_requests[Net::HTTP::Get][0].should == @checker.options['payload'] |
|
| 86 | 109 |
end |
| 87 | 110 |
end |
| 88 | 111 |
|
@@ -112,7 +135,7 @@ describe Agents::PostAgent do |
||
| 112 | 135 |
@checker.should_not be_valid |
| 113 | 136 |
end |
| 114 | 137 |
|
| 115 |
- it "should validate method as post or get, defaulting to post" do |
|
| 138 |
+ it "should validate method as post, get, put, patch, or delete, defaulting to post" do |
|
| 116 | 139 |
@checker.options['method'] = "" |
| 117 | 140 |
@checker.method.should == "post" |
| 118 | 141 |
@checker.should be_valid |
@@ -125,11 +148,35 @@ describe Agents::PostAgent do |
||
| 125 | 148 |
@checker.method.should == "get" |
| 126 | 149 |
@checker.should be_valid |
| 127 | 150 |
|
| 151 |
+ @checker.options['method'] = "patch" |
|
| 152 |
+ @checker.method.should == "patch" |
|
| 153 |
+ @checker.should be_valid |
|
| 154 |
+ |
|
| 128 | 155 |
@checker.options['method'] = "wut" |
| 129 | 156 |
@checker.method.should == "wut" |
| 130 | 157 |
@checker.should_not be_valid |
| 131 | 158 |
end |
| 132 | 159 |
|
| 160 |
+ it "should validate that no_merge is 'true' or 'false', if present" do |
|
| 161 |
+ @checker.options['no_merge'] = "" |
|
| 162 |
+ @checker.should be_valid |
|
| 163 |
+ |
|
| 164 |
+ @checker.options['no_merge'] = "true" |
|
| 165 |
+ @checker.should be_valid |
|
| 166 |
+ |
|
| 167 |
+ @checker.options['no_merge'] = "false" |
|
| 168 |
+ @checker.should be_valid |
|
| 169 |
+ |
|
| 170 |
+ @checker.options['no_merge'] = false |
|
| 171 |
+ @checker.should be_valid |
|
| 172 |
+ |
|
| 173 |
+ @checker.options['no_merge'] = true |
|
| 174 |
+ @checker.should be_valid |
|
| 175 |
+ |
|
| 176 |
+ @checker.options['no_merge'] = 'blarg' |
|
| 177 |
+ @checker.should_not be_valid |
|
| 178 |
+ end |
|
| 179 |
+ |
|
| 133 | 180 |
it "should validate payload as a hash, if present" do |
| 134 | 181 |
@checker.options['payload'] = "" |
| 135 | 182 |
@checker.should be_valid |