Fix platformLocation path and search dropping (#126232)

This PR fixes the dropping of both the `path` and `search` fields from the platform location in the URL when using Flutter Web and brings it in par with similar technologies (e.g. React Router).
It allows developers to keep the original path and/or search parameters in the URL, which are perfectly valid even while fragment routing is present.

**Example use case:**
Call a Flutter Web app with initial config parameters in the URL: 
`http://my-flutter.app/?skipIntro=true`

**Example:**
Before initial routing:
`http://localhost:45389/?foo=bar`
After routing:
`http://localhost:45389/#/menu`
After routing (with fix):
`http://localhost:45389/?foo=bar#menu`

Fixes #116415
This commit is contained in:
Severin 2023-05-09 18:38:49 +02:00 committed by GitHub
parent 8a7ded7b25
commit cab29b2034
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 20 additions and 4 deletions

View File

@ -99,11 +99,10 @@ class HashUrlStrategy extends ui_web.UrlStrategy {
String prepareExternalUrl(String internalUrl) { String prepareExternalUrl(String internalUrl) {
// It's convention that if the hash path is empty, we omit the `#`; however, // It's convention that if the hash path is empty, we omit the `#`; however,
// if the empty URL is pushed it won't replace any existing fragment. So // if the empty URL is pushed it won't replace any existing fragment. So
// when the hash path is empty, we instead return the location's path and // when the hash path is empty, we still return the location's path and
// query. // query.
return internalUrl.isEmpty return '${_platformLocation.pathname}${_platformLocation.search}'
? '${_platformLocation.pathname}${_platformLocation.search}' '${internalUrl.isEmpty ? '' : '#$internalUrl'}';
: '#$internalUrl';
} }
@override @override

View File

@ -46,6 +46,23 @@ void main() {
location.hash = '#'; location.hash = '#';
expect(strategy.getPath(), '/'); expect(strategy.getPath(), '/');
}); });
test('allows location path/search before fragment', () {
const String internalUrl = '/menu?foo=bar';
final HashUrlStrategy strategy = HashUrlStrategy(location);
location.pathname = '/';
expect(strategy.prepareExternalUrl(internalUrl), '/#/menu?foo=bar');
location.pathname = '/main';
expect(strategy.prepareExternalUrl(internalUrl), '/main#/menu?foo=bar');
location.search = '?foo=bar';
expect(
strategy.prepareExternalUrl(internalUrl),
'/main?foo=bar#/menu?foo=bar',
);
});
}); });
group('$PathUrlStrategy', () { group('$PathUrlStrategy', () {