Titanium SDK 7.0/8.0: HTTPClient redirect header preservation diverges between NSURLSession and OkHttp backends
0 reputation · 12 Mar 2025, 23:49 UTC
0 reputation · 12 Mar 2025, 23:49 UTC
Since Titanium SDK 7.0 migrated iOS to NSURLSession and SDK 8.0 migrated Android to OkHttp, both backends enable HTTP keep-alive by default and follow redirects automatically. However, the handling of request headers — particularly Authorization — on cross-origin redirects differs between the underlying platform stacks. NSURLSession may drop Authorization headers when redirecting across origins, while OkHttp preserves headers per RFC 7231 up to its 20-redirect limit. Titanium does not expose a unified redirect policy API to control or inspect this behavior.
Applications that rely on consistent auth-header forwarding through redirect chains (e.g., OAuth flows, API gateways with intermediate 302s) cannot guarantee identical behavior on iOS and Android using the standard HTTPClient. The SDK changelogs for 7.0.0 and 8.0.0 document the backend switches but do not specify a cross-platform redirect contract. Workarounds such as disabling keep-alive or manually handling redirects via onreadystatechange defeat connection reuse benefits and increase latency.
What is the documented or observable behavior for Authorization header preservation on cross-origin redirects for each platform backend in Titanium SDK 12.x? Does setting validatesSecureCertificate=false or custom header manipulation via setRequestHeader alter the platform default? Is there a supported pattern to achieve parity without abandoning HTTPClient keep-alive?
32275 reputation · 13 Mar 2025, 02:30 UTC
On Titanium SDK 12.x there is no divergence to reconcile: both backends strip the Authorization header when following a redirect to a different origin (host, port, or scheme). iOS does it via NSURLSession's credential-leak protection, and Android does it via OkHttp's redirect follower, which implements the same rule. Neither validatesSecureCertificate=false nor setRequestHeader changes this, and the SDK exposes no redirect-policy API. The only supported route to parity with header preservation is manual redirect handling — which, as you suspected, costs you automatic connection reuse.
Confirmed: the 7.0.0 and 8.0.0 changelogs document the backend migrations (NSURLSession, OkHttp) but define no cross-platform redirect contract. Likely explanation, based on the underlying libraries' well-established defaults:
So the practical divergence you may have observed is usually in same-origin behavior, redirect limits, or cookie handling — not in cross-origin Authorization forwarding, where both stacks converge on stripping.
validatesSecureCertificate=false only relaxes TLS chain validation. It has no effect on redirect header logic, and it carries real security risk — don't use it as a workaround here.setRequestHeader('Authorization', ...) sets the header on the initial request. The platform stack removes it after the redirect decision, so re-setting it before send() changes nothing for the redirected hop.Since SDK 12.x offers no hook to inspect or override redirect policy, the reliable approach is to treat 3xx responses yourself:
this.status in onload for 301/302/303/307/308.Location response header, resolve it against the request URL, and enforce a redirect counter (e.g., max 5) to avoid loops.setRequestHeader applied again — now the header survives because you control each hop.Keep-alive still works at the platform layer for connections to the same host across your manual hops; what you lose is the single-call convenience and any intra-chain socket reuse the stack would have done. For an OAuth-style flow with one or two redirects, the added latency is typically one extra round trip — usually acceptable, but measure it if you chain many calls.
Because this behavior depends on the underlying libraries and could shift in future SDK releases, confirm it on your target versions:
validatesSecureCertificate=false and with an extra custom header to confirm neither changes the outcome.One caveat: if your redirect target is actually same-origin (only the path changes) and you still see the header dropped, that would contradict the expected behavior — capture the echoed headers and the exact SDK version before redesigning around it.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.