Fix protobuf body parsing causing 400 errors on agent heartbeat
Plug.Parsers was trying to parse protobuf bodies as JSON, failing with 400 errors before the request reached the controller. Changes: - Added custom BodyReader to endpoint that skips parsing for protobuf - When Content-Type is application/x-protobuf, return empty body to parser - Controller reads the raw body directly for protobuf requests - Added error handling for protobuf decode failures in heartbeat endpoint This fixes the 400 errors agents were seeing on heartbeat requests.
This commit is contained in:
parent
31b906b0fa
commit
ae521d2108
2 changed files with 41 additions and 7 deletions
|
|
@ -98,14 +98,31 @@ defmodule ToweropsWeb.Api.AgentController do
|
|||
case get_req_header(conn, "content-type") do
|
||||
["application/x-protobuf" | _] ->
|
||||
# Decode protobuf
|
||||
{:ok, body, _conn} = Plug.Conn.read_body(conn)
|
||||
proto_metadata = HeartbeatMetadata.decode(body)
|
||||
case Plug.Conn.read_body(conn) do
|
||||
{:ok, body, _conn} ->
|
||||
try do
|
||||
proto_metadata = HeartbeatMetadata.decode(body)
|
||||
|
||||
%{
|
||||
"version" => proto_metadata.version,
|
||||
"hostname" => proto_metadata.hostname,
|
||||
"uptime_seconds" => proto_metadata.uptime_seconds
|
||||
}
|
||||
%{
|
||||
"version" => proto_metadata.version,
|
||||
"hostname" => proto_metadata.hostname,
|
||||
"uptime_seconds" => proto_metadata.uptime_seconds
|
||||
}
|
||||
rescue
|
||||
e ->
|
||||
require Logger
|
||||
|
||||
Logger.error("Failed to decode protobuf heartbeat: #{inspect(e)}")
|
||||
# Return empty metadata on decode error
|
||||
%{}
|
||||
end
|
||||
|
||||
{:error, reason} ->
|
||||
require Logger
|
||||
|
||||
Logger.error("Failed to read heartbeat body: #{inspect(reason)}")
|
||||
%{}
|
||||
end
|
||||
|
||||
_ ->
|
||||
# JSON format (fallback)
|
||||
|
|
|
|||
|
|
@ -49,8 +49,25 @@ defmodule ToweropsWeb.Endpoint do
|
|||
plug Plug.Parsers,
|
||||
parsers: [:urlencoded, :multipart, :json],
|
||||
pass: ["*/*"],
|
||||
body_reader: {ToweropsWeb.Endpoint.BodyReader, :read_body, []},
|
||||
json_decoder: Phoenix.json_library()
|
||||
|
||||
# Custom body reader that skips parsing for protobuf content type
|
||||
defmodule BodyReader do
|
||||
@moduledoc false
|
||||
def read_body(conn, opts) do
|
||||
case Plug.Conn.get_req_header(conn, "content-type") do
|
||||
["application/x-protobuf" | _] ->
|
||||
# Don't parse protobuf, let the controller handle it
|
||||
{:ok, "", conn}
|
||||
|
||||
_ ->
|
||||
# Use default body reader for other content types
|
||||
Plug.Conn.read_body(conn, opts)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
plug Plug.MethodOverride
|
||||
plug Plug.Head
|
||||
plug Plug.Session, @session_options
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue