Forward the caller's query bytes on the public-facing proxies

FixAPIService
Ya
7 Agosti 2026, 05:02 UTC
Mwandishi
Kamo
Ahadi ya
21670e5

The gateway stopped double-encoding forwarded query strings in 3c24d32, but four other proxies in this service still concatenated already-percent-encoded bytes into a String and handed it to RestTemplate's String overload, which treats it as a URI template and encodes it a second time: %2C left as %252C, the upstream decoded once and got the literal token A%2CB. These are all public surfaces, so the failures are silent and land outside the company: - /api/public/esign/** — a Business-plan customer's status=SENT%2CCOMPLETED filter arrived at ESigService as one run-together token. - /api/public/webinar/** — same shape, MediaService side. - /api/social/webhook/{token} — the GET verification handshake IS the query string. A Meta verify token containing a space compared unequal downstream and MediaService answered 200-empty, so Meta dropped the subscription; X's crc_token is HMAC'd verbatim, so a mangled one deregisters the webhook. Safe to change: Meta's x-hub-signature-256 and X's signature are both HMAC over the raw BODY (MessengerAdapter:110, InstagramAdapter:114, XAdapter:151), which is forwarded as an untouched byte[]. No signature covers the URL. - /api/public-chat/** — the three handlers that append getQueryString(). The helper moves out of APIGatewayController into UpstreamUri so four classes share one parse-and-fall-back branch instead of four copies. A URL that URI.create rejects (raw space, |, {}, truncated escape — shapes that work today only BECAUSE of the second encode) still goes down the old String path with a WARN, so malformed traffic behaves exactly as it did. Public chat needed a second entry point rather than the gateway's. Its path is built from @PathVariables that Spring has already DECODED while its query is raw, so wrapping the concatenated URL in URI.create would have been a regression: a session token arriving as abc%23xyz decodes to abc#xyz, which URI.create accepts while silently truncating the path at the fragment. The halves are kept apart to the call site — the path encoded through the same UriComponentsBuilder call DefaultUriBuilderFactory makes, so those bytes are unchanged; the query left alone. The seven query-less handlers keep the String path untouched: no query, no double-encode to fix. Deliberately NOT changed, and they must stay that way — all encode exactly once today, so "fixing" them would 502 live traffic: subscription-catalog (splices a DECODED @RequestParam locale), subscription-promotions (fixed literal), validate-key in **************** (SHA-256 hex, a fixed point under URI_COMPONENT), LeadIntakePublicController (decoded UUID path variable, never calls getQueryString), the VOIP recording ingest POST (config literal, all input in the multipart body), and CapchaVerificationService (payload is in the JSON body).

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