.NET, Maui, Android: getting Java exception for URI using POST

336 Views Asked by At

The problem

I'm using boilerplate code to create a resource (POST) in a .NET Maui application, and I'm getting an exception when I run this line of code:

 HttpResponseMessage response = await httpClient.SendAsync(message);

Here's the exception:

Java.Lang.IllegalArgumentException: Invalid input to toASCII: changed_for_privacy.com ---> Android.Icu.Text.StringPrepParseException: The input does not conform to the STD 3 ASCII rules

The Message variable is the URI of the POST. In this case, the URI has, of course, a URL. I believe the problem is that the URL contains and underscore character. Like, the message looks something like this:
https://my_site.com/proceed/to/endpoint

Based on the exception, the stacktrace (see below), and some Googling (see links at the end of this question), I believe that Android is having issues dealing with an underscore that's in the URL. There are other folks who've had similar problems, but I can't find anything in the last couple of years. There are solutions to the problem, but they are either not .NET or the solution is "Well, you shouldn't be using URLs with underscores".

To be clear, there's an underscore in the URL, not the URI.

Anyways, "not using a URL with an underscore in it" isn't an option that I have.

My Code

The code is fairly boilerplate:

namespace my_project.Service;
internal class MyService
{
    private readonly HttpClient httpClient;
    public MyService()
    {
        httpClient = new();
    }

    public async Task GetAuthTokenPOST()
    {
        AccessTokenBodyPost accessTokenBodyModel = new()
        {
            grant_type = "password",
            username = "username"
        };

        try
        {
            HttpRequestMessage message = new(HttpMethod.Post, "https://changed_for_privacy.com/core/connect/token");
            message.Content = JsonContent.Create(accessTokenBodyModel);

            // EXCEPTION THROWN ON THIS LINE
            HttpResponseMessage response = await httpClient.SendAsync(message);
        }
        catch (Exception ex)
        {
            await ExitProgram.ErrorExitProgram();
        }
    }
}

EDIT: Underscore in URL was the problem

I managed to get the folks to spin up an entire new test server without any underscores... and it works.

I suppose the lesson is: avoid underscores in URLs?

Here is more of the stack trace. (I can't post the entire thing -- Stack Overflow keeps giving me an error message when I try -- but I will try again if anyone wants to see it, even though it's basically just what I'm posting below repeated.)

Java.Lang.IllegalArgumentException: Invalid input to toASCII: changed_for_privacy.com
 ---> Android.Icu.Text.StringPrepParseException: The input does not conform to the STD 3 ASCII rules

  --- End of managed Android.Icu.Text.StringPrepParseException stack trace ---
The input does not conform to the STD 3 ASCII rules. line:  0. preContext:  . postContext: 3_identity

    at android.icu.impl.IDNA2003.convertToASCII(IDNA2003.java:218)
    at android.icu.impl.IDNA2003.convertIDNToASCII(IDNA2003.java:276)
    at android.icu.text.IDNA.convertIDNToASCII(IDNA.java:654)
    at com.android.icu.text.ExtendedIDNA.convertIDNToASCII(ExtendedIDNA.java:50)
    at java.net.IDN.toASCII(IDN.java:108)
    at javax.net.ssl.SNIHostName.<init>(SNIHostName.java:99)
    at com.android.org.conscrypt.Platform.getSSLParameters(Platform.java:187)
    at com.android.org.conscrypt.ConscryptEngine.getSSLParameters(ConscryptEngine.java:525)
    at com.android.org.conscrypt.ConscryptEngineSocket.getSSLParameters(ConscryptEngineSocket.java:186)
    at com.android.okhttp.internal.Platform.configureTlsExtensions(Platform.java:121)
    at com.android.okhttp.internal.io.RealConnection.connectTls(RealConnection.java:191)
    at com.android.okhttp.internal.io.RealConnection.connectSocket(RealConnection.java:153)
    at com.android.okhttp.internal.io.RealConnection.connect(RealConnection.java:116)
    at com.android.okhttp.internal.http.StreamAllocation.findConnection(StreamAllocation.java:186)
    at com.android.okhttp.internal.http.StreamAllocation.findHealthyConnection(StreamAllocation.java:128)
    at com.android.okhttp.internal.http.StreamAllocation.newStream(StreamAllocation.java:97)
    at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:289)
    at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:232)
    at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:465)
    at com.android.okhttp.internal.huc.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:131)
    at com.android.okhttp.internal.huc.DelegatingHttpsURLConnection.connect(DelegatingHttpsURLConnection.java:90)
    at com.android.okhttp.internal.huc.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:30)

  --- End of managed Android.Icu.Text.StringPrepParseException stack trace ---
The input does not conform to the STD 3 ASCII rules. line:  0. preContext:  . postContext: 3_identity

    at android.icu.impl.IDNA2003.convertToASCII(IDNA2003.java:218)
    at android.icu.impl.IDNA2003.convertIDNToASCII(IDNA2003.java:276)
    at android.icu.text.IDNA.convertIDNToASCII(IDNA.java:654)
    at com.android.icu.text.ExtendedIDNA.convertIDNToASCII(ExtendedIDNA.java:50)
    at java.net.IDN.toASCII(IDN.java:108)
    at javax.net.ssl.SNIHostName.<init>(SNIHostName.java:99)
    at com.android.org.conscrypt.Platform.getSSLParameters(Platform.java:187)
    at com.android.org.conscrypt.ConscryptEngine.getSSLParameters(ConscryptEngine.java:525)
    at com.android.org.conscrypt.ConscryptEngineSocket.getSSLParameters(ConscryptEngineSocket.java:186)
    at com.android.okhttp.internal.Platform.configureTlsExtensions(Platform.java:121)
    at com.android.okhttp.internal.io.RealConnection.connectTls(RealConnection.java:191)
    at com.android.okhttp.internal.io.RealConnection.connectSocket(RealConnection.java:153)
    at com.android.okhttp.internal.io.RealConnection.connect(RealConnection.java:116)
    at com.android.okhttp.internal.http.StreamAllocation.findConnection(StreamAllocation.java:186)
    at com.android.okhttp.internal.http.StreamAllocation.findHealthyConnection(StreamAllocation.java:128)
    at com.android.okhttp.internal.http.StreamAllocation.newStream(StreamAllocation.java:97)
    at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:289)
    at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:232)
    at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:465)
    at com.android.okhttp.internal.huc.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:131)
    at com.android.okhttp.internal.huc.DelegatingHttpsURLConnection.connect(DelegatingHttpsURLConnection.java:90)
    at com.android.okhttp.internal.huc.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:30)

   --- End of inner exception stack trace ---
Java.Lang.IllegalArgumentException: Invalid input to toASCII: changed_for_privacy.com
 ---> Android.Icu.Text.StringPrepParseException: The input does not conform to the STD 3 ASCII rules

  --- End of managed Android.Icu.Text.StringPrepParseException stack trace ---
The input does not conform to the STD 3 ASCII rules. line:  0. preContext:  . postContext: 3_identity

    at android.icu.impl.IDNA2003.convertToASCII(IDNA2003.java:218)
    at android.icu.impl.IDNA2003.convertIDNToASCII(IDNA2003.java:276)
    at android.icu.text.IDNA.convertIDNToASCII(IDNA.java:654)
    at com.android.icu.text.ExtendedIDNA.convertIDNToASCII(ExtendedIDNA.java:50)
    at java.net.IDN.toASCII(IDN.java:108)
    at javax.net.ssl.SNIHostName.<init>(SNIHostName.java:99)
    at com.android.org.conscrypt.Platform.getSSLParameters(Platform.java:187)
    at com.android.org.conscrypt.ConscryptEngine.getSSLParameters(ConscryptEngine.java:525)
    at com.android.org.conscrypt.ConscryptEngineSocket.getSSLParameters(ConscryptEngineSocket.java:186)
    at com.android.okhttp.internal.Platform.configureTlsExtensions(Platform.java:121)
    at com.android.okhttp.internal.io.RealConnection.connectTls(RealConnection.java:191)
    at com.android.okhttp.internal.io.RealConnection.connectSocket(RealConnection.java:153)
    at com.android.okhttp.internal.io.RealConnection.connect(RealConnection.java:116)
    at com.android.okhttp.internal.http.StreamAllocation.findConnection(StreamAllocation.java:186)
    at com.android.okhttp.internal.http.StreamAllocation.findHealthyConnection(StreamAllocation.java:128)
    at com.android.okhttp.internal.http.StreamAllocation.newStream(StreamAllocation.java:97)
    at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:289)
    at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:232)
    at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:465)
    at com.android.okhttp.internal.huc.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:131)
    at com.android.okhttp.internal.huc.DelegatingHttpsURLConnection.connect(DelegatingHttpsURLConnection.java:90)
    at com.android.okhttp.internal.huc.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:30)

  --- End of managed Android.Icu.Text.StringPrepParseException stack trace ---
The input does not conform to the STD 3 ASCII rules. line:  0. preContext:  . postContext: 3_identity

    at android.icu.impl.IDNA2003.convertToASCII(IDNA2003.java:218)
    at android.icu.impl.IDNA2003.convertIDNToASCII(IDNA2003.java:276)
    at android.icu.text.IDNA.convertIDNToASCII(IDNA.java:654)
    at com.android.icu.text.ExtendedIDNA.convertIDNToASCII(ExtendedIDNA.java:50)
    at java.net.IDN.toASCII(IDN.java:108)
    at javax.net.ssl.SNIHostName.<init>(SNIHostName.java:99)
    at com.android.org.conscrypt.Platform.getSSLParameters(Platform.java:187)
    at com.android.org.conscrypt.ConscryptEngine.getSSLParameters(ConscryptEngine.java:525)
    at com.android.org.conscrypt.ConscryptEngineSocket.getSSLParameters(ConscryptEngineSocket.java:186)
    at com.android.okhttp.internal.Platform.configureTlsExtensions(Platform.java:121)
    at com.android.okhttp.internal.io.RealConnection.connectTls(RealConnection.java:191)
    at com.android.okhttp.internal.io.RealConnection.connectSocket(RealConnection.java:153)
    at com.android.okhttp.internal.io.RealConnection.connect(RealConnection.java:116)
    at com.android.okhttp.internal.http.StreamAllocation.findConnection(StreamAllocation.java:186)
    at com.android.okhttp.internal.http.StreamAllocation.findHealthyConnection(StreamAllocation.java:128)
    at com.android.okhttp.internal.http.StreamAllocation.newStream(StreamAllocation.java:97)
    at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:289)
    at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:232)
    at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:465)
    at com.android.okhttp.internal.huc.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:131)
    at com.android.okhttp.internal.huc.DelegatingHttpsURLConnection.connect(DelegatingHttpsURLConnection.java:90)
    at com.android.okhttp.internal.huc.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:30)

   --- End of inner exception stack trace ---

Does anyone know what this is and/or how to solve it? I've tried everything involving httpClient and "encoding", or using ASCII character instead of underscore.

Here is where I got the idea that the problem is the underscore in the URL. It seems that people used to have this problem but not recently.

Here and here is where I get the impression that this isn't a bug or an error, it's just the way the world works: no underscores in domains if you wanna use Android. I wonder why this is? It's making the last two months of my work useless. Literally.

Note that the URL is ping-able, and the POST works on Postman.

0

There are 0 best solutions below