Module: Webhooks::Outgoing::DeliveryAttemptSupport

Extended by:
ActiveSupport::Concern
Includes:
UriFiltering
Included in:
DeliveryAttempt
Defined in:
app/models/concerns/webhooks/outgoing/delivery_attempt_support.rb

Constant Summary collapse

SUCCESS_RESPONSE_CODES =
[200, 201, 202, 203, 204, 205, 206, 207, 226].freeze

Instance Method Summary collapse

Methods included from UriFiltering

#_allowed_uri?, #allowed_uri?, #resolve_ip_from_authoritative

Instance Method Details

#attemptObject



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'app/models/concerns/webhooks/outgoing/delivery_attempt_support.rb', line 31

def attempt
  uri = URI.parse(delivery.endpoint_url)

  if BulletTrain::OutgoingWebhooks.advanced_hostname_security
    unless allowed_uri?(uri)
      self.response_code = 0
      self.error_message = "URI is not allowed: " + uri
      save
      return false
    end
  end

  hostname = if BulletTrain::OutgoingWebhooks.advanced_hostname_security
    resolve_ip_from_authoritative(uri.hostname.downcase)
  else
    uri.hostname.downcase
  end

  # Net::HTTP will consider the url invalid (and not deliver the webhook) unless it ends with a '/'
  if uri.path == ""
    uri.path = "/"
  end

  http = Net::HTTP.new(hostname, uri.port)
  if uri.scheme == "https"
    http.use_ssl = true
    if BulletTrain::OutgoingWebhooks.http_verify_mode
      # Developers might need to set this to `OpenSSL::SSL::VERIFY_NONE` in some cases.
      http.verify_mode = BulletTrain::OutgoingWebhooks.http_verify_mode
    end
  end

  request = Net::HTTP::Post.new(uri.request_uri)
  request.add_field("Host", uri.host)
  request.add_field("Content-Type", "application/json")

  # Generate and add signature headers
  payload = delivery.event.payload
  signature_data = BulletTrain::OutgoingWebhooks::Signature
    .generate(payload, delivery.endpoint.webhook_secret)

  webhook_headers_namespace = Rails.configuration.outgoing_webhooks[:webhook_headers_namespace]
  request.add_field("#{webhook_headers_namespace}-Signature", signature_data[:signature])
  request.add_field("#{webhook_headers_namespace}-Timestamp", signature_data[:timestamp])
  request.add_field("#{webhook_headers_namespace}-Id", delivery.event.uuid)

  request.body = payload.to_json

  begin
    response = http.request(request)
    self.response_message = response.message
    self.response_code = response.code
    self.response_body = response.body
  rescue => exception
    self.response_code = 0
    self.error_message = exception.message
  end

  save
  successful?
end

#failed?Boolean

Returns:

  • (Boolean)


27
28
29
# File 'app/models/concerns/webhooks/outgoing/delivery_attempt_support.rb', line 27

def failed?
  !(successful? || still_attempting?)
end

#label_stringObject



93
94
95
# File 'app/models/concerns/webhooks/outgoing/delivery_attempt_support.rb', line 93

def label_string
  "#{attempt_number.ordinalize} Attempt"
end

#still_attempting?Boolean

Returns:

  • (Boolean)


19
20
21
# File 'app/models/concerns/webhooks/outgoing/delivery_attempt_support.rb', line 19

def still_attempting?
  error_message.nil? && response_code.nil?
end

#successful?Boolean

Returns:

  • (Boolean)


23
24
25
# File 'app/models/concerns/webhooks/outgoing/delivery_attempt_support.rb', line 23

def successful?
  SUCCESS_RESPONSE_CODES.include?(response_code)
end