Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[wasm] HttpClient regression when using BaseAddress #14630

Open
SteveSandersonMS opened this issue May 24, 2019 · 11 comments

Comments

@SteveSandersonMS
Copy link

commented May 24, 2019

For a few months, Blazor developers have been reporting this bug, which I've now tracked down to be a regression in Mono.

The problem: if your HttpClient has a BaseAddress, it should be able to make requests to slash-rooted URLs, but a few months ago this started failing with an exception.

Repro steps

This code:

var httpClient = new HttpClient();
httpClient.BaseAddress = new System.Uri("http://localhost:52590/");
var task = httpClient.GetStringAsync("/something");
System.Console.WriteLine("OK");

Expected output: OK (with request happening in the background)

Actual: throws

WASM: System.ArgumentException: Only 'http' and 'https' schemes are allowed.
blazor.webassembly.js:821 WASM: Parameter name: requestUri
blazor.webassembly.js:821 WASM:   at System.Net.Http.HttpRequestMessage.InitializeValues (System.Net.Http.HttpMethod method, System.Uri requestUri) <0x20e35c0 + 0x00046> in <5e1a30ab033b420ead3173e84550c6f2>:0 
blazor.webassembly.js:821 WASM:   at System.Net.Http.HttpRequestMessage..ctor (System.Net.Http.HttpMethod method, System.Uri requestUri) <0x20e3400 + 0x00044> in <5e1a30ab033b420ead3173e84550c6f2>:0 
blazor.webassembly.js:821 WASM:   at System.Net.Http.HttpClient.GetAsync (System.Uri requestUri, System.Net.Http.HttpCompletionOption completionOption, System.Threading.CancellationToken cancellationToken) <0x20d5830 + 0x0000c> in <5e1a30ab033b420ead3173e84550c6f2>:0 
blazor.webassembly.js:821 WASM:   at System.Net.Http.HttpClient.GetAsync (System.Uri requestUri, System.Net.Http.HttpCompletionOption completionOption) <0x20cd9a8 + 0x00018> in <5e1a30ab033b420ead3173e84550c6f2>:0 
blazor.webassembly.js:821 WASM:   at System.Net.Http.HttpClient.GetStringAsync (System.Uri requestUri) <0x20cd878 + 0x0000e> in <5e1a30ab033b420ead3173e84550c6f2>:0 
blazor.webassembly.js:821 WASM:   at System.Net.Http.HttpClient.GetStringAsync (System.String requestUri) <0x20cd618 + 0x00010> in <5e1a30ab033b420ead3173e84550c6f2>:0 

It seems that it's unable to combine the URL with BaseUri if it starts with a slash. However, the exact same code works fine on .NET Core (CoreCLR).

@SteveSandersonMS

This comment has been minimized.

Copy link
Author

commented May 24, 2019

cc @lewing

@rynowak

This comment has been minimized.

Copy link

commented May 24, 2019

@SteveSandersonMS is it reasonable that we could add a workaround to our code for this? This is a really disruptive bug, and I'm not sure we have plans to take another mono build this preview.

@SteveSandersonMS

This comment has been minimized.

Copy link
Author

commented May 24, 2019

@rynowak Yes, I was going to discuss this today. We don't have an obvious way of fixing GetStringAsync since calls to that don't touch anything outside the BCL, but we could put in logic to the higher-level JSON extension methods to resolve slash-rooted URLs against the BaseAddress.

@lewing

This comment has been minimized.

Copy link
Member

commented May 24, 2019

Does this fail on desktop mono as well?

@lewing

This comment has been minimized.

Copy link
Member

commented May 24, 2019

cc @baulig is this a regression from the corefx integration?

@marek-safar

This comment has been minimized.

Copy link
Member

commented May 24, 2019

@baulig

This comment has been minimized.

Copy link
Member

commented May 24, 2019

The problem is that our System.Uri class behaves differently than it does in CoreFX. You can force the CoreFX behavior by setting the MONO_URI_DOTNETRELATIVEORABSOLUTE=true environment variable.

The code they're using is

        static bool IsAllowedAbsoluteUri(Uri requestUri)
        {
            return !requestUri.IsAbsoluteUri || HttpUtilities.IsHttpUri(requestUri);
        }

We have a custom implementation of that:

                static bool IsAllowedAbsoluteUri (Uri uri)
                {
                        if (!uri.IsAbsoluteUri)
                                return true;

#if WASM
                        if (uri.Scheme == "blob")
                                return true;
#endif

                        return HttpUtilities.IsHttpUri (uri);
                }

which is essentially the same thing except that it allows "blob" on WASM.

The problem is that Mono's implementation considers /foo to be an absolute Uri and there is no check for the base address.

@lewing

This comment has been minimized.

Copy link
Member

commented May 24, 2019

@SteveSandersonMS @rynowak I haven't had a chance to test it but if @baulig is correct https://github.com/lewing/AspNetCore/tree/relative-url should work around the issue for you. We'll change the mono default for wasm as well

@baulig

This comment has been minimized.

Copy link
Member

commented May 24, 2019

@lewing Oh cool, at least we have a workaround for the time being.

I'll still have a look at this next week because this is also going to hurt us on desktop and mobile (after switching to the new handler there).

@baulig baulig self-assigned this May 24, 2019

@lewing

This comment has been minimized.

Copy link
Member

commented May 27, 2019

I tested the workaround and it does resolve the issue

@lewing

This comment has been minimized.

Copy link
Member

commented May 28, 2019

aspnet/AspNetCore#10551 which has now merged worked around the issue on the blazor side. I'm leaving this open to track the changes to the default needed on our side.

@ts678 ts678 referenced this issue Aug 8, 2019

Open

Error OneDrive and Mono 6.0 #3852

1 of 1 task complete
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
5 participants
You can’t perform that action at this time.