winget-cli

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit d25870a4aa739184ab635326e5d486af030e392a
parent bafc20f0b08a4d372c38b9b937ff3f9e09243320
Author: Ashwini Patil <47225815+ashpatil-msft@users.noreply.github.com>
Date:   Fri, 26 Mar 2021 09:59:11 -0700

Rest endpoint helper and json object field check - Bug fix (#821)

* Fixing endpoint and checking field value presence in json deserialization
Diffstat:
Msrc/AppInstallerRepositoryCore/AppInstallerRepositoryCore.vcxproj | 2++
Msrc/AppInstallerRepositoryCore/AppInstallerRepositoryCore.vcxproj.filters | 6++++++
Msrc/AppInstallerRepositoryCore/Rest/RestClient.cpp | 3++-
Msrc/AppInstallerRepositoryCore/Rest/Schema/1_0/Interface.cpp | 13++-----------
Msrc/AppInstallerRepositoryCore/Rest/Schema/Json/ManifestDeserializer.cpp | 54++++++++++++++++++++++++++++++++++++------------------
Asrc/AppInstallerRepositoryCore/Rest/Schema/RestHelper.cpp | 17+++++++++++++++++
Asrc/AppInstallerRepositoryCore/Rest/Schema/RestHelper.h | 12++++++++++++
7 files changed, 77 insertions(+), 30 deletions(-)

diff --git a/src/AppInstallerRepositoryCore/AppInstallerRepositoryCore.vcxproj b/src/AppInstallerRepositoryCore/AppInstallerRepositoryCore.vcxproj @@ -216,6 +216,7 @@ <ClInclude Include="Rest\Schema\Json\JsonHelper.h" /> <ClInclude Include="Rest\Schema\Json\ManifestDeserializer.h" /> <ClInclude Include="Rest\Schema\Json\SearchResponseDeserializer.h" /> + <ClInclude Include="Rest\Schema\RestHelper.h" /> <ClInclude Include="SourceFactory.h" /> <ClInclude Include="SQLiteStatementBuilder.h" /> <ClInclude Include="Public\AppInstallerRepositorySearch.h" /> @@ -266,6 +267,7 @@ <ClCompile Include="Rest\Schema\Json\JsonHelper.cpp" /> <ClCompile Include="Rest\Schema\Json\ManifestDeserializer.cpp" /> <ClCompile Include="Rest\Schema\Json\SearchResponseDeserializer.cpp" /> + <ClCompile Include="Rest\Schema\RestHelper.cpp" /> <ClCompile Include="SQLiteStatementBuilder.cpp" /> <ClCompile Include="SQLiteTempTable.cpp" /> <ClCompile Include="SQLiteWrapper.cpp" /> diff --git a/src/AppInstallerRepositoryCore/AppInstallerRepositoryCore.vcxproj.filters b/src/AppInstallerRepositoryCore/AppInstallerRepositoryCore.vcxproj.filters @@ -198,6 +198,9 @@ <ClInclude Include="Rest\Schema\Json\SearchResponseDeserializer.h"> <Filter>Rest\Schema\Json</Filter> </ClInclude> + <ClInclude Include="Rest\Schema\RestHelper.h"> + <Filter>Rest\Schema</Filter> + </ClInclude> </ItemGroup> <ItemGroup> <ClCompile Include="pch.cpp"> @@ -302,6 +305,9 @@ <ClCompile Include="Rest\Schema\Json\SearchResponseDeserializer.cpp"> <Filter>Rest\Schema\Json</Filter> </ClCompile> + <ClCompile Include="Rest\Schema\RestHelper.cpp"> + <Filter>Rest\Schema</Filter> + </ClCompile> </ItemGroup> <ItemGroup> <None Include="PropertySheet.props" /> diff --git a/src/AppInstallerRepositoryCore/Rest/RestClient.cpp b/src/AppInstallerRepositoryCore/Rest/RestClient.cpp @@ -7,6 +7,7 @@ #include "Rest/Schema/Json/InformationResponseDeserializer.h" #include "Rest/Schema/Json/JsonHelper.h" #include "Rest/Schema/Json/CommonRestConstants.h" +#include "Rest/Schema/RestHelper.h" using namespace AppInstaller::Repository::Rest::Schema; using namespace AppInstaller::Repository::Rest::Schema::Json; @@ -30,7 +31,7 @@ namespace AppInstaller::Repository::Rest utility::string_t RestClient::GetInformationEndpoint(const std::string& restApiUri) { - std::string informationApi = restApiUri; + std::string informationApi = RestHelper::GetRestAPIBaseUri(restApiUri); return utility::conversions::to_string_t(informationApi.append(InformationGetEndpoint)); } diff --git a/src/AppInstallerRepositoryCore/Rest/Schema/1_0/Interface.cpp b/src/AppInstallerRepositoryCore/Rest/Schema/1_0/Interface.cpp @@ -9,6 +9,7 @@ #include "Rest/Schema/Json/JsonHelper.h" #include "Rest/Schema/Json/CommonRestConstants.h" #include "Rest/Schema/Json/ManifestDeserializer.h" +#include "Rest/Schema/RestHelper.h" #include "Rest/Schema/Json/SearchResponseDeserializer.h" #include "winget/ManifestValidation.h" @@ -37,16 +38,6 @@ namespace AppInstaller::Repository::Rest::Schema::V1_0 return json_body; } - std::string GetRestAPIBaseUri(std::string restApiUri) - { - if (!restApiUri.empty() && restApiUri.back() == '/') - { - restApiUri.pop_back(); - } - - return restApiUri; - } - utility::string_t GetSearchEndpoint(const std::string& restApiUri) { std::string fullSearchAPI = restApiUri; @@ -82,7 +73,7 @@ namespace AppInstaller::Repository::Rest::Schema::V1_0 Interface::Interface(const std::string& restApi) { - m_restApiUri = GetRestAPIBaseUri(restApi); + m_restApiUri = RestHelper::GetRestAPIBaseUri(restApi); m_searchEndpoint = GetSearchEndpoint(m_restApiUri); m_requiredRestApiHeaders.emplace_back( std::pair(JsonHelper::GetUtilityString(ContractVersion), JsonHelper::GetUtilityString(GetVersion()))); diff --git a/src/AppInstallerRepositoryCore/Rest/Schema/Json/ManifestDeserializer.cpp b/src/AppInstallerRepositoryCore/Rest/Schema/Json/ManifestDeserializer.cpp @@ -142,17 +142,26 @@ namespace AppInstaller::Repository::Rest::Schema::Json manifest.Channel = JsonHelper::GetRawStringValueFromJsonNode(versionItem, JsonHelper::GetUtilityString(Channel)).value_or(""); // Default locale - auto& defaultLocale = versionItem.at(JsonHelper::GetUtilityString(DefaultLocale)); - std::optional<Manifest::ManifestLocalization> defaultLocaleObject = DeserializeLocale(defaultLocale); - if (!defaultLocaleObject) + std::optional<std::reference_wrapper<const web::json::value>> defaultLocale = + JsonHelper::GetJsonValueFromNode(versionItem, JsonHelper::GetUtilityString(DefaultLocale)); + if (!defaultLocale) { AICLI_LOG(Repo, Error, << "Missing default locale in package: " << manifest.Id); return {}; } - manifest.DefaultLocalization = std::move(defaultLocaleObject.value()); + else + { + std::optional<Manifest::ManifestLocalization> defaultLocaleObject = DeserializeLocale(defaultLocale.value().get()); + if (!defaultLocaleObject) + { + AICLI_LOG(Repo, Error, << "Missing default locale in package: " << manifest.Id); + return {}; + } + manifest.DefaultLocalization = std::move(defaultLocaleObject.value()); - // Moniker is in Default locale - manifest.Moniker = JsonHelper::GetRawStringValueFromJsonNode(defaultLocale, JsonHelper::GetUtilityString(Moniker)).value_or(""); + // Moniker is in Default locale + manifest.Moniker = JsonHelper::GetRawStringValueFromJsonNode(defaultLocale.value().get(), JsonHelper::GetUtilityString(Moniker)).value_or(""); + } // Installers std::optional<std::reference_wrapper<const web::json::array>> installers = JsonHelper::GetRawJsonArrayFromJsonNode(versionItem, JsonHelper::GetUtilityString(Installers)); @@ -335,14 +344,19 @@ namespace AppInstaller::Repository::Rest::Schema::Json } // Installer Switches - auto& installerSwitches = installerJsonObject.at(JsonHelper::GetUtilityString(InstallerSwitches)); - installer.Switches[InstallerSwitchType::Silent] = JsonHelper::GetRawStringValueFromJsonNode(installerSwitches, JsonHelper::GetUtilityString(Silent)).value_or(""); - installer.Switches[InstallerSwitchType::SilentWithProgress] = JsonHelper::GetRawStringValueFromJsonNode(installerSwitches, JsonHelper::GetUtilityString(SilentWithProgress)).value_or(""); - installer.Switches[InstallerSwitchType::Interactive] = JsonHelper::GetRawStringValueFromJsonNode(installerSwitches, JsonHelper::GetUtilityString(Interactive)).value_or(""); - installer.Switches[InstallerSwitchType::InstallLocation] = JsonHelper::GetRawStringValueFromJsonNode(installerSwitches, JsonHelper::GetUtilityString(InstallLocation)).value_or(""); - installer.Switches[InstallerSwitchType::Log] = JsonHelper::GetRawStringValueFromJsonNode(installerSwitches, JsonHelper::GetUtilityString(Log)).value_or(""); - installer.Switches[InstallerSwitchType::Update] = JsonHelper::GetRawStringValueFromJsonNode(installerSwitches, JsonHelper::GetUtilityString(Upgrade)).value_or(""); - installer.Switches[InstallerSwitchType::Custom] = JsonHelper::GetRawStringValueFromJsonNode(installerSwitches, JsonHelper::GetUtilityString(Custom)).value_or(""); + std::optional<std::reference_wrapper<const web::json::value>> switches = + JsonHelper::GetJsonValueFromNode(installerJsonObject, JsonHelper::GetUtilityString(InstallerSwitches)); + if (switches) + { + auto& installerSwitches = switches.value().get(); + installer.Switches[InstallerSwitchType::Silent] = JsonHelper::GetRawStringValueFromJsonNode(installerSwitches, JsonHelper::GetUtilityString(Silent)).value_or(""); + installer.Switches[InstallerSwitchType::SilentWithProgress] = JsonHelper::GetRawStringValueFromJsonNode(installerSwitches, JsonHelper::GetUtilityString(SilentWithProgress)).value_or(""); + installer.Switches[InstallerSwitchType::Interactive] = JsonHelper::GetRawStringValueFromJsonNode(installerSwitches, JsonHelper::GetUtilityString(Interactive)).value_or(""); + installer.Switches[InstallerSwitchType::InstallLocation] = JsonHelper::GetRawStringValueFromJsonNode(installerSwitches, JsonHelper::GetUtilityString(InstallLocation)).value_or(""); + installer.Switches[InstallerSwitchType::Log] = JsonHelper::GetRawStringValueFromJsonNode(installerSwitches, JsonHelper::GetUtilityString(Log)).value_or(""); + installer.Switches[InstallerSwitchType::Update] = JsonHelper::GetRawStringValueFromJsonNode(installerSwitches, JsonHelper::GetUtilityString(Upgrade)).value_or(""); + installer.Switches[InstallerSwitchType::Custom] = JsonHelper::GetRawStringValueFromJsonNode(installerSwitches, JsonHelper::GetUtilityString(Custom)).value_or(""); + } // Installer SuccessCodes std::optional<std::reference_wrapper<const web::json::array>> installSuccessCodes = JsonHelper::GetRawJsonArrayFromJsonNode(installerJsonObject, JsonHelper::GetUtilityString(InstallerSuccessCodes)); @@ -369,11 +383,15 @@ namespace AppInstaller::Repository::Rest::Schema::Json installer.FileExtensions = JsonHelper::GetRawStringArrayFromJsonNode(installerJsonObject, JsonHelper::GetUtilityString(FileExtensions)); // Dependencies - auto& dependenciesObject = installerJsonObject.at(JsonHelper::GetUtilityString(Dependencies)); - std::optional<Manifest::Dependency> dependency = DeserializeDependency(dependenciesObject); - if (dependency) + std::optional<std::reference_wrapper<const web::json::value>> dependenciesObject = + JsonHelper::GetJsonValueFromNode(installerJsonObject, JsonHelper::GetUtilityString(Dependencies)); + if (dependenciesObject) { - installer.Dependencies = std::move(dependency.value()); + std::optional<Manifest::Dependency> dependency = DeserializeDependency(dependenciesObject.value().get()); + if (dependency) + { + installer.Dependencies = std::move(dependency.value()); + } } installer.PackageFamilyName = JsonHelper::GetRawStringValueFromJsonNode(installerJsonObject, JsonHelper::GetUtilityString(PackageFamilyName)).value_or(""); diff --git a/src/AppInstallerRepositoryCore/Rest/Schema/RestHelper.cpp b/src/AppInstallerRepositoryCore/Rest/Schema/RestHelper.cpp @@ -0,0 +1,17 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +#include "pch.h" +#include "RestHelper.h" + +namespace AppInstaller::Repository::Rest::Schema +{ + std::string RestHelper::GetRestAPIBaseUri(std::string restApiUri) + { + if (!restApiUri.empty() && restApiUri.back() == '/') + { + restApiUri.pop_back(); + } + + return restApiUri; + } +} diff --git a/src/AppInstallerRepositoryCore/Rest/Schema/RestHelper.h b/src/AppInstallerRepositoryCore/Rest/Schema/RestHelper.h @@ -0,0 +1,12 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +#pragma once + +namespace AppInstaller::Repository::Rest::Schema +{ + // Rest source helper. + struct RestHelper + { + static std::string GetRestAPIBaseUri(std::string restApiUri); + }; +}