Files
baffle-hub/app/controllers/api/events_controller.rb

76 lines
2.1 KiB
Ruby

# frozen_string_literal: true
class Api::EventsController < ApplicationController
skip_before_action :verify_authenticity_token
# POST /api/:project_id/events
def create
project = authenticate_project!
return head :not_found unless project
# Parse the incoming WAF event data
event_data = parse_event_data(request)
# Create event asynchronously
ProcessWafEventJob.perform_later(
project_id: project.id,
event_data: event_data,
headers: extract_serializable_headers(request)
)
# Always return 200 OK to avoid agent retries
head :ok
rescue DsnAuthenticationService::AuthenticationError => e
Rails.logger.warn "DSN authentication failed: #{e.message}"
head :unauthorized
rescue JSON::ParserError => e
Rails.logger.error "Invalid JSON in event data: #{e.message}"
head :bad_request
end
private
def authenticate_project!
DsnAuthenticationService.authenticate(request, params[:project_id])
end
def parse_event_data(request)
# Handle different content types
content_type = request.content_type || "application/json"
case content_type
when /application\/json/
JSON.parse(request.body.read)
when /application\/x-www-form-urlencoded/
# Convert form data to JSON-like hash
request.request_parameters
else
# Try to parse as JSON anyway
JSON.parse(request.body.read)
end
rescue => e
Rails.logger.error "Failed to parse event data: #{e.message}"
{}
ensure
request.body.rewind if request.body.respond_to?(:rewind)
end
def extract_serializable_headers(request)
# Only extract the headers we need for analytics, avoiding IO objects
important_headers = %w[
User-Agent Content-Type Content-Length Accept
X-Forwarded-For X-Real-IP X-Forwarded-Proto
Authorization X-Baffle-Auth X-Sentry-Auth
Referer Accept-Language Accept-Encoding
]
headers = {}
important_headers.each do |header|
value = request.headers[header]
# Standardize headers to lower case during import phase
headers[header.downcase] = value if value.present?
end
headers
end
end