cover/Elixir.DaProductAppWeb.Plugs.ConditionalBodyReader.html

1 defmodule DaProductAppWeb.Plugs.ConditionalBodyReader do
2 @moduledoc """
3 Custom body reader that captures raw body for NPCI UPI routes
4 before other plugs can consume it.
5 """
6
7 import Plug.Conn
8
9 10 def init(opts), do: opts
10
11 def call(conn, _opts) do
12 10 if is_npci_route?(conn.request_path) do
13 require Logger
14
:-(
Logger.info("ConditionalBodyReader: Processing NPCI route #{conn.request_path}")
15
16
:-(
case read_body(conn) do
17 {:ok, body, conn} when body != "" ->
18
:-(
Logger.info("ConditionalBodyReader: Successfully read body of size #{byte_size(body)}")
19
:-(
Logger.debug("ConditionalBodyReader: Body content: #{inspect(body)}")
20 conn
21
:-(
|> assign(:raw_body, body)
22
23 {:ok, "", conn} ->
24
:-(
Logger.warning("ConditionalBodyReader: Empty body received")
25 conn
26
:-(
|> assign(:raw_body, "")
27
28 {:error, reason} ->
29
:-(
Logger.error("ConditionalBodyReader: Error reading body: #{inspect(reason)}")
30
:-(
conn
31 end
32 else
33 # Not an NPCI route, pass through unchanged
34 10 conn
35 end
36 end
37
38 defp is_npci_route?(path) do
39
:-(
String.starts_with?(path, "/ReqHbt") or
40 10 String.starts_with?(path, "/ReqPay") or
41 10 String.starts_with?(path, "/ReqValQr") or
42 10 String.starts_with?(path, "/ReqChkTxn") or
43 10 String.starts_with?(path, "/ReqRegMob") or
44 10 String.starts_with?(path, "/ReqOtp") or
45 10 String.starts_with?(path, "/ReqSetCre") or
46 10 String.starts_with?(path, "/ReqMandateConf") or
47 # Also allow API-prefixed UPI routes used by partners: /api/v1/upi/*
48 10 String.starts_with?(path, "/api/v1/upi/") or
49 # Some controllers may use lowercase endpoints like /api/v1/upi/reconciliation
50 10 String.starts_with?(path, "/api/v1/upi")
51 end
52 end
Line Hits Source