post_agent.rb 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. module Agents
  2. class PostAgent < Agent
  3. include WebRequestConcern
  4. cannot_create_events!
  5. default_schedule "never"
  6. description <<-MD
  7. 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`.
  8. The `post_url` field must specify where you would like to send requests. Please include the URI scheme (`http` or `https`).
  9. The `method` used can be any of `get`, `post`, `put`, `patch`, and `delete`.
  10. By default, non-GETs will be sent with form encoding (`application/x-www-form-urlencoded`). Change `content_type` to `json` to send JSON instead.
  11. Other Options:
  12. * `headers` - When present, it should be a hash of headers to send with the request.
  13. * `basic_auth` - Specify HTTP basic auth parameters: `"username:password"`, or `["username", "password"]`.
  14. * `user_agent` - A custom User-Agent name (default: "Faraday v#{Faraday::VERSION}").
  15. MD
  16. event_description "Does not produce events."
  17. def default_options
  18. {
  19. 'post_url' => "http://www.example.com",
  20. 'expected_receive_period_in_days' => '1',
  21. 'content_type' => 'form',
  22. 'method' => 'post',
  23. 'payload' => {
  24. 'key' => 'value',
  25. 'something' => 'the event contained {{ somekey }}'
  26. },
  27. 'headers' => {}
  28. }
  29. end
  30. def working?
  31. last_receive_at && last_receive_at > interpolated['expected_receive_period_in_days'].to_i.days.ago && !recent_error_logs?
  32. end
  33. def method
  34. (interpolated['method'].presence || 'post').to_s.downcase
  35. end
  36. def validate_options
  37. unless options['post_url'].present? && options['expected_receive_period_in_days'].present?
  38. errors.add(:base, "post_url and expected_receive_period_in_days are required fields")
  39. end
  40. if options['payload'].present? && !options['payload'].is_a?(Hash)
  41. errors.add(:base, "if provided, payload must be a hash")
  42. end
  43. unless %w[post get put delete patch].include?(method)
  44. errors.add(:base, "method must be 'post', 'get', 'put', 'delete', or 'patch'")
  45. end
  46. if options['no_merge'].present? && !%[true false].include?(options['no_merge'].to_s)
  47. errors.add(:base, "if provided, no_merge must be 'true' or 'false'")
  48. end
  49. unless headers.is_a?(Hash)
  50. errors.add(:base, "if provided, headers must be a hash")
  51. end
  52. validate_web_request_options!
  53. end
  54. def receive(incoming_events)
  55. incoming_events.each do |event|
  56. outgoing = interpolated(event)['payload'].presence || {}
  57. if boolify(interpolated['no_merge'])
  58. handle outgoing, event.payload
  59. else
  60. handle outgoing.merge(event.payload), event.payload
  61. end
  62. end
  63. end
  64. def check
  65. handle interpolated['payload'].presence || {}
  66. end
  67. private
  68. def handle(data, payload = {})
  69. url = interpolated(payload)[:post_url]
  70. headers = headers()
  71. case method
  72. when 'get', 'delete'
  73. params, body = data, nil
  74. when 'post', 'put', 'patch'
  75. params = nil
  76. case interpolated(payload)['content_type']
  77. when 'json'
  78. headers['Content-Type'] = 'application/json; charset=utf-8'
  79. body = data.to_json
  80. else
  81. body = data
  82. end
  83. else
  84. error "Invalid method '#{method}'"
  85. end
  86. faraday.run_request(method.to_sym, url, body, headers) { |request|
  87. request.params.update(params) if params
  88. }
  89. end
  90. end
  91. end