fix(ios): preserve URL percent-encoding through to PHP#93
Open
bkuhl wants to merge 7 commits intoNativePHP:mainfrom
Open
fix(ios): preserve URL percent-encoding through to PHP#93bkuhl wants to merge 7 commits intoNativePHP:mainfrom
bkuhl wants to merge 7 commits intoNativePHP:mainfrom
Conversation
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.
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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: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.percentEncodedPathand.percentEncodedQuery— the iOS-equivalent of Android'sUri.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
/,+,$,*)%in route parameter data