sdk icon indicating copy to clipboard operation
sdk copied to clipboard

HttpClient unhandled exception when handling redirects

Open emersion opened this issue 5 months ago • 3 comments

Given this code snippet:

import 'dart:io';
import 'dart:convert';

void main() async {
	var client = HttpClient();
	try {
		var req = await client.getUrl(Uri.parse('https://tinyurl.com/ircv3'));
		var resp = await req.close();
		final stringData = await resp.transform(utf8.decoder).join();
		print(stringData);
	} on Exception catch (err) {
		print('Failed to fetch URL: $err');
	}
}

The script crashes with the following uncaught exception, with no easy way to catch/prevent it:

Unhandled exception:
Invalid argument(s): Unsupported scheme 'ircs' in URI ircs://irc.libera.chat/
#0      _HttpClient._openUrl (dart:_http/http_impl.dart:3023:9)
#1      _HttpClient._openUrlFromRequest (dart:_http/http_impl.dart:3129:12)
#2      _HttpClientResponse.redirect (dart:_http/http_impl.dart:707:10)
#3      _HttpClientRequest._handleIncoming.<anonymous closure> (dart:_http/http_impl.dart:1590:27)
<asynchronous suspension>
#4      _HttpClientRequest._handleIncoming.<anonymous closure> (dart:_http/http_impl.dart:1608:7)
<asynchronous suspension>

I believe HttpClient should check that the redirect URI is valid and supported before trying to handle the redirection.

General info

  • Dart 3.8.0 (stable) (Wed May 14 09:07:14 2025 -0700) on "linux_x64"
  • on linux / Linux 6.14.6-arch1-1 #1 SMP PREEMPT_DYNAMIC Fri, 09 May 2025 17:36:18 +0000
  • locale is en_US.UTF-8

Project info

  • sdk constraint: '^3.0.0'
  • dependencies: app_links, async, characters, connectivity_plus, dynamic_color, file_selector, firebase_core, firebase_messaging, flutter, flutter_apns_only, flutter_background, flutter_flipped_autocomplete, flutter_local_notifications, geolocator, hex, html, image_picker, linkify, mime, path, provider, scrollable_positioned_list, sentry, share_handler, share_plus, shared_preferences, shared_preferences_android, sqflite, sqflite_common_ffi, unicode_emojis, unifiedpush, url_launcher, webcrypto
  • dev_dependencies: flutter_lints
  • elided dependencies: 1

Process info

No Dart processes found.

emersion avatar Jun 05 '25 15:06 emersion

cc @brianquinlan

devoncarew avatar Jun 05 '25 15:06 devoncarew

Hey @emersion,

HttpClient should probably throw HttpException in that case (which is technically a breaking change but probably wouldn't effect many people in practice).

But the reason that your code isn't catching the error is because ArgumentError isn't a subclass of Exception.

The code will behave as you except, if you change the catch line to:

  } catch (err) {
    print('Failed to fetch URL: $err');
  }
}

brianquinlan avatar Jun 05 '25 19:06 brianquinlan

Ah, that makes sense! Yeah, I completely agree that throwing a regular exception is the right thing to do here.

emersion avatar Jun 05 '25 20:06 emersion