post_agent.rb 3.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. module Agents
  2. class PostAgent < Agent
  3. cannot_create_events!
  4. default_schedule "never"
  5. description <<-MD
  6. 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.
  7. The `post_url` field must specify where you would like to send requests. Please include the URI scheme (`http` or `https`).
  8. The `method` used can be any of `get`, `post`, `put`, `patch`, and `delete`.
  9. By default, non-GETs will be sent with form encoding (`application/x-www-form-urlencoded`). Change `content_type` to `json` to send JSON instead.
  10. The `headers` field is optional. When present, it should be a hash of headers to send with the request.
  11. MD
  12. event_description "Does not produce events."
  13. def default_options
  14. {
  15. 'post_url' => "http://www.example.com",
  16. 'expected_receive_period_in_days' => 1,
  17. 'content_type' => 'form',
  18. 'method' => 'post',
  19. 'payload' => {
  20. 'key' => 'value'
  21. },
  22. 'headers' => {}
  23. }
  24. end
  25. def working?
  26. last_receive_at && last_receive_at > interpolated['expected_receive_period_in_days'].to_i.days.ago && !recent_error_logs?
  27. end
  28. def method
  29. (interpolated['method'].presence || 'post').to_s.downcase
  30. end
  31. def headers
  32. interpolated['headers'].presence || {}
  33. end
  34. def validate_options
  35. unless options['post_url'].present? && options['expected_receive_period_in_days'].present?
  36. errors.add(:base, "post_url and expected_receive_period_in_days are required fields")
  37. end
  38. if options['payload'].present? && !options['payload'].is_a?(Hash)
  39. errors.add(:base, "if provided, payload must be a hash")
  40. end
  41. unless %w[post get].include?(method)
  42. errors.add(:base, "method must be 'post' or 'get'")
  43. end
  44. unless headers.is_a?(Hash)
  45. errors.add(:base, "if provided, headers must be a hash")
  46. end
  47. end
  48. def receive(incoming_events)
  49. incoming_events.each do |event|
  50. handle (interpolated(event.payload)['payload'].presence || {}).merge(event.payload)
  51. end
  52. end
  53. def check
  54. handle interpolated['payload'].presence || {}
  55. end
  56. def generate_uri(params = nil)
  57. uri = URI interpolated[:post_url]
  58. uri.query = URI.encode_www_form(Hash[URI.decode_www_form(uri.query || '')].merge(params)) if params
  59. uri
  60. end
  61. private
  62. def handle(data)
  63. if method == 'post'
  64. post_data(data, Net::HTTP::Post)
  65. elsif method == 'put'
  66. post_data(data, Net::HTTP::Put)
  67. elsif method == 'delete'
  68. post_data(data, Net::HTTP::Delete)
  69. elsif method == 'patch'
  70. post_data(data, Net::HTTP::Patch)
  71. elsif method == 'get'
  72. get_data(data)
  73. else
  74. error "Invalid method '#{method}'"
  75. end
  76. end
  77. def post_data(data, request_type = Net::HTTP::Post)
  78. uri = generate_uri
  79. req = request_type.new(uri.request_uri, headers)
  80. if interpolated['content_type'] == 'json'
  81. req.set_content_type('application/json', 'charset' => 'utf-8')
  82. req.body = data.to_json
  83. else
  84. req.form_data = data
  85. end
  86. Net::HTTP.start(uri.hostname, uri.port, :use_ssl => uri.scheme == "https") { |http| http.request(req) }
  87. end
  88. def get_data(data)
  89. uri = generate_uri(data)
  90. req = Net::HTTP::Get.new(uri.request_uri, headers)
  91. Net::HTTP.start(uri.hostname, uri.port, :use_ssl => uri.scheme == "https") { |http| http.request(req) }
  92. end
  93. end
  94. end