dart-lang / api.dart.dev

Dart API docs
https://api.dart.dev
BSD 3-Clause "New" or "Revised" License
19 stars 17 forks source link

Uri.parse(url) does not parse url properly when they start with wss #80

Closed misici234 closed 3 years ago

misici234 commented 3 years ago

I submitted the issue at https://github.com/flutter/flutter/issues/69410 but I was told to do it here.

This is very simple to reproduce. Go to https://dart.dev/#try-dart and enter following code main() { String url = 'wss://hello.world.com/myHub?v=abcdefgh'; Uri uri = Uri.parse(url); uri = Uri( scheme: uri.scheme == "wss" ? "https" : "http", userInfo: uri.userInfo, host: uri.host, port: uri.port, path: uri.path, query: uri.query, fragment: uri.fragment); print(uri.toString()); }

Actual results: https://hello.world.com:0/myHub?v=abcdefgh#

Expected results: https://hello.world.com/myHub?v=abcdefgh# There should be no port 0 for url scheme wss. In other words, if there is no port in the input url then don't use a default port; consider it to be null and return Uri without port.

Due to this bug websocket_impl.dart can't connect using WebSocket. In the websocket_impl.dart and method static Future connect obvious Exception occurs in the following line return _httpClient.openUrl("GET", uri).then((request) {

aam commented 3 years ago

Check out this paragraph from https://api.dart.dev/stable/2.10.3/dart-core/Uri/Uri.html:

The port part of the authority component is set through port. If port is omitted or null,
it implies the default port for the URI's scheme, and is equivalent to passing that port explicitly.
The recognized schemes, and their default ports, are "http" (80) and "https" (443).
All other schemes are considered as having zero as the default port.

So what you see seems as expected as wss: scheme default port is 0, which you then provide explicitly when you construct https: uri.

aam commented 3 years ago

Marking as working as intended

misici234 commented 3 years ago

OK, I can understand that one but this problem exists in websocket_impl.dart. I copied the code from this dart file and removed irrelevant block of code for this issue. When you call below method with url = 'wss://hello.world.com/myHub?v=abcdefgh'; it creates uri which string representation is 'https://hello.world.com:0/myHub?v=abcdefgh' and fails to call _httpClient.openUrl("GET", uri) because uri should be 'https://hello.world.com/myHub?v=abcdefgh' but not 'https://hello.world.com:0/myHub?v=abcdefgh'. Can you fix this bug in websocket_impl.dart , please?

class _WebSocketImpl extends Stream with _ServiceObject implements WebSocket { .... static Future connect( String url, Iterable? protocols, Map<String, dynamic>? headers, {CompressionOptions compression = CompressionOptions.compressionDefault}) { Uri uri = Uri.parse(url); if (uri.scheme != "ws" && uri.scheme != "wss") { throw new WebSocketException("Unsupported URL scheme '${uri.scheme}'"); } .... uri = new Uri( scheme: uri.scheme == "wss" ? "https" : "http", userInfo: uri.userInfo, host: uri.host, port: uri.port, path: uri.path, query: uri.query, fragment: uri.fragment); return _httpClient.openUrl("GET", uri).then((request) { if (uri.userInfo != null && !uri.userInfo.isEmpty) {