@@ -245,23 +245,7 @@ public static Uri create(String s) {
245245 break ;
246246 }
247247 }
248- String authority = s .substring (authorityStart , i );
249-
250- // 3.2.1. UserInfo. Easy, because '@' cannot appear unencoded inside userinfo or host.
251- int userInfoEnd = authority .indexOf ('@' );
252- if (userInfoEnd >= 0 ) {
253- builder .setRawUserInfo (authority .substring (0 , userInfoEnd ));
254- }
255-
256- // 3.2.2/3. Host/Port.
257- int hostStart = userInfoEnd >= 0 ? userInfoEnd + 1 : 0 ;
258- int portStartColon = findPortStartColon (authority , hostStart );
259- if (portStartColon < 0 ) {
260- builder .setRawHost (authority .substring (hostStart ));
261- } else {
262- builder .setRawHost (authority .substring (hostStart , portStartColon ));
263- builder .setRawPort (authority .substring (portStartColon + 1 ));
264- }
248+ builder .setRawAuthority (s .substring (authorityStart , i ));
265249 }
266250
267251 // 3.3. Path: Whatever is left before '?' or '#'.
@@ -963,6 +947,51 @@ Builder setRawPort(String port) {
963947 return this ;
964948 }
965949
950+ /**
951+ * Specifies the userinfo, host and port URI components all at once using a single string.
952+ *
953+ * <p>This setter is "raw" in the sense that special characters in userinfo and host must be
954+ * passed in percent-encoded. See <a
955+ * href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.2">RFC 3986 3.2</a> for the set
956+ * of characters allowed in each component of an authority.
957+ *
958+ * <p>There's no "cooked" method to set authority like for other URI components because
959+ * authority is a *compound* URI component whose userinfo, host and port components are
960+ * delimited with special characters '@' and ':'. But the first two of those components can
961+ * themselves contain these delimiters so we need percent-encoding to parse them unambiguously.
962+ *
963+ * @param authority an RFC 3986 authority string that will be used to set userinfo, host and
964+ * port, or null to clear all three of those components
965+ */
966+ @ CanIgnoreReturnValue
967+ public Builder setRawAuthority (@ Nullable String authority ) {
968+ if (authority == null ) {
969+ setUserInfo (null );
970+ setHost ((String ) null );
971+ setPort (-1 );
972+ } else {
973+ // UserInfo. Easy because '@' cannot appear unencoded inside userinfo or host.
974+ int userInfoEnd = authority .indexOf ('@' );
975+ if (userInfoEnd >= 0 ) {
976+ setRawUserInfo (authority .substring (0 , userInfoEnd ));
977+ } else {
978+ setUserInfo (null );
979+ }
980+
981+ // Host/Port.
982+ int hostStart = userInfoEnd >= 0 ? userInfoEnd + 1 : 0 ;
983+ int portStartColon = findPortStartColon (authority , hostStart );
984+ if (portStartColon < 0 ) {
985+ setRawHost (authority .substring (hostStart ));
986+ setPort (-1 );
987+ } else {
988+ setRawHost (authority .substring (hostStart , portStartColon ));
989+ setRawPort (authority .substring (portStartColon + 1 ));
990+ }
991+ }
992+ return this ;
993+ }
994+
966995 /** Builds a new instance of {@link Uri} as specified by the setters. */
967996 public Uri build () {
968997 checkState (scheme != null , "Missing required scheme." );
0 commit comments