| @@ -1,5 +1,7 @@ | ||
| 1 | 1 | module Agents | 
| 2 | 2 | class PostAgent < Agent | 
| 3 | + include WebRequestConcern | |
| 4 | + | |
| 3 | 5 | cannot_create_events! | 
| 4 | 6 |  | 
| 5 | 7 | default_schedule "never" | 
| @@ -13,7 +15,11 @@ module Agents | ||
| 13 | 15 |  | 
| 14 | 16 | 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 | 17 |  | 
| 16 | - The `headers` field is optional. When present, it should be a hash of headers to send with the request. | |
| 18 | + Other Options: | |
| 19 | + | |
| 20 | + * `headers` - When present, it should be a hash of headers to send with the request. | |
| 21 | + * `basic_auth` - Specify HTTP basic auth parameters: `"username:password"`, or `["username", "password"]`. | |
| 22 | +        * `user_agent` - A custom User-Agent name (default: "Faraday v#{Faraday::VERSION}"). | |
| 17 | 23 | MD | 
| 18 | 24 |  | 
| 19 | 25 | event_description "Does not produce events." | 
| @@ -40,10 +46,6 @@ module Agents | ||
| 40 | 46 | (interpolated['method'].presence || 'post').to_s.downcase | 
| 41 | 47 | end | 
| 42 | 48 |  | 
| 43 | - def headers | |
| 44 | -      interpolated['headers'].presence || {} | |
| 45 | - end | |
| 46 | - | |
| 47 | 49 | def validate_options | 
| 48 | 50 | unless options['post_url'].present? && options['expected_receive_period_in_days'].present? | 
| 49 | 51 | errors.add(:base, "post_url and expected_receive_period_in_days are required fields") | 
| @@ -64,6 +66,8 @@ module Agents | ||
| 64 | 66 | unless headers.is_a?(Hash) | 
| 65 | 67 | errors.add(:base, "if provided, headers must be a hash") | 
| 66 | 68 | end | 
| 69 | + | |
| 70 | + validate_web_request_options! | |
| 67 | 71 | end | 
| 68 | 72 |  | 
| 69 | 73 | def receive(incoming_events) | 
| @@ -81,48 +85,32 @@ module Agents | ||
| 81 | 85 |        handle interpolated['payload'].presence || {} | 
| 82 | 86 | end | 
| 83 | 87 |  | 
| 84 | -    def generate_uri(params = nil, payload = {}) | |
| 85 | - uri = URI interpolated(payload)[:post_url] | |
| 86 | - uri.query = URI.encode_www_form(Hash[URI.decode_www_form(uri.query || '')].merge(params)) if params | |
| 87 | - uri | |
| 88 | - end | |
| 89 | - | |
| 90 | 88 | private | 
| 91 | 89 |  | 
| 92 | 90 |      def handle(data, payload = {}) | 
| 93 | - if method == 'post' | |
| 94 | - post_data(data, payload, Net::HTTP::Post) | |
| 95 | - elsif method == 'put' | |
| 96 | - post_data(data, payload, Net::HTTP::Put) | |
| 97 | - elsif method == 'delete' | |
| 98 | - post_data(data, payload, Net::HTTP::Delete) | |
| 99 | - elsif method == 'patch' | |
| 100 | - post_data(data, payload, Net::HTTP::Patch) | |
| 101 | - elsif method == 'get' | |
| 102 | - get_data(data, payload) | |
| 91 | + url = interpolated(payload)[:post_url] | |
| 92 | + headers = headers() | |
| 93 | + | |
| 94 | + case method | |
| 95 | + when 'get', 'delete' | |
| 96 | + params, body = data, nil | |
| 97 | + when 'post', 'put', 'patch' | |
| 98 | + params = nil | |
| 99 | + | |
| 100 | + case interpolated(payload)['content_type'] | |
| 101 | + when 'json' | |
| 102 | + headers['Content-Type'] = 'application/json; charset=utf-8' | |
| 103 | + body = data.to_json | |
| 104 | + else | |
| 105 | + body = data | |
| 106 | + end | |
| 103 | 107 | else | 
| 104 | 108 |          error "Invalid method '#{method}'" | 
| 105 | 109 | end | 
| 106 | - end | |
| 107 | - | |
| 108 | - def post_data(data, payload, request_type = Net::HTTP::Post) | |
| 109 | - uri = generate_uri(nil, payload) | |
| 110 | - req = request_type.new(uri.request_uri, headers) | |
| 111 | - | |
| 112 | - if interpolated(payload)['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 | - | |
| 119 | -      Net::HTTP.start(uri.hostname, uri.port, :use_ssl => uri.scheme == "https") { |http| http.request(req) } | |
| 120 | - end | |
| 121 | 110 |  | 
| 122 | - def get_data(data, payload) | |
| 123 | - uri = generate_uri(data, payload) | |
| 124 | - req = Net::HTTP::Get.new(uri.request_uri, headers) | |
| 125 | -      Net::HTTP.start(uri.hostname, uri.port, :use_ssl => uri.scheme == "https") { |http| http.request(req) } | |
| 111 | +      faraday.run_request(method.to_sym, url, body, headers) { |request| | |
| 112 | + request.params.update(params) if params | |
| 113 | + } | |
| 126 | 114 | end | 
| 127 | 115 | end | 
| 128 | 116 | end | 
| @@ -2,16 +2,17 @@ require 'spec_helper' | ||
| 2 | 2 |  | 
| 3 | 3 | describe Agents::PostAgent do | 
| 4 | 4 | before do | 
| 5 | -    @valid_params = { | |
| 6 | - :name => "somename", | |
| 7 | -      :options => { | |
| 8 | - 'post_url' => "http://www.example.com", | |
| 9 | - 'expected_receive_period_in_days' => 1, | |
| 10 | -        'payload' => { | |
| 11 | - 'default' => 'value' | |
| 12 | - } | |
| 5 | +    @valid_options = { | |
| 6 | + 'post_url' => "http://www.example.com", | |
| 7 | + 'expected_receive_period_in_days' => 1, | |
| 8 | +      'payload' => { | |
| 9 | + 'default' => 'value' | |
| 13 | 10 | } | 
| 14 | 11 | } | 
| 12 | +    @valid_params = { | |
| 13 | + name: "somename", | |
| 14 | + options: @valid_options | |
| 15 | + } | |
| 15 | 16 |  | 
| 16 | 17 | @checker = Agents::PostAgent.new(@valid_params) | 
| 17 | 18 | @checker.user = users(:jane) | 
| @@ -26,22 +27,37 @@ describe Agents::PostAgent do | ||
| 26 | 27 | } | 
| 27 | 28 | } | 
| 28 | 29 | @requests = 0 | 
| 29 | -    @sent_requests = { Net::HTTP::Get => [], Net::HTTP::Post => [], Net::HTTP::Put => [], Net::HTTP::Delete => [], Net::HTTP::Patch => [] } | |
| 30 | - | |
| 31 | -    stub.any_instance_of(Agents::PostAgent).post_data { |data, payload, type| @requests += 1; @sent_requests[type] << data } | |
| 32 | -    stub.any_instance_of(Agents::PostAgent).get_data { |data, payload| @requests += 1; @sent_requests[Net::HTTP::Get] << data } | |
| 30 | +    @sent_requests = Hash.new { |hash, method| hash[method] = [] } | |
| 31 | + | |
| 32 | +    stub_request(:any, /:/).to_return { |request| | |
| 33 | + method = request.method | |
| 34 | + @requests += 1 | |
| 35 | + case method | |
| 36 | + when :get, :delete | |
| 37 | + data = request.uri.query | |
| 38 | + else | |
| 39 | + if data = request.body | |
| 40 | + case request.headers['Content-Type'] | |
| 41 | + when /json/ | |
| 42 | + data = ActiveSupport::JSON.decode(data) | |
| 43 | + end | |
| 44 | + end | |
| 45 | + end | |
| 46 | + @sent_requests[method] << data | |
| 47 | +      { status: 200, body: "ok" } | |
| 48 | + } | |
| 33 | 49 | end | 
| 34 | 50 |  | 
| 51 | + it_behaves_like WebRequestConcern | |
| 52 | + | |
| 35 | 53 | describe "making requests" do | 
| 36 | 54 | 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| | |
| 55 | + %w[get put post patch delete].each.with_index(1) do |verb, index| | |
| 40 | 56 | @checker.options['method'] = verb | 
| 41 | 57 | @checker.should be_valid | 
| 42 | 58 | @checker.check | 
| 43 | - @requests.should == index + 1 | |
| 44 | - @sent_requests[type].length.should == 1 | |
| 59 | + @requests.should == index | |
| 60 | + @sent_requests[verb.to_sym].length.should == 1 | |
| 45 | 61 | end | 
| 46 | 62 | end | 
| 47 | 63 | end | 
| @@ -59,11 +75,11 @@ describe Agents::PostAgent do | ||
| 59 | 75 |        lambda { | 
| 60 | 76 |          lambda { | 
| 61 | 77 | @checker.receive([@event, event1]) | 
| 62 | -        }.should change { @sent_requests[Net::HTTP::Post].length }.by(2) | |
| 63 | -      }.should_not change { @sent_requests[Net::HTTP::Get].length } | |
| 78 | +        }.should change { @sent_requests[:post].length }.by(2) | |
| 79 | +      }.should_not change { @sent_requests[:get].length } | |
| 64 | 80 |  | 
| 65 | -      @sent_requests[Net::HTTP::Post][0].should == @event.payload.merge('default' => 'value') | |
| 66 | - @sent_requests[Net::HTTP::Post][1].should == event1.payload | |
| 81 | +      @sent_requests[:post][0].should == @event.payload.merge('default' => 'value').to_query | |
| 82 | + @sent_requests[:post][1].should == event1.payload.to_query | |
| 67 | 83 | end | 
| 68 | 84 |  | 
| 69 | 85 | it "can make GET requests" do | 
| @@ -72,10 +88,10 @@ describe Agents::PostAgent do | ||
| 72 | 88 |        lambda { | 
| 73 | 89 |          lambda { | 
| 74 | 90 | @checker.receive([@event]) | 
| 75 | -        }.should change { @sent_requests[Net::HTTP::Get].length }.by(1) | |
| 76 | -      }.should_not change { @sent_requests[Net::HTTP::Post].length } | |
| 91 | +        }.should change { @sent_requests[:get].length }.by(1) | |
| 92 | +      }.should_not change { @sent_requests[:post].length } | |
| 77 | 93 |  | 
| 78 | -      @sent_requests[Net::HTTP::Get][0].should == @event.payload.merge('default' => 'value') | |
| 94 | +      @sent_requests[:get][0].should == @event.payload.merge('default' => 'value').to_query | |
| 79 | 95 | end | 
| 80 | 96 |  | 
| 81 | 97 | it "can skip merging the incoming event when no_merge is set, but it still interpolates" do | 
| @@ -84,7 +100,7 @@ describe Agents::PostAgent do | ||
| 84 | 100 |          'key' => 'it said: {{ someotherkey.somekey }}' | 
| 85 | 101 | } | 
| 86 | 102 | @checker.receive([@event]) | 
| 87 | -      @sent_requests[Net::HTTP::Post].first.should == { 'key' => 'it said: value' } | |
| 103 | +      @sent_requests[:post].first.should == { 'key' => 'it said: value' }.to_query | |
| 88 | 104 | end | 
| 89 | 105 | end | 
| 90 | 106 |  | 
| @@ -92,9 +108,9 @@ describe Agents::PostAgent do | ||
| 92 | 108 | it "sends options['payload'] as a POST request" do | 
| 93 | 109 |        lambda { | 
| 94 | 110 | @checker.check | 
| 95 | -      }.should change { @sent_requests[Net::HTTP::Post].length }.by(1) | |
| 111 | +      }.should change { @sent_requests[:post].length }.by(1) | |
| 96 | 112 |  | 
| 97 | - @sent_requests[Net::HTTP::Post][0].should == @checker.options['payload'] | |
| 113 | + @sent_requests[:post][0].should == @checker.options['payload'].to_query | |
| 98 | 114 | end | 
| 99 | 115 |  | 
| 100 | 116 | it "sends options['payload'] as a GET request" do | 
| @@ -102,10 +118,10 @@ describe Agents::PostAgent do | ||
| 102 | 118 |        lambda { | 
| 103 | 119 |          lambda { | 
| 104 | 120 | @checker.check | 
| 105 | -        }.should change { @sent_requests[Net::HTTP::Get].length }.by(1) | |
| 106 | -      }.should_not change { @sent_requests[Net::HTTP::Post].length } | |
| 121 | +        }.should change { @sent_requests[:get].length }.by(1) | |
| 122 | +      }.should_not change { @sent_requests[:post].length } | |
| 107 | 123 |  | 
| 108 | - @sent_requests[Net::HTTP::Get][0].should == @checker.options['payload'] | |
| 124 | + @sent_requests[:get][0].should == @checker.options['payload'].to_query | |
| 109 | 125 | end | 
| 110 | 126 | end | 
| 111 | 127 |  | 
| @@ -208,34 +224,4 @@ describe Agents::PostAgent do | ||
| 208 | 224 | @checker.should be_valid | 
| 209 | 225 | end | 
| 210 | 226 | end | 
| 211 | - | |
| 212 | - describe "#generate_uri" do | |
| 213 | - it "merges params with any in the post_url" do | |
| 214 | - @checker.options['post_url'] = "http://example.com/a/path?existing_param=existing_value" | |
| 215 | -      uri = @checker.generate_uri("some_param" => "some_value", "another_param" => "another_value") | |
| 216 | - uri.request_uri.should == "/a/path?existing_param=existing_value&some_param=some_value&another_param=another_value" | |
| 217 | - end | |
| 218 | - | |
| 219 | - it "works fine with urls that do not have a query" do | |
| 220 | - @checker.options['post_url'] = "http://example.com/a/path" | |
| 221 | -      uri = @checker.generate_uri("some_param" => "some_value", "another_param" => "another_value") | |
| 222 | - uri.request_uri.should == "/a/path?some_param=some_value&another_param=another_value" | |
| 223 | - end | |
| 224 | - | |
| 225 | - it "just returns the post_uri when no params are given" do | |
| 226 | - @checker.options['post_url'] = "http://example.com/a/path?existing_param=existing_value" | |
| 227 | - uri = @checker.generate_uri | |
| 228 | - uri.host.should == 'example.com' | |
| 229 | - uri.scheme.should == 'http' | |
| 230 | - uri.request_uri.should == "/a/path?existing_param=existing_value" | |
| 231 | - end | |
| 232 | - | |
| 233 | - it "interpolates when receiving a payload" do | |
| 234 | -      @checker.options['post_url'] = "https://{{ domain }}/{{ variable }}?existing_param=existing_value" | |
| 235 | -      uri = @checker.generate_uri({ "some_param" => "some_value", "another_param" => "another_value" }, { 'domain' => 'google.com', 'variable' => 'a_variable' }) | |
| 236 | - uri.request_uri.should == "/a_variable?existing_param=existing_value&some_param=some_value&another_param=another_value" | |
| 237 | - uri.host.should == 'google.com' | |
| 238 | - uri.scheme.should == 'https' | |
| 239 | - end | |
| 240 | - end | |
| 241 | -end | |
| 227 | +end |