Forward the caller's query bytes instead of encoding them twice

FixAPIService
Ya
7 Agosti 2026, 04:07 UTC
Mwandishi
Kamo
Ahadi ya
3c24d32

Every URL this gateway builds is assembled from getRequestURI() and getQueryString() — both already percent-encoded — and was then handed to RestTemplate as a String. RestTemplate's String overloads do not take a URL; they take a URI TEMPLATE, expanded by a DefaultUriBuilderFactory that RestTemplate configures in EncodingMode.URI_COMPONENT. That mode encodes every component, and '%' is not a pchar, so an existing escape was escaped again: %2C left as %252C. The upstream service decoded once and received the literal token A%2CB — one value where the caller sent two. forward() is the single funnel for every /api/<x>/** route, so /api/docs, /api/security, /api/kb, /api/media and the rest were all affected at once; values with no reserved character are a fixed point, which is what made it intermittent and easy to miss. toUpstreamUri() parses the URL and the URI overload of exchange() bypasses the template handler entirely, so the bytes cross the hop untouched. It is deliberately NOT a straight swap to URI.create. That method THROWS on a character which is illegal in a URI — a raw space, '|', '{}', a truncated escape — and such a request works TODAY precisely because the second encode repairs it. On IllegalArgumentException the helper returns null and the caller hands the String to RestTemplate exactly as before, with a WARN naming the URL so the case is visible instead of silent. Correct traffic stops being mangled; malformed traffic behaves exactly as it did. All five exchange sites in this class — forward, forwardWebhook, forwardCallback and the two webhook POST helpers — go through one exchangeUpstream so the two encodings cannot drift per call site. Tests assert the URI that actually leaves RestTemplate, via MockRestServiceServer rather than the helper's return value alone, since the encoding happens inside RestTemplate: status=PENDING%2CIN_PROGRESS arrives with exactly one level of encoding and no %25 anywhere; the String overload is pinned as the thing that double-encoded it; a raw space, a truncated %2 and a {id} brace each fall back rather than throw; and an ordinary repeated-param query is unchanged either way. mvn -o test: 29 tests, 0 failures.

Mabadiliko yote

Je, unaona nini kuhusu usafiri?

Kila moja ya hizi updates ardhi katika nafasi yako ya kazi moja kwa moja. Kuanza bure na kuangalia kukua wiki baada ya wiki.

Kuwa Huru MileleMtazamo wa bei