Skip to content

Uri.parse and Uri constructor fail to handle RFC 3986 IPvFuture host syntax #60483

@bivens-dev

Description

@bivens-dev

General Dart info

  • Dart 3.8.0-171.0.dev (dev) (Wed Mar 5 16:03:11 2025 -0800) on "linux_x64"
  • on linux / Linux 6.6.72+ 1 SMP PREEMPT_DYNAMIC Sat Mar 22 08:54:41 UTC 2025
  • locale is en_US.UTF-8

Description:

The Uri.parse function and the Uri(...) constructor currently fail to correctly handle the IPvFuture IP literal syntax defined in RFC 3986, Section 3.2.2.

When attempting to parse a URI string containing an IPvFuture host (e.g., "http://[v1.foo]/") or construct a Uri object explicitly with an IPvFuture host string (e.g., host: "[v1.foo]"), both methods throw FormatException instead of successfully creating a Uri object representing the valid input according to the standard.

Uri.parse throws FormatException: Invalid host character
The Uri constructor throws FormatException: Illegal IPv6 address, too few parts (appearing to misinterpret IPvFuture as a malformed IPv6 address).

Steps to Reproduce:

void main() {
  // A syntactically valid URI with an IPvFuture host according to RFC 3986
  final uriStringWithIPvFuture = 'http://[v1.valid-host-chars]/' ;
  final ipvFutureHost = '[v1.valid-host-chars]'; // v + hex + dot + unreserved/sub-delims/:

  print('Testing Uri.parse with IPvFuture:');
  try {
    final parsedUri = Uri.parse(uriStringWithIPvFuture);
    print('SUCCESS: Parsed Uri: $parsedUri');
    print('parsedUri.host: ${parsedUri.host}');
  } catch (e) {
    // Clean up the error message slightly for clarity in the bug report
    final errorMessage = e.toString().split('\n').first;
    print('FAILED with Exception: $errorMessage');
  }

  print('\nTesting Uri constructor with IPvFuture host:');
  try {
    final constructedUri = Uri(scheme: 'http', host: ipvFutureHost);
    print('SUCCESS: Constructed Uri: $constructedUri');
    print('constructedUri.host: ${constructedUri.host}');
  } catch (e) {
    final errorMessage = e.toString().split('\n').first;
    print('FAILED with Exception: $errorMessage');
  }

  // For comparison: Standard IPv6 works as expected
  print('\nTesting Uri constructor with standard IPv6 host:');
   try {
    final constructedUri = Uri(scheme: 'http', host: '[2001:db8::1]');
    print('SUCCESS: Constructed Uri: $constructedUri');
    print('constructedUri.host: ${constructedUri.host}');
  } catch (e) {
    final errorMessage = e.toString().split('\n').first;
    print('FAILED with Exception: $errorMessage');
  }
}

Result

Testing Uri.parse with IPvFuture:
  FAILED with Exception: FormatException: Illegal IPv6 address, too few parts

Testing Uri constructor with IPvFuture host:
  FAILED with Exception: FormatException: Illegal IPv6 address, too few parts

Testing Uri constructor with standard IPv6 host:
  SUCCESS: Constructed Uri: http://[2001:db8::1]
  constructedUri.host: 2001:db8::1

Additional Context:

This limitation prevents Dart applications and libraries from fully supporting the URI syntax as defined in RFC 3986. For example, libraries implementing RFC 3987 (IRIs) cannot correctly convert IRIs containing IPvFuture hosts to standard Uri objects using the core Dart libraries, requiring workarounds like disallowing this valid host format.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area-core-librarySDK core library issues (core, async, ...); use area-vm or area-web for platform specific libraries.library-coretype-enhancementA request for a change that isn't a bug

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions