Skip to content

fix(ios): preserve URL percent-encoding through to PHP#93

Open
bkuhl wants to merge 7 commits intoNativePHP:mainfrom
bkuhl:fix/ios-preserve-url-encoding
Open

fix(ios): preserve URL percent-encoding through to PHP#93
bkuhl wants to merge 7 commits intoNativePHP:mainfrom
bkuhl:fix/ios-preserve-url-encoding

Conversation

@bkuhl
Copy link
Copy Markdown
Contributor

@bkuhl bkuhl commented Apr 13, 2026

Problem

Laravel's URL generator (route(), redirect(), etc.) percent-encodes path and query values. PHP expects to consume the URI with that encoding intact — the shape $_SERVER['REQUEST_URI'] and $_SERVER['QUERY_STRING'] would have behind a real HTTP server.

Android preserves the encoding via Uri.encodedPath (added in #24).

iOS does not. The current handler uses URL.path, which percent-decodes once before handing the URI to PHP:

let uri = request.url?.path ?? "/"

When Laravel generates a URL like /game-board/abc%2Fdef, PHP on iOS sees /game-board/abc/def. Reserved characters (/, +, $, *) and literal % from route parameters arrive as bare characters, breaking route matching — Symfony rejects URIs Laravel itself generated as malformed (HTTP 400).

The encoding Laravel produces and the encoding iOS NativePHP delivers do not match.

Fix

Use URLComponents.percentEncodedPath and .percentEncodedQuery — the iOS-equivalent of Android's Uri.encodedPath. PHP receives the URI in the same shape on both platforms, matching what Laravel and Symfony expect.

This PR also depends on #108 being merged, as 108 actually fails first before it reaches this point.

Test plan

  • Routes with reserved chars in path (/, +, $, *)
  • Routes with literal % in route parameter data
  • Long URLs (~3500 char real-world tokens)
  • Static asset routes
  • Routes without special characters

bkuhl added 2 commits April 13, 2026 09:20
Use URLComponents.percentEncodedPath instead of URL.path when
extracting the request URI in extractRequestData(). URL.path silently
decodes percent-encoded characters (%3A → :, %2B → +, %25 → %, etc.),
which causes PHP to receive a decoded path instead of the raw encoding
a real browser would send.

This is the iOS equivalent of the Android fix in NativePHP#24, where
Uri.getPath() was replaced with Uri.getEncodedPath().
WKWebView normalizes URLs for custom scheme handlers by decoding
percent-encoded characters before passing them to WKURLSchemeHandler.
For example, %253A in an HTML href becomes %3A by the time
extractRequestData() runs. This is fundamentally different from Android
where WebResourceRequest preserves the original encoding.

To compensate, re-encode each path segment using only RFC 3986
unreserved characters (A-Za-z0-9-._~). This produces a maximally-
encoded URL that rawurldecode() in PHP resolves identically to the
original, achieving parity with browser behavior and the Android fix
in NativePHP#24.

Also apply the same re-encoding to redirect Location header paths,
which bypass extractRequestData() and would otherwise pass decoded
URIs back to PHP.

Replaces the previous URLComponents.percentEncodedPath approach which
did not work because URLComponents also receives the already-decoded
URL from WKWebView.
@bkuhl bkuhl changed the title fix(ios): preserve URL encoding when extracting request URI fix(ios): re-encode URL path segments to preserve percent-encoding Apr 14, 2026
bkuhl added 5 commits April 14, 2026 10:58
Location headers come directly from PHP's HTTP response as raw strings.
They never pass through WebKit's URL normalization, so re-encoding them
adds an unwanted extra level of encoding that breaks URLs with
percent-encoded characters.

The re-encoding fix only belongs in extractRequestData() where WKWebView
has already decoded the URL before passing it to the scheme handler.
Replace manual absoluteString parsing with URLComponents.percentEncodedPath
and custom character whitelist with .urlPathAllowed. Same behavior, less
fragile, and -11 lines.
The guard at the top of extractRequestData already ensures request.url
is non-nil.
@bkuhl bkuhl changed the title fix(ios): re-encode URL path segments to preserve percent-encoding fix(ios): preserve URL percent-encoding through to PHP Apr 28, 2026
@bkuhl bkuhl marked this pull request as ready for review April 28, 2026 13:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant