microsoft / vscode

Visual Studio Code
https://code.visualstudio.com
MIT License
164.91k stars 29.52k forks source link

"Failed to load resource" with 401 on a file that exists and should be accessible #197103

Closed axosoft-ramint closed 12 months ago

axosoft-ramint commented 1 year ago

Getting Failed to load resource: the server responded with a status of 401 () on a file/resource that exists and should be accessible.

image

This was triggered by pinning a view for an extension as an editor tab (in this case, commit graph of GitLens), upgrading the extension (or switching from release to pre-release or vise versa), and reloading VS Code.

Version: 1.83.1 (user setup) Commit: f1b07bd25dfad64b0167beb15359ae573aecd2cc Date: 2023-10-10T23:48:05.904Z Electron: 25.8.4 ElectronBuildId: 24154031 Chromium: 114.0.5735.289 Node.js: 18.15.0 V8: 11.4.183.29-electron.0 OS: Windows_NT x64 10.0.19045

mjbvz commented 1 year ago

Please start by filing this against gitlens

eamodio commented 1 year ago

@mjbvz this is from the GitLens team. VS Code seems to be failing to load the js in this scenario and GitLens isn't really involved in that flow.

mjbvz commented 1 year ago

Please provide a minimal repo then (one not using gitlens)

ggrossetie commented 1 year ago

We are experiencing the same issue on the Asciidoctor VS Code Extension. You can reproduce this issue using version 3.1.8 of the Asciidoctor VS Code Extension (using Windows)

  1. Create a folder named A

  2. In the A folder:

    1. Add image named mountain.jpeg
    2. Create a file named index.adoc with the following content:

      image:mountain.jpeg[]
  3. Open a terminal (PowerShell)

  4. Navigate to the A folder and run code .

  5. Open index.adoc and use the command "AsciiDoc: Open Preview to the Side"

image

The HTML in the WebView is <img src="mountain.jpeg" alt="mountain">.

Please note that the exact same request works in the Markdown Extension:

image

It's also interesting to note that if I open the A folder using a new VS Code Window, then "File > Open Folder..." it does work!

https://github.com/microsoft/vscode/assets/333276/a2145871-d40f-4ae2-86ed-33b9ccaf4fcf

https://github.com/asciidoctor/asciidoctor-vscode/issues/819

SaschaWillems commented 1 year ago

Same here. In all of the Antora projects I work on the, the asciidoctor extension no loner shows images. They're all blocked with 401 Unauthorized.

ggrossetie commented 1 year ago

@mjbvz I think I found the root cause. The following line returns undefined:

const resourceToLoad = getResourceToLoad(requestUri, options.roots);

https://github.com/microsoft/vscode/blob/b1cddfafe0c054fbeb346a3d3dc9a58f504eb55b/src/vs/workbench/contrib/webview/browser/resourceLoading.ts#L57

In my case, options.root is equals to:

[
    {
        "$mid": 1,
        "fsPath": "c:\\Users\\gross\\.vscode\\extensions\\asciidoctor.asciidoctor-vscode-3.1.8\\media",
        "_sep": 1,
        "external": "file:///c%3A/Users/gross/.vscode/extensions/asciidoctor.asciidoctor-vscode-3.1.8/media",
        "path": "/c:/Users/gross/.vscode/extensions/asciidoctor.asciidoctor-vscode-3.1.8/media",
        "scheme": "file"
    },
    {
        "$mid": 1,
        "fsPath": "c:\\Users\\gross\\.vscode\\extensions\\asciidoctor.asciidoctor-vscode-3.1.8\\dist",
        "_sep": 1,
        "external": "file:///c%3A/Users/gross/.vscode/extensions/asciidoctor.asciidoctor-vscode-3.1.8/dist",
        "path": "/c:/Users/gross/.vscode/extensions/asciidoctor.asciidoctor-vscode-3.1.8/dist",
        "scheme": "file"
    },
    {
        "$mid": 1,
        "fsPath": "c:\\users\\gross\\documents\\a",
        "_sep": 1,
        "external": "file:///c%3A/users/gross/documents/a",
        "path": "/c:/users/gross/documents/a",
        "scheme": "file"
    }
]

As you can see, the folder "a" is in lowercase but the requestUri is using "A" uppercase:

{
    "$mid": 1,
    "fsPath": "c:\\Users\\gross\\Documents\\A\\mountain.jpeg",
    "_sep": 1,
    "external": "file:///c%3A/Users/gross/Documents/A/mountain.jpeg",
    "path": "/c:/Users/gross/Documents/A/mountain.jpeg",
    "scheme": "file"
}

As far as I know, URI are case sensitive but Windows is case-insensitive. I believe that the correct URI in options.root should be:

    {
        "$mid": 1,
        "fsPath": "c:\\users\\gross\\documents\\A",
        "_sep": 1,
        "external": "file:///c%3A/users/gross/documents/A",
        "path": "/c:/users/gross/documents/A",
        "scheme": "file"
    }

fsPath could either use a or A since Windows is case insensitive but for consistency it should probably use A.

ggrossetie commented 1 year ago

I forgot to mention that when it works it's because we are in a workspace and somehow the image is cached! So it returns a 304.

ggrossetie commented 1 year ago

It's actually a bug in the Asciidoctor Extension where we apply toLowerCase on the path 😥

AnouarDoukkali commented 1 year ago

@eamodio could you please check if this applies to Gitlens too ?

eamodio commented 1 year ago

In GitLens this is a narrow case. It happens when users have a webview open, upgrade GitLens to a new version, and reload VS Code. On that first reload the webview fails to be restored properly -- vscode restores it but my guess it tries to restore the js bundle from the old extension location, not the new one.

If the user closes the webview and reopens it everything works from then on until the next upgrade.

ggrossetie commented 1 year ago

My guess is that the localResourceRoots on the WebView is configured to: /c:/Users/<user>/.vscode/extensions/<path-to-gitlens-with-version>/dist. For instance:

/c:/Users/<user>/.vscode/extensions/eamodio.gitlens-2023.10.3105/dist

When you install a new version, let's say 2023.11.1914, the WebView won't allow to load assets from /c:/Users/<user>/.vscode/extensions/eamodio.gitlens-2023.11.1914/dist since only /c:/Users/<user>/.vscode/extensions/eamodio.gitlens-2023.10.3105/dist is configured as loadResourceRoots (hence the 401).

Not sure what's the best approach here. Should extensions forcibly recreate WebView when the extension is updated? Should VS code take care of it? Should we allow regular expression/glob pattern in localResourceRoots to prevent issues (i.e., eamodio.gitlens-.*).

mjbvz commented 12 months ago

Great investigation and finds!

Should extensions forcibly recreate WebView when the extension is updated

@eamodio @axosoft-ramint Can you try setting localResourceRoots when restoring the webview too?

I'm hesitant to adding logic on the VS Code side that does this automatically as there's a chance we get this wrong. Better I think to make this explicit on the extension side, especially because the fix should be pretty easy since extensions already need to set the roots for new webviews

eamodio commented 12 months ago

@mjbvz I don't know what we would set it to? We currently set it to ExtensionContext.extensionPath, and I don't know what the previous path would be. IMO, VS Code is the only one who could reasonably handle this -- as VS Code "knows" the previous path, as it upgraded the extension and controls the extensionPath.