Adding Azure DevOps based Microsoft.PreIndexed.Package Source fails
Brief description of your issue
When adding a Microsoft.PreIndexed.Package based HTTPS source a HTTP HEAD operation is attemped to retrieve file size of Source.MSIX. This fails due to lack of HEAD method support on the Azure DevOps.
I've tested both git and tfsgit providers with same result.
Source Add Exception 0x80190195 : Method not allowed (405).
Relevant Log Entries [REPO] Initializing source from: core => https://dev.azure.com/Tryll/DevTestLabs/_apis/git/repositories/Software-Repository/items?resolveLfs=true&%24format=octetStream&api-version=5.0&download=true&path=/source.msix [FAIL] WindowsPackageManager.dll!00007FF970FA3022: ReturnHr(1) tid(1e4) 80190195 Method not allowed (405). Msg:[D:\a_work\1\s\external\pkg\src\AppInstallerCommonCore\HttpStream\HttpClientWrapper.cpp(50)\WindowsPackageManager.dll!00007FF970F8F58A: (caller: 00007FF970E88BA9) Exception(1) tid(1e4) 80190195 Method not allowed (405). ]
[FAIL] WindowsPackageManager.dll!00007FF970E367C7: LogHr(1) tid(1e4) 80190195 Method not allowed (405).
HttpClientWrapper.cpp suggestion HttpClientWrapper::PopulateInfoAsync() in src/AppInstallerCommonCore/HttpStream/HttpClientWrapper.cpp : already supports a non determined file size, but throws immediately on HTTP response other than HttpStatusCode::Ok. It should rather go directly for a GET operation with co_await SendHttpRequestAsync(0, 1);
Steps to reproduce
winget source add --verbose-logs -n core -a "https://dev.azure.com/Tryll/DevTestLabs/_apis/git/repositories/Software-Repository/items?resolveLfs=true&%24format=octetStream&api-version=5.0&download=true&path=" Adding source: core -> https://dev.azure.com/Tryll/DevTestLabs/_apis/git/repositories/Software-Repository/items?resolveLfs=true&%24format=octetStream&api-version=5.0&download=true&path= An unexpected error occurred while executing the command: 0x80190195 : Method not allowed (405).
Expected behavior
Source is added.
Actual behavior
winget source add --verbose-logs -n core -a "https://dev.azure.com/Tryll/DevTestL abs/_apis/git/repositories/a352abf2-74c3-486c-8558-5eb0f525f163/items?path=" Adding source: core -> https://dev.azure.com/Tryll/DevTestLabs/_apis/git/repositories/a352abf2-74c3-486c-8558-5eb0f525f163/items?path= An unexpected error occurred while executing the command: 0x80190195 : Method not allowed (405).
Environment
Windows Package Manager v1.3.2691
Copyright (c) Microsoft Corporation. All rights reserved.
Windows: Windows.Desktop v10.0.22000.1098
System Architecture: X64
Package: Microsoft.DesktopAppInstaller v1.18.2691.0
Logs: %LOCALAPPDATA%\Packages\Microsoft.DesktopAppInstaller_8wekyb3d8bbwe\LocalState\DiagOutputDir
Links
---------------------------------------------------------------------------
Privacy Statement https://aka.ms/winget-privacy
License Agreement https://aka.ms/winget-license
Third Party Notices https://aka.ms/winget-3rdPartyNotice
Homepage https://aka.ms/winget
Windows Store Terms https://www.microsoft.com/en-us/storedocs/terms-of-sale
This works fine with a github based project https://github.com/Tryll/Software-Repository
winget source add --verbose-logs -n core -a https://raw.githubusercontent.com/Tryll/Software-Repository/master Adding source: core -> https://raw.githubusercontent.com/Tryll/Software-Repository/master ██████████████████████████████ 100% Done
I looked abit more into this.
The purpose of HttpClientWrapper class is to enable ranged downloading, by first identifying file size. Where both HEAD and Range inspection is not supported by the hosting web server (like Azure DevOps) download fails completely.
Tested I compiled HttpClientWrapper::PopulateInfoAsync() with an exception allowing for MethodNotAllowed and it turns out Azure Devops repositories ("items" and "blobs") also does not support Ranged lookups/inspection either. "Content-Length" is not returned and full content is available resulting in crash at response.Content().ReadAsBufferAsync() in HttpClientWrapper::SendHttpRequestAsync.
Feature request If HEAD and Range=bytes=0-0 is not able to detect filesize, there should be a fall-back for a single full download. Supporting full download is the only option for HTTP hosts without HEAD or Range support (like Azure Devops).
Conclusion Maybe this is more of a feature request and not directly a bug; though PopulateInfoAsync should forward MethodNotAllowed results to SendHttpRequestAsync to attempt the Range approach, to determine file size and allow for ranged downloading.