diff --git a/sdk/core/azure-core/inc/azure/core/http/http.hpp b/sdk/core/azure-core/inc/azure/core/http/http.hpp index 33622c1f4..ce279c563 100644 --- a/sdk/core/azure-core/inc/azure/core/http/http.hpp +++ b/sdk/core/azure-core/inc/azure/core/http/http.hpp @@ -31,16 +31,6 @@ namespace Azure { namespace Core { namespace Test { namespace Azure { namespace Core { namespace Http { namespace Details { - // returns left map plus all items in right - // when duplicates, left items are preferred - static std::map MergeMaps( - std::map left, - std::map const& right) - { - left.insert(right.begin(), right.end()); - return left; - } - /** * @brief Insert a header into \p headers checking that \p headerName does not contain invalid * characters. @@ -197,52 +187,49 @@ namespace Azure { namespace Core { namespace Http { Stream, ///< Stream. }; - // Url represent the location where a request will be performed. It can be parsed and init from - // a string that contains all Url parts (scheme, host, path, etc). - // Authority is not currently supported. /** - * @brief URL. + * @brief Url represents the location where a request will be performed. + * It can be parsed and initialized from a string that contains all URL components (scheme, host, + * path, etc.). Authority is not currently supported. */ class Url { - // Let Request class to be able to set retry enabled ON - friend class Request; - private: std::string m_scheme; std::string m_host; int m_port{-1}; std::string m_encodedPath; - std::string m_fragment; - // query parameters are all decoded - std::map m_queryParameters; - std::map m_retryQueryParameters; - bool m_retryModeEnabled{false}; + // query parameters are all encoded + std::map m_encodedQueryParameters; - /********* private static methods for all instances *******/ - static std::string Decode(const std::string& value); - static std::string EncodeHost(const std::string& host); - static std::string EncodePath(const std::string& path); - static std::string EncodeQuery(const std::string& query); - static std::string EncodeFragment(const std::string& fragment); - static std::string EncodeImpl( - const std::string& source, - const std::function& should_encode); - - void StartRetry() - { - m_retryModeEnabled = true; - m_retryQueryParameters.clear(); - } - - void StopRetry() - { - m_retryModeEnabled = false; - m_retryQueryParameters.clear(); - } + // List of default non-URL-encode chars. While URL encoding a string, do not escape any chars in + // this set. + static std::unordered_set defaultNonUrlEncodeChars; public: /** - * @brief Construct an empty URL. + * @brief Decodes \p value by transforming all escaped characters to it's non-encoded value. + * + * @param value URL-encoded string. + * @return std::string with non-URL encoded values. + */ + static std::string Decode(const std::string& value); + + /** + * @brief Encodes \p value by escaping characters to the form of %HH where HH are hex digits. + * + * @remark \p doNotEncodeSymbols arg can be used to explicitly ask this function to skip + * characters from encoding. For instance, using this `= -` input would prevent encoding `=`, ` + * ` and `-`. + * + * @param value Non URL-encoded string. + * @param doNotEncodeSymbols + * @return std::string + */ + static std::string Encode(const std::string& value, const std::string& doNotEncodeSymbols = ""); + + /** + * @brief Constructs a new, empty URL object. + * */ Url() {} @@ -267,12 +254,8 @@ namespace Azure { namespace Core { namespace Http { * @brief Set URL host. * * @param host URL host. - * @param isHostEncoded `true` if \p host is URL-encoded, `false` otherwise. */ - void SetHost(const std::string& host, bool isHostEncoded = false) - { - m_host = isHostEncoded ? host : EncodeHost(host); - } + void SetHost(const std::string& encodedHost) { m_host = encodedHost; } /** * @brief Set URL port. @@ -285,22 +268,20 @@ namespace Azure { namespace Core { namespace Http { * @brief Set URL path. * * @param path URL path. - * @param isPathEncoded `true` if \p fragment is URL-encoded, `false` otherwise. */ - void SetPath(const std::string& path, bool isPathEncoded = false) - { - m_encodedPath = isPathEncoded ? path : EncodePath(path); - } + void SetPath(const std::string& encodedPath) { m_encodedPath = encodedPath; } /** - * @brief Set URL fragment. + * @brief Set the query parameters from an existing query parameter map. * - * @param fragment URL fragment. - * @param isFragmentEncoded `true` if \p fragment is URL-encoded, `false` otherwise. + * @remark Keys and values in \p queryParameters are expected to be URL-encoded. + * + * @param queryParameters */ - void SetFragment(const std::string& fragment, bool isFragmentEncoded = false) + void SetQueryParameters(std::map queryParameters) { - m_fragment = isFragmentEncoded ? fragment : EncodeFragment(fragment); + // creates a copy and discard previous + m_encodedQueryParameters = std::move(queryParameters); } // ===== APIs for mutating URL state: ====== @@ -309,93 +290,85 @@ namespace Azure { namespace Core { namespace Http { * @brief Append an element of URL path. * * @param path URL path element to append. - * @param isPathEncoded `true` if \p path is URL-encoded, `false` otherwise. */ - void AppendPath(const std::string& path, bool isPathEncoded = false) + void AppendPath(const std::string& encodedPath) { if (!m_encodedPath.empty() && m_encodedPath.back() != '/') { m_encodedPath += '/'; } - m_encodedPath += isPathEncoded ? path : EncodePath(path); + m_encodedPath += encodedPath; } /** - * @brief Append an HTTP query parameter. + * @brief The value of a query parameter is expected to be non-URL-encoded and, by default, it + * will be encoded before adding to the URL. Use \p isValueEncoded = true when the + * value is already encoded. * - * @note Overrides previous query parameters. - * @remark A query key can't contain any characters that need to be URL-encoded (per RFC 7230). + * @remark This function overrides the value of existing query parameters. * - * @param key HTTP query parameter. - * @param value HTTP query parameter value. - * @param isValueEncoded `true` if \p value is URL-encoded, `false` otherwise. + * @param encodedKey Name of the query parameter, already encoded. + * @param encodedValue Value of the query parameter, already encoded. */ - void AppendQuery(const std::string& key, const std::string& value, bool isValueEncoded = false) + void AppendQueryParameter(const std::string& encodedKey, const std::string& encodedValue) { - std::string encoded_value = isValueEncoded ? Decode(value) : value; - if (m_retryModeEnabled) - { - m_retryQueryParameters[key] = encoded_value; - } - else - { - m_queryParameters[key] = encoded_value; - } + m_encodedQueryParameters[encodedKey] = encodedValue; } /** - * @brief Append a HTTP query. + * @brief Finds the first '?' symbol and parses everything after it as query parameters. + * separated by '&'. * - * @note All the required HTTP query parts should be URL-encoded. - * - * @param encodedQueries HTTP query. + * @param encodedQueryParameters String containing one or more query parameters. */ - void AppendQueries(const std::string& encodedQueries); + void AppendQueryParameters(const std::string& encodedQueryParameters); /** - * @brief Removes a HTTP query parameter. + * @brief Removes an existing query parameter. * - * @param key HTTP query parameter to remove. + * @param encodedKey The name of the query parameter to be removed. */ - void RemoveQuery(const std::string& key) + void RemoveQueryParameter(const std::string& encodedKey) { - m_queryParameters.erase(key); - m_retryQueryParameters.erase(key); + m_encodedQueryParameters.erase(encodedKey); } /************** API to read values from Url ***************/ /** * @brief Get URL host. */ - std::string GetHost() const { return m_host; } + const std::string& GetHost() const { return m_host; } /** - * @brief Get URL path. + * @brief Gets the URL path. + * + * @return const std::string& */ const std::string& GetPath() const { return m_encodedPath; } /** - * @brief Get all the query parameters in the URL. + * @brief Provides a copy to the list of query parameters from the URL. * - * @note Retry parameters have preference and will override any value from the initial query - * parameters. - * @note All the values are URL-encoded. + * @remark The query parameters are URL-encoded. * - * @return URL query parameters. + * @return const std::map& */ - const std::map GetQuery() const + std::map GetQueryParameters() const { - return Details::MergeMaps(m_retryQueryParameters, m_queryParameters); + return m_encodedQueryParameters; } /** - * @brief Get relative URL. + * @brief Gets the path and query parameters. + * + * @return std::string The string is URL encoded. */ std::string GetRelativeUrl() const; /** - * @brief Get relative URL. - * @remark All the query parameters are URL-encoded. + * @brief Gets Scheme, host, path and query parameters. + * + * @return std::string The string is URL encoded. */ std::string GetAbsoluteUrl() const; }; @@ -428,9 +401,6 @@ namespace Azure { namespace Core { namespace Http { // adapter will decide chunk size. int64_t m_uploadChunkSize = 0; - void StartRetry(); // only called by retry policy - void StopRetry(); // only called by retry policy - public: /** * @brief Construct an HTTP @request. @@ -549,6 +519,9 @@ namespace Azure { namespace Core { namespace Http { * @brief Get URL. */ Url const& GetUrl() const { return this->m_url; } + // Expected to be called by a Retry policy to reset all headers set after this function was + // previously called + void StartTry(); }; /* diff --git a/sdk/core/azure-core/src/http/request.cpp b/sdk/core/azure-core/src/http/request.cpp index b4261bbe1..a08c634a7 100644 --- a/sdk/core/azure-core/src/http/request.cpp +++ b/sdk/core/azure-core/src/http/request.cpp @@ -10,6 +10,18 @@ using namespace Azure::Core::Http; +namespace { +// returns left map plus all items in right +// when duplicates, left items are preferred +static std::map MergeMaps( + std::map left, + std::map const& right) +{ + left.insert(right.begin(), right.end()); + return left; +} +} // namespace + void Request::AddHeader(std::string const& name, std::string const& value) { auto headerNameLowerCase = Azure::Core::Details::ToLower(name); @@ -26,18 +38,10 @@ void Request::RemoveHeader(std::string const& name) this->m_retryHeaders.erase(name); } -void Request::StartRetry() +void Request::StartTry() { this->m_retryModeEnabled = true; this->m_retryHeaders.clear(); - this->m_url.StartRetry(); -} - -void Request::StopRetry() -{ - this->m_retryModeEnabled = false; - this->m_retryHeaders.clear(); - this->m_url.StopRetry(); } HttpMethod Request::GetMethod() const { return this->m_method; } @@ -46,7 +50,7 @@ std::map Request::GetHeaders() const { // create map with retry headers which are the most important and we don't want // to override them with any duplicate header - return Details::MergeMaps(this->m_retryHeaders, this->m_headers); + return MergeMaps(this->m_retryHeaders, this->m_headers); } // Writes an HTTP request with RFC 7230 without the body (head line and headers) diff --git a/sdk/core/azure-core/src/http/retry_policy.cpp b/sdk/core/azure-core/src/http/retry_policy.cpp index d1c609413..e108d87a4 100644 --- a/sdk/core/azure-core/src/http/retry_policy.cpp +++ b/sdk/core/azure-core/src/http/retry_policy.cpp @@ -134,6 +134,9 @@ std::unique_ptr Azure::Core::Http::RetryPolicy::Send( for (RetryNumber attempt = 1;; ++attempt) { Delay retryAfter{}; + request.StartTry(); + // creates a copy of original query parameters from request + auto originalQueryParameters = request.GetUrl().GetQueryParameters(); try { auto response = nextHttpPolicy.Send(ctx, request); @@ -142,9 +145,8 @@ std::unique_ptr Azure::Core::Http::RetryPolicy::Send( // doesn't need to be retried), then ShouldRetry returns false. if (!ShouldRetryOnResponse(*response.get(), m_retryOptions, attempt, retryAfter)) { - // If this is the second attempt and StartRetry was called, we need to stop it. Otherwise + // If this is the second attempt and StartTry was called, we need to stop it. Otherwise // trying to perform same request would use last retry query/headers - request.StopRetry(); return response; } } @@ -163,7 +165,6 @@ std::unique_ptr Azure::Core::Http::RetryPolicy::Send( } } - request.StartRetry(); if (auto bodyStream = request.GetBodyStream()) { bodyStream->Rewind(); @@ -186,6 +187,9 @@ std::unique_ptr Azure::Core::Http::RetryPolicy::Send( std::this_thread::sleep_for(retryAfter); } + // Restore the original query parameters before next retry + request.GetUrl().SetQueryParameters(std::move(originalQueryParameters)); + ctx.ThrowIfCanceled(); } } diff --git a/sdk/core/azure-core/src/http/url.cpp b/sdk/core/azure-core/src/http/url.cpp index 439ba78d5..d389221ff 100644 --- a/sdk/core/azure-core/src/http/url.cpp +++ b/sdk/core/azure-core/src/http/url.cpp @@ -49,14 +49,9 @@ Url::Url(const std::string& url) if (pos != url.end() && *pos == '?') { auto queryIter = std::find(pos + 1, url.end(), '#'); - AppendQueries(std::string(pos + 1, queryIter)); + AppendQueryParameters(std::string(pos + 1, queryIter)); pos = queryIter; } - - if (pos != url.end() && *pos == '#') - { - m_fragment = std::string(pos + 1, url.end()); - } } std::string Url::Decode(const std::string& value) @@ -103,86 +98,20 @@ std::string Url::Decode(const std::string& value) return decodedValue; } -static const char* unreserved - = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~"; -static const char* subdelimiters = "!$&'()*+,;="; - -std::string Url::EncodeHost(const std::string& host) -{ - return EncodeImpl(host, [](int c) { return c > 127; }); -} - -std::string Url::EncodePath(const std::string& path) -{ - const static std::vector shouldEncodeTable = []() { - const std::string pathCharacters - = std::string(unreserved) + std::string(subdelimiters) + "%/:@"; - - std::vector ret(256, true); - for (char c : pathCharacters) - { - ret[c] = false; - } - // we also encode % and + - ret['%'] = true; - ret['+'] = true; - return ret; - }(); - - return EncodeImpl(path, [](int c) { return shouldEncodeTable[c]; }); -} - -std::string Url::EncodeQuery(const std::string& query) -{ - const static std::vector shouldEncodeTable = []() { - std::string queryCharacters = std::string(unreserved) + std::string(subdelimiters) + "%/:@?"; - - std::vector ret(256, true); - for (char c : queryCharacters) - { - ret[c] = false; - } - // we also encode % and + - ret['%'] = true; - ret['+'] = true; - // Surprisingly, '=' also needs to be encoded because Azure Storage server side is so strict. - // We are applying this function to query key and value respectively, so this won't affect - // that = used to separate key and query. - ret['='] = true; - return ret; - }(); - - return EncodeImpl(query, [](int c) { return shouldEncodeTable[c]; }); -} - -std::string Url::EncodeFragment(const std::string& fragment) -{ - const static std::vector shouldEncodeTable = []() { - std::string queryCharacters = std::string(unreserved) + std::string(subdelimiters) + "%/:@?"; - - std::vector ret(256, true); - for (char c : queryCharacters) - { - ret[c] = false; - } - // we also encode % and + - ret['%'] = true; - ret['+'] = true; - return ret; - }(); - - return EncodeImpl(fragment, [](int c) { return shouldEncodeTable[c]; }); -} - -std::string Url::EncodeImpl(const std::string& source, const std::function& shouldEncode) +std::string Url::Encode(const std::string& value, const std::string& doNotEncodeSymbols) { const char* hex = "0123456789ABCDEF"; + std::unordered_set noEncodingSymbolsSet( + doNotEncodeSymbols.begin(), doNotEncodeSymbols.end()); std::string encoded; - for (char c : source) + for (char c : value) { unsigned char uc = c; - if (shouldEncode(uc)) + // encode if char is not in the default non-encoding set AND if it is NOT in chars to ignore + // from user input + if (defaultNonUrlEncodeChars.find(uc) == defaultNonUrlEncodeChars.end() + && noEncodingSymbolsSet.find(uc) == noEncodingSymbolsSet.end()) { encoded += '%'; encoded += hex[(uc >> 4) & 0x0f]; @@ -196,7 +125,7 @@ std::string Url::EncodeImpl(const std::string& source, const std::function Url::defaultNonUrlEncodeChars + = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', + 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', + 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', + 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '.', '_', '~'}; diff --git a/sdk/core/azure-core/test/e2e/CMakeLists.txt b/sdk/core/azure-core/test/e2e/CMakeLists.txt index a6ad5d7eb..f625e2748 100644 --- a/sdk/core/azure-core/test/e2e/CMakeLists.txt +++ b/sdk/core/azure-core/test/e2e/CMakeLists.txt @@ -34,15 +34,15 @@ add_executable ( azure_core_storage_list_containers_sample ) -add_executable ( - ${TARGET_NAME_STORAGE_REUSE_CONNECTION} - azure_hang -) +#add_executable ( +# ${TARGET_NAME_STORAGE_REUSE_CONNECTION} +# azure_hang +#) target_link_libraries(${TARGET_NAME} PRIVATE azure-core) target_link_libraries(${TARGET_NAME_STREAM} PRIVATE azure-core) target_link_libraries(${TARGET_NAME_STORAGE_ISSUE_249} PRIVATE azure-core) target_link_libraries(${TARGET_NAME_STORAGE_ISSUE_248} PRIVATE azure-core) -target_link_libraries(${TARGET_NAME_STORAGE_REUSE_CONNECTION} PRIVATE azure-core azure::storage::files::datalake azure-storage-common) +#target_link_libraries(${TARGET_NAME_STORAGE_REUSE_CONNECTION} PRIVATE azure-core azure::storage::files::datalake azure-storage-common) endif() diff --git a/sdk/core/azure-core/test/e2e/azure_core_with_curl_bodyStream.cpp b/sdk/core/azure-core/test/e2e/azure_core_with_curl_bodyStream.cpp index b609dfbe2..e329c59c6 100644 --- a/sdk/core/azure-core/test/e2e/azure_core_with_curl_bodyStream.cpp +++ b/sdk/core/azure-core/test/e2e/azure_core_with_curl_bodyStream.cpp @@ -98,8 +98,8 @@ void doGetRequest(Context const& context, HttpPipeline& pipeline) request.AddHeader("Host", "httpbin.org"); - request.GetUrl().AppendQuery("dynamicArg", "3"); - request.GetUrl().AppendQuery("dynamicArg2", "4"); + request.GetUrl().AppendQueryParameter("dynamicArg", "3"); + request.GetUrl().AppendQueryParameter("dynamicArg2", "4"); auto response = pipeline.Send(context, request); printStream(context, std::move(response)); @@ -155,9 +155,9 @@ void doPutStreamRequest(Context const& context, HttpPipeline& pipeline) request.AddHeader("Content-Length", std::to_string(StreamSize)); - request.GetUrl().AppendQuery("dynamicArg", "1"); - request.GetUrl().AppendQuery("dynamicArg2", "1"); - request.GetUrl().AppendQuery("dynamicArg3", "1"); + request.GetUrl().AppendQueryParameter("dynamicArg", "1"); + request.GetUrl().AppendQueryParameter("dynamicArg2", "1"); + request.GetUrl().AppendQueryParameter("dynamicArg3", "1"); printStream(context, pipeline.Send(context, request)); } diff --git a/sdk/core/azure-core/test/ut/http.cpp b/sdk/core/azure-core/test/ut/http.cpp index 11edf4138..0ac6909ae 100644 --- a/sdk/core/azure-core/test/ut/http.cpp +++ b/sdk/core/azure-core/test/ut/http.cpp @@ -43,7 +43,7 @@ namespace Azure { namespace Core { namespace Test { EXPECT_PRED2([](std::string a, std::string b) { return a == b; }, value2->second, "value2"); // now add to retry headers - req.StartRetry(); + req.StartTry(); // same headers first, then one new EXPECT_NO_THROW(req.AddHeader("namE", "retryValue")); @@ -87,7 +87,7 @@ namespace Azure { namespace Core { namespace Test { { Http::HttpMethod httpMethod = Http::HttpMethod::Put; Http::Url url("http://test.com"); - EXPECT_NO_THROW(url.AppendQuery("query", "value")); + EXPECT_NO_THROW(url.AppendQueryParameter("query", "value")); Http::Request req(httpMethod, url); @@ -100,16 +100,16 @@ namespace Azure { namespace Core { namespace Test { Http::Request req_with_query(httpMethod, url_with_query); // override if adding same query parameter key that is already in url - EXPECT_NO_THROW(req_with_query.GetUrl().AppendQuery("query", "value")); + EXPECT_NO_THROW(req_with_query.GetUrl().AppendQueryParameter("query", "value")); EXPECT_PRED2( [](std::string a, std::string b) { return a == b; }, req_with_query.GetUrl().GetAbsoluteUrl(), "http://test.com?query=value"); // retry query params testing - req_with_query.StartRetry(); + req_with_query.StartTry(); // same query parameter should override previous - EXPECT_NO_THROW(req_with_query.GetUrl().AppendQuery("query", "retryValue")); + EXPECT_NO_THROW(req_with_query.GetUrl().AppendQueryParameter("query", "retryValue")); EXPECT_TRUE(req_with_query.m_retryModeEnabled); @@ -117,15 +117,40 @@ namespace Azure { namespace Core { namespace Test { [](std::string a, std::string b) { return a == b; }, req_with_query.GetUrl().GetAbsoluteUrl(), "http://test.com?query=retryValue"); + } - // Stop retry. Request should return original query - req_with_query.StopRetry(); - EXPECT_FALSE(req_with_query.m_retryModeEnabled); + TEST(TestHttp, query_parameter_encode_decode) + { + Http::HttpMethod httpMethod = Http::HttpMethod::Put; + Http::Url url("http://test.com"); + EXPECT_NO_THROW(url.AppendQueryParameter("query", Http::Url::Encode("va=lue"))); + // Default encoder from URL won't encode an equal symbol EXPECT_PRED2( [](std::string a, std::string b) { return a == b; }, - req_with_query.GetUrl().GetAbsoluteUrl(), - "http://test.com?query=value"); + url.GetAbsoluteUrl(), + "http://test.com?query=va%3Dlue"); + + // Provide symbol to do not encode + EXPECT_NO_THROW(url.AppendQueryParameter("query", Http::Url::Encode("va=lue", "="))); + EXPECT_PRED2( + [](std::string a, std::string b) { return a == b; }, + url.GetAbsoluteUrl(), + "http://test.com?query=va=lue"); + + // Provide more than one extra symbol to be encoded + EXPECT_NO_THROW(url.AppendQueryParameter("query", Http::Url::Encode("va=l u?e", " ?"))); + EXPECT_PRED2( + [](std::string a, std::string b) { return a == b; }, + url.GetAbsoluteUrl(), + "http://test.com?query=va%3Dl u?e"); + + // default, encode it all + EXPECT_NO_THROW(url.AppendQueryParameter("query", Http::Url::Encode("va=l u?e"))); + EXPECT_PRED2( + [](std::string a, std::string b) { return a == b; }, + url.GetAbsoluteUrl(), + "http://test.com?query=va%3Dl%20u%3Fe"); } TEST(TestHttp, add_path) @@ -140,7 +165,7 @@ namespace Azure { namespace Core { namespace Test { req.GetUrl().GetAbsoluteUrl(), "http://test.com/path"); - EXPECT_NO_THROW(req.GetUrl().AppendQuery("query", "value")); + EXPECT_NO_THROW(req.GetUrl().AppendQueryParameter("query", "value")); EXPECT_PRED2( [](std::string a, std::string b) { return a == b; }, req.GetUrl().GetAbsoluteUrl(), diff --git a/sdk/core/azure-core/test/ut/transport_adapter.cpp b/sdk/core/azure-core/test/ut/transport_adapter.cpp index f44d51f65..c38cab3ac 100644 --- a/sdk/core/azure-core/test/ut/transport_adapter.cpp +++ b/sdk/core/azure-core/test/ut/transport_adapter.cpp @@ -121,6 +121,8 @@ namespace Azure { namespace Core { namespace Test { auto expectedResponseBodySize = std::stoull(response->GetHeaders().at("content-length")); CheckBodyFromBuffer(*response, expectedResponseBodySize); + // Need to init request again, since retry would be on after it is sent + request = Azure::Core::Http::Request(Azure::Core::Http::HttpMethod::Get, host); // Add a header and send again. RawResponse should return that header in the body request.AddHeader("123", "456"); response = pipeline.Send(context, request); @@ -268,6 +270,7 @@ namespace Azure { namespace Core { namespace Test { auto expectedResponseBodySize = std::stoull(response->GetHeaders().at("content-length")); CheckBodyFromStream(*response, expectedResponseBodySize); + request = Azure::Core::Http::Request(Azure::Core::Http::HttpMethod::Get, host, true); // Add a header and send again. Response should return that header in the body request.AddHeader("123", "456"); response = pipeline.Send(context, request); diff --git a/sdk/storage/azure-storage-blobs/inc/azure/storage/blobs/protocol/blob_rest_client.hpp b/sdk/storage/azure-storage-blobs/inc/azure/storage/blobs/protocol/blob_rest_client.hpp index 6d7157e19..2cd64db96 100644 --- a/sdk/storage/azure-storage-blobs/inc/azure/storage/blobs/protocol/blob_rest_client.hpp +++ b/sdk/storage/azure-storage-blobs/inc/azure/storage/blobs/protocol/blob_rest_client.hpp @@ -8,6 +8,7 @@ #include "azure/core/http/pipeline.hpp" #include "azure/core/nullable.hpp" #include "azure/core/response.hpp" +#include "azure/storage/common/crypt.hpp" #include "azure/storage/common/storage_common.hpp" #include "azure/storage/common/storage_error.hpp" #include "azure/storage/common/xml_wrapper.hpp" @@ -1707,26 +1708,31 @@ namespace Azure { namespace Storage { namespace Blobs { request.AddHeader("x-ms-version", c_ApiVersion); if (options.Timeout.HasValue()) { - request.GetUrl().AppendQuery("timeout", std::to_string(options.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + "timeout", std::to_string(options.Timeout.GetValue())); } - request.GetUrl().AppendQuery("comp", "list"); + request.GetUrl().AppendQueryParameter("comp", "list"); if (options.Prefix.HasValue()) { - request.GetUrl().AppendQuery("prefix", options.Prefix.GetValue()); + request.GetUrl().AppendQueryParameter( + "prefix", Details::UrlEncodeQueryParameter(options.Prefix.GetValue())); } if (options.Marker.HasValue()) { - request.GetUrl().AppendQuery("marker", options.Marker.GetValue()); + request.GetUrl().AppendQueryParameter( + "marker", Details::UrlEncodeQueryParameter(options.Marker.GetValue())); } if (options.MaxResults.HasValue()) { - request.GetUrl().AppendQuery("maxresults", std::to_string(options.MaxResults.GetValue())); + request.GetUrl().AppendQueryParameter( + "maxresults", std::to_string(options.MaxResults.GetValue())); } std::string list_blob_containers_include_item = ListBlobContainersIncludeItemToString(options.Include); if (!list_blob_containers_include_item.empty()) { - request.GetUrl().AppendQuery("include", list_blob_containers_include_item); + request.GetUrl().AppendQueryParameter( + "include", Details::UrlEncodeQueryParameter(list_blob_containers_include_item)); } auto pHttpResponse = pipeline.Send(context, request); Azure::Core::Http::RawResponse& httpResponse = *pHttpResponse; @@ -1774,12 +1780,13 @@ namespace Azure { namespace Storage { namespace Blobs { auto request = Azure::Core::Http::Request( Azure::Core::Http::HttpMethod::Post, url, &xml_body_stream); request.AddHeader("Content-Length", std::to_string(xml_body_stream.Length())); - request.GetUrl().AppendQuery("restype", "service"); - request.GetUrl().AppendQuery("comp", "userdelegationkey"); + request.GetUrl().AppendQueryParameter("restype", "service"); + request.GetUrl().AppendQueryParameter("comp", "userdelegationkey"); request.AddHeader("x-ms-version", c_ApiVersion); if (options.Timeout.HasValue()) { - request.GetUrl().AppendQuery("timeout", std::to_string(options.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + "timeout", std::to_string(options.Timeout.GetValue())); } auto pHttpResponse = pipeline.Send(context, request); Azure::Core::Http::RawResponse& httpResponse = *pHttpResponse; @@ -1814,12 +1821,13 @@ namespace Azure { namespace Storage { namespace Blobs { { unused(options); auto request = Azure::Core::Http::Request(Azure::Core::Http::HttpMethod::Get, url); - request.GetUrl().AppendQuery("restype", "service"); - request.GetUrl().AppendQuery("comp", "properties"); + request.GetUrl().AppendQueryParameter("restype", "service"); + request.GetUrl().AppendQueryParameter("comp", "properties"); request.AddHeader("x-ms-version", c_ApiVersion); if (options.Timeout.HasValue()) { - request.GetUrl().AppendQuery("timeout", std::to_string(options.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + "timeout", std::to_string(options.Timeout.GetValue())); } auto pHttpResponse = pipeline.Send(context, request); Azure::Core::Http::RawResponse& httpResponse = *pHttpResponse; @@ -1866,12 +1874,13 @@ namespace Azure { namespace Storage { namespace Blobs { auto request = Azure::Core::Http::Request(Azure::Core::Http::HttpMethod::Put, url, &xml_body_stream); request.AddHeader("Content-Length", std::to_string(xml_body_stream.Length())); - request.GetUrl().AppendQuery("restype", "service"); - request.GetUrl().AppendQuery("comp", "properties"); + request.GetUrl().AppendQueryParameter("restype", "service"); + request.GetUrl().AppendQueryParameter("comp", "properties"); request.AddHeader("x-ms-version", c_ApiVersion); if (options.Timeout.HasValue()) { - request.GetUrl().AppendQuery("timeout", std::to_string(options.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + "timeout", std::to_string(options.Timeout.GetValue())); } auto pHttpResponse = pipeline.Send(context, request); Azure::Core::Http::RawResponse& httpResponse = *pHttpResponse; @@ -1900,12 +1909,13 @@ namespace Azure { namespace Storage { namespace Blobs { { unused(options); auto request = Azure::Core::Http::Request(Azure::Core::Http::HttpMethod::Head, url); - request.GetUrl().AppendQuery("restype", "account"); - request.GetUrl().AppendQuery("comp", "properties"); + request.GetUrl().AppendQueryParameter("restype", "account"); + request.GetUrl().AppendQueryParameter("comp", "properties"); request.AddHeader("x-ms-version", c_ApiVersion); if (options.Timeout.HasValue()) { - request.GetUrl().AppendQuery("timeout", std::to_string(options.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + "timeout", std::to_string(options.Timeout.GetValue())); } auto pHttpResponse = pipeline.Send(context, request); Azure::Core::Http::RawResponse& httpResponse = *pHttpResponse; @@ -1937,12 +1947,13 @@ namespace Azure { namespace Storage { namespace Blobs { { unused(options); auto request = Azure::Core::Http::Request(Azure::Core::Http::HttpMethod::Get, url); - request.GetUrl().AppendQuery("restype", "service"); - request.GetUrl().AppendQuery("comp", "stats"); + request.GetUrl().AppendQueryParameter("restype", "service"); + request.GetUrl().AppendQueryParameter("comp", "stats"); request.AddHeader("x-ms-version", c_ApiVersion); if (options.Timeout.HasValue()) { - request.GetUrl().AppendQuery("timeout", std::to_string(options.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + "timeout", std::to_string(options.Timeout.GetValue())); } auto pHttpResponse = pipeline.Send(context, request); Azure::Core::Http::RawResponse& httpResponse = *pHttpResponse; @@ -1983,17 +1994,21 @@ namespace Azure { namespace Storage { namespace Blobs { request.AddHeader("x-ms-version", c_ApiVersion); if (options.Timeout.HasValue()) { - request.GetUrl().AppendQuery("timeout", std::to_string(options.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + "timeout", std::to_string(options.Timeout.GetValue())); } - request.GetUrl().AppendQuery("comp", "blobs"); - request.GetUrl().AppendQuery("where", options.Where); + request.GetUrl().AppendQueryParameter("comp", "blobs"); + request.GetUrl().AppendQueryParameter( + "where", Details::UrlEncodeQueryParameter(options.Where)); if (options.Marker.HasValue()) { - request.GetUrl().AppendQuery("marker", options.Marker.GetValue()); + request.GetUrl().AppendQueryParameter( + "marker", Details::UrlEncodeQueryParameter(options.Marker.GetValue())); } if (options.MaxResults.HasValue()) { - request.GetUrl().AppendQuery("maxresults", std::to_string(options.MaxResults.GetValue())); + request.GetUrl().AppendQueryParameter( + "maxresults", std::to_string(options.MaxResults.GetValue())); } auto pHttpResponse = pipeline.Send(context, request); Azure::Core::Http::RawResponse& httpResponse = *pHttpResponse; @@ -3448,11 +3463,12 @@ namespace Azure { namespace Storage { namespace Blobs { unused(options); auto request = Azure::Core::Http::Request(Azure::Core::Http::HttpMethod::Put, url); request.AddHeader("Content-Length", "0"); - request.GetUrl().AppendQuery("restype", "container"); + request.GetUrl().AppendQueryParameter("restype", "container"); request.AddHeader("x-ms-version", c_ApiVersion); if (options.Timeout.HasValue()) { - request.GetUrl().AppendQuery("timeout", std::to_string(options.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + "timeout", std::to_string(options.Timeout.GetValue())); } std::set metadataKeys; for (const auto& pair : options.Metadata) @@ -3516,11 +3532,12 @@ namespace Azure { namespace Storage { namespace Blobs { { unused(options); auto request = Azure::Core::Http::Request(Azure::Core::Http::HttpMethod::Delete, url); - request.GetUrl().AppendQuery("restype", "container"); + request.GetUrl().AppendQueryParameter("restype", "container"); request.AddHeader("x-ms-version", c_ApiVersion); if (options.Timeout.HasValue()) { - request.GetUrl().AppendQuery("timeout", std::to_string(options.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + "timeout", std::to_string(options.Timeout.GetValue())); } if (options.LeaseId.HasValue()) { @@ -3564,12 +3581,13 @@ namespace Azure { namespace Storage { namespace Blobs { unused(options); auto request = Azure::Core::Http::Request(Azure::Core::Http::HttpMethod::Put, url); request.AddHeader("Content-Length", "0"); - request.GetUrl().AppendQuery("restype", "container"); - request.GetUrl().AppendQuery("comp", "undelete"); + request.GetUrl().AppendQueryParameter("restype", "container"); + request.GetUrl().AppendQueryParameter("comp", "undelete"); request.AddHeader("x-ms-version", c_ApiVersion); if (options.Timeout.HasValue()) { - request.GetUrl().AppendQuery("timeout", std::to_string(options.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + "timeout", std::to_string(options.Timeout.GetValue())); } request.AddHeader("x-ms-deleted-container-name", options.DeletedContainerName); request.AddHeader("x-ms-deleted-container-version", options.DeletedContainerVersion); @@ -3601,11 +3619,12 @@ namespace Azure { namespace Storage { namespace Blobs { { unused(options); auto request = Azure::Core::Http::Request(Azure::Core::Http::HttpMethod::Head, url); - request.GetUrl().AppendQuery("restype", "container"); + request.GetUrl().AppendQueryParameter("restype", "container"); request.AddHeader("x-ms-version", c_ApiVersion); if (options.Timeout.HasValue()) { - request.GetUrl().AppendQuery("timeout", std::to_string(options.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + "timeout", std::to_string(options.Timeout.GetValue())); } if (options.LeaseId.HasValue()) { @@ -3673,12 +3692,13 @@ namespace Azure { namespace Storage { namespace Blobs { unused(options); auto request = Azure::Core::Http::Request(Azure::Core::Http::HttpMethod::Put, url); request.AddHeader("Content-Length", "0"); - request.GetUrl().AppendQuery("restype", "container"); - request.GetUrl().AppendQuery("comp", "metadata"); + request.GetUrl().AppendQueryParameter("restype", "container"); + request.GetUrl().AppendQueryParameter("comp", "metadata"); request.AddHeader("x-ms-version", c_ApiVersion); if (options.Timeout.HasValue()) { - request.GetUrl().AppendQuery("timeout", std::to_string(options.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + "timeout", std::to_string(options.Timeout.GetValue())); } std::set metadataKeys; for (const auto& pair : options.Metadata) @@ -3738,26 +3758,31 @@ namespace Azure { namespace Storage { namespace Blobs { request.AddHeader("x-ms-version", c_ApiVersion); if (options.Timeout.HasValue()) { - request.GetUrl().AppendQuery("timeout", std::to_string(options.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + "timeout", std::to_string(options.Timeout.GetValue())); } - request.GetUrl().AppendQuery("restype", "container"); - request.GetUrl().AppendQuery("comp", "list"); + request.GetUrl().AppendQueryParameter("restype", "container"); + request.GetUrl().AppendQueryParameter("comp", "list"); if (options.Prefix.HasValue()) { - request.GetUrl().AppendQuery("prefix", options.Prefix.GetValue()); + request.GetUrl().AppendQueryParameter( + "prefix", Details::UrlEncodeQueryParameter(options.Prefix.GetValue())); } if (options.Marker.HasValue()) { - request.GetUrl().AppendQuery("marker", options.Marker.GetValue()); + request.GetUrl().AppendQueryParameter( + "marker", Details::UrlEncodeQueryParameter(options.Marker.GetValue())); } if (options.MaxResults.HasValue()) { - request.GetUrl().AppendQuery("maxresults", std::to_string(options.MaxResults.GetValue())); + request.GetUrl().AppendQueryParameter( + "maxresults", std::to_string(options.MaxResults.GetValue())); } std::string list_blobs_include_item = ListBlobsIncludeItemToString(options.Include); if (!list_blobs_include_item.empty()) { - request.GetUrl().AppendQuery("include", list_blobs_include_item); + request.GetUrl().AppendQueryParameter( + "include", Details::UrlEncodeQueryParameter(list_blobs_include_item)); } auto pHttpResponse = pipeline.Send(context, request); Azure::Core::Http::RawResponse& httpResponse = *pHttpResponse; @@ -3800,30 +3825,36 @@ namespace Azure { namespace Storage { namespace Blobs { request.AddHeader("x-ms-version", c_ApiVersion); if (options.Timeout.HasValue()) { - request.GetUrl().AppendQuery("timeout", std::to_string(options.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + "timeout", std::to_string(options.Timeout.GetValue())); } - request.GetUrl().AppendQuery("restype", "container"); - request.GetUrl().AppendQuery("comp", "list"); + request.GetUrl().AppendQueryParameter("restype", "container"); + request.GetUrl().AppendQueryParameter("comp", "list"); if (options.Prefix.HasValue()) { - request.GetUrl().AppendQuery("prefix", options.Prefix.GetValue()); + request.GetUrl().AppendQueryParameter( + "prefix", Details::UrlEncodeQueryParameter(options.Prefix.GetValue())); } if (options.Delimiter.HasValue()) { - request.GetUrl().AppendQuery("delimiter", options.Delimiter.GetValue()); + request.GetUrl().AppendQueryParameter( + "delimiter", Details::UrlEncodeQueryParameter(options.Delimiter.GetValue())); } if (options.Marker.HasValue()) { - request.GetUrl().AppendQuery("marker", options.Marker.GetValue()); + request.GetUrl().AppendQueryParameter( + "marker", Details::UrlEncodeQueryParameter(options.Marker.GetValue())); } if (options.MaxResults.HasValue()) { - request.GetUrl().AppendQuery("maxresults", std::to_string(options.MaxResults.GetValue())); + request.GetUrl().AppendQueryParameter( + "maxresults", std::to_string(options.MaxResults.GetValue())); } std::string list_blobs_include_item = ListBlobsIncludeItemToString(options.Include); if (!list_blobs_include_item.empty()) { - request.GetUrl().AppendQuery("include", list_blobs_include_item); + request.GetUrl().AppendQueryParameter( + "include", Details::UrlEncodeQueryParameter(list_blobs_include_item)); } auto pHttpResponse = pipeline.Send(context, request); Azure::Core::Http::RawResponse& httpResponse = *pHttpResponse; @@ -3862,10 +3893,11 @@ namespace Azure { namespace Storage { namespace Blobs { request.AddHeader("x-ms-version", c_ApiVersion); if (options.Timeout.HasValue()) { - request.GetUrl().AppendQuery("timeout", std::to_string(options.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + "timeout", std::to_string(options.Timeout.GetValue())); } - request.GetUrl().AppendQuery("restype", "container"); - request.GetUrl().AppendQuery("comp", "acl"); + request.GetUrl().AppendQueryParameter("restype", "container"); + request.GetUrl().AppendQueryParameter("comp", "acl"); auto pHttpResponse = pipeline.Send(context, request); Azure::Core::Http::RawResponse& httpResponse = *pHttpResponse; GetContainerAccessPolicyResult response; @@ -3922,10 +3954,11 @@ namespace Azure { namespace Storage { namespace Blobs { request.AddHeader("x-ms-version", c_ApiVersion); if (options.Timeout.HasValue()) { - request.GetUrl().AppendQuery("timeout", std::to_string(options.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + "timeout", std::to_string(options.Timeout.GetValue())); } - request.GetUrl().AppendQuery("restype", "container"); - request.GetUrl().AppendQuery("comp", "acl"); + request.GetUrl().AppendQueryParameter("restype", "container"); + request.GetUrl().AppendQueryParameter("comp", "acl"); if (options.AccessType.HasValue()) { request.AddHeader( @@ -3980,10 +4013,11 @@ namespace Azure { namespace Storage { namespace Blobs { request.AddHeader("x-ms-version", c_ApiVersion); if (options.Timeout.HasValue()) { - request.GetUrl().AppendQuery("timeout", std::to_string(options.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + "timeout", std::to_string(options.Timeout.GetValue())); } - request.GetUrl().AppendQuery("restype", "container"); - request.GetUrl().AppendQuery("comp", "lease"); + request.GetUrl().AppendQueryParameter("restype", "container"); + request.GetUrl().AppendQueryParameter("comp", "lease"); request.AddHeader("x-ms-lease-action", "acquire"); request.AddHeader("x-ms-lease-duration", std::to_string(options.LeaseDuration)); if (options.ProposedLeaseId.HasValue()) @@ -4035,10 +4069,11 @@ namespace Azure { namespace Storage { namespace Blobs { request.AddHeader("x-ms-version", c_ApiVersion); if (options.Timeout.HasValue()) { - request.GetUrl().AppendQuery("timeout", std::to_string(options.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + "timeout", std::to_string(options.Timeout.GetValue())); } - request.GetUrl().AppendQuery("restype", "container"); - request.GetUrl().AppendQuery("comp", "lease"); + request.GetUrl().AppendQueryParameter("restype", "container"); + request.GetUrl().AppendQueryParameter("comp", "lease"); request.AddHeader("x-ms-lease-action", "renew"); request.AddHeader("x-ms-lease-id", options.LeaseId); if (options.IfModifiedSince.HasValue()) @@ -4087,10 +4122,11 @@ namespace Azure { namespace Storage { namespace Blobs { request.AddHeader("x-ms-version", c_ApiVersion); if (options.Timeout.HasValue()) { - request.GetUrl().AppendQuery("timeout", std::to_string(options.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + "timeout", std::to_string(options.Timeout.GetValue())); } - request.GetUrl().AppendQuery("restype", "container"); - request.GetUrl().AppendQuery("comp", "lease"); + request.GetUrl().AppendQueryParameter("restype", "container"); + request.GetUrl().AppendQueryParameter("comp", "lease"); request.AddHeader("x-ms-lease-action", "change"); request.AddHeader("x-ms-lease-id", options.LeaseId); request.AddHeader("x-ms-proposed-lease-id", options.ProposedLeaseId); @@ -4139,10 +4175,11 @@ namespace Azure { namespace Storage { namespace Blobs { request.AddHeader("x-ms-version", c_ApiVersion); if (options.Timeout.HasValue()) { - request.GetUrl().AppendQuery("timeout", std::to_string(options.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + "timeout", std::to_string(options.Timeout.GetValue())); } - request.GetUrl().AppendQuery("restype", "container"); - request.GetUrl().AppendQuery("comp", "lease"); + request.GetUrl().AppendQueryParameter("restype", "container"); + request.GetUrl().AppendQueryParameter("comp", "lease"); request.AddHeader("x-ms-lease-action", "release"); request.AddHeader("x-ms-lease-id", options.LeaseId); if (options.IfModifiedSince.HasValue()) @@ -4189,10 +4226,11 @@ namespace Azure { namespace Storage { namespace Blobs { request.AddHeader("x-ms-version", c_ApiVersion); if (options.Timeout.HasValue()) { - request.GetUrl().AppendQuery("timeout", std::to_string(options.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + "timeout", std::to_string(options.Timeout.GetValue())); } - request.GetUrl().AppendQuery("restype", "container"); - request.GetUrl().AppendQuery("comp", "lease"); + request.GetUrl().AppendQueryParameter("restype", "container"); + request.GetUrl().AppendQueryParameter("comp", "lease"); request.AddHeader("x-ms-lease-action", "break"); if (options.BreakPeriod.HasValue()) { @@ -5156,7 +5194,8 @@ namespace Azure { namespace Storage { namespace Blobs { request.AddHeader("x-ms-version", c_ApiVersion); if (options.Timeout.HasValue()) { - request.GetUrl().AppendQuery("timeout", std::to_string(options.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + "timeout", std::to_string(options.Timeout.GetValue())); } if (options.Range.HasValue()) { @@ -5424,7 +5463,8 @@ namespace Azure { namespace Storage { namespace Blobs { request.AddHeader("x-ms-version", c_ApiVersion); if (options.Timeout.HasValue()) { - request.GetUrl().AppendQuery("timeout", std::to_string(options.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + "timeout", std::to_string(options.Timeout.GetValue())); } if (options.DeleteSnapshots.HasValue()) { @@ -5507,9 +5547,10 @@ namespace Azure { namespace Storage { namespace Blobs { request.AddHeader("x-ms-version", c_ApiVersion); if (options.Timeout.HasValue()) { - request.GetUrl().AppendQuery("timeout", std::to_string(options.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + "timeout", std::to_string(options.Timeout.GetValue())); } - request.GetUrl().AppendQuery("comp", "expiry"); + request.GetUrl().AppendQueryParameter("comp", "expiry"); request.AddHeader( "x-ms-expiry-option", ScheduleBlobExpiryOriginTypeToString(options.ExpiryOrigin)); if (options.ExpiryTime.HasValue()) @@ -5547,9 +5588,10 @@ namespace Azure { namespace Storage { namespace Blobs { request.AddHeader("x-ms-version", c_ApiVersion); if (options.Timeout.HasValue()) { - request.GetUrl().AppendQuery("timeout", std::to_string(options.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + "timeout", std::to_string(options.Timeout.GetValue())); } - request.GetUrl().AppendQuery("comp", "undelete"); + request.GetUrl().AppendQueryParameter("comp", "undelete"); auto pHttpResponse = pipeline.Send(context, request); Azure::Core::Http::RawResponse& httpResponse = *pHttpResponse; UndeleteBlobResult response; @@ -5589,7 +5631,8 @@ namespace Azure { namespace Storage { namespace Blobs { request.AddHeader("x-ms-version", c_ApiVersion); if (options.Timeout.HasValue()) { - request.GetUrl().AppendQuery("timeout", std::to_string(options.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + "timeout", std::to_string(options.Timeout.GetValue())); } if (options.EncryptionKey.HasValue()) { @@ -5873,11 +5916,12 @@ namespace Azure { namespace Storage { namespace Blobs { unused(options); auto request = Azure::Core::Http::Request(Azure::Core::Http::HttpMethod::Put, url); request.AddHeader("Content-Length", "0"); - request.GetUrl().AppendQuery("comp", "properties"); + request.GetUrl().AppendQueryParameter("comp", "properties"); request.AddHeader("x-ms-version", c_ApiVersion); if (options.Timeout.HasValue()) { - request.GetUrl().AppendQuery("timeout", std::to_string(options.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + "timeout", std::to_string(options.Timeout.GetValue())); } if (!options.HttpHeaders.ContentType.empty()) { @@ -5975,11 +6019,12 @@ namespace Azure { namespace Storage { namespace Blobs { unused(options); auto request = Azure::Core::Http::Request(Azure::Core::Http::HttpMethod::Put, url); request.AddHeader("Content-Length", "0"); - request.GetUrl().AppendQuery("comp", "metadata"); + request.GetUrl().AppendQueryParameter("comp", "metadata"); request.AddHeader("x-ms-version", c_ApiVersion); if (options.Timeout.HasValue()) { - request.GetUrl().AppendQuery("timeout", std::to_string(options.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + "timeout", std::to_string(options.Timeout.GetValue())); } std::set metadataKeys; for (const auto& pair : options.Metadata) @@ -6068,11 +6113,12 @@ namespace Azure { namespace Storage { namespace Blobs { unused(options); auto request = Azure::Core::Http::Request(Azure::Core::Http::HttpMethod::Put, url); request.AddHeader("Content-Length", "0"); - request.GetUrl().AppendQuery("comp", "tier"); + request.GetUrl().AppendQueryParameter("comp", "tier"); request.AddHeader("x-ms-version", c_ApiVersion); if (options.Timeout.HasValue()) { - request.GetUrl().AppendQuery("timeout", std::to_string(options.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + "timeout", std::to_string(options.Timeout.GetValue())); } request.AddHeader("x-ms-access-tier", AccessTierToString(options.Tier)); if (options.RehydratePriority.HasValue()) @@ -6151,7 +6197,8 @@ namespace Azure { namespace Storage { namespace Blobs { request.AddHeader("x-ms-version", c_ApiVersion); if (options.Timeout.HasValue()) { - request.GetUrl().AppendQuery("timeout", std::to_string(options.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + "timeout", std::to_string(options.Timeout.GetValue())); } std::set metadataKeys; for (const auto& pair : options.Metadata) @@ -6276,10 +6323,12 @@ namespace Azure { namespace Storage { namespace Blobs { request.AddHeader("x-ms-version", c_ApiVersion); if (options.Timeout.HasValue()) { - request.GetUrl().AppendQuery("timeout", std::to_string(options.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + "timeout", std::to_string(options.Timeout.GetValue())); } - request.GetUrl().AppendQuery("comp", "copy"); - request.GetUrl().AppendQuery("copyid", options.CopyId); + request.GetUrl().AppendQueryParameter("comp", "copy"); + request.GetUrl().AppendQueryParameter( + "copyid", Details::UrlEncodeQueryParameter(options.CopyId)); request.AddHeader("x-ms-copy-action", "abort"); if (options.LeaseId.HasValue()) { @@ -6324,11 +6373,12 @@ namespace Azure { namespace Storage { namespace Blobs { unused(options); auto request = Azure::Core::Http::Request(Azure::Core::Http::HttpMethod::Put, url); request.AddHeader("Content-Length", "0"); - request.GetUrl().AppendQuery("comp", "snapshot"); + request.GetUrl().AppendQueryParameter("comp", "snapshot"); request.AddHeader("x-ms-version", c_ApiVersion); if (options.Timeout.HasValue()) { - request.GetUrl().AppendQuery("timeout", std::to_string(options.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + "timeout", std::to_string(options.Timeout.GetValue())); } if (options.EncryptionKey.HasValue()) { @@ -6443,9 +6493,10 @@ namespace Azure { namespace Storage { namespace Blobs { request.AddHeader("x-ms-version", c_ApiVersion); if (options.Timeout.HasValue()) { - request.GetUrl().AppendQuery("timeout", std::to_string(options.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + "timeout", std::to_string(options.Timeout.GetValue())); } - request.GetUrl().AppendQuery("comp", "tags"); + request.GetUrl().AppendQueryParameter("comp", "tags"); if (options.IfTags.HasValue()) { request.AddHeader("x-ms-if-tags", options.IfTags.GetValue()); @@ -6499,9 +6550,10 @@ namespace Azure { namespace Storage { namespace Blobs { request.AddHeader("x-ms-version", c_ApiVersion); if (options.Timeout.HasValue()) { - request.GetUrl().AppendQuery("timeout", std::to_string(options.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + "timeout", std::to_string(options.Timeout.GetValue())); } - request.GetUrl().AppendQuery("comp", "tags"); + request.GetUrl().AppendQueryParameter("comp", "tags"); request.AddHeader("Content-Type", "application/xml; charset=UTF-8"); if (options.IfTags.HasValue()) { @@ -6545,9 +6597,10 @@ namespace Azure { namespace Storage { namespace Blobs { request.AddHeader("x-ms-version", c_ApiVersion); if (options.Timeout.HasValue()) { - request.GetUrl().AppendQuery("timeout", std::to_string(options.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + "timeout", std::to_string(options.Timeout.GetValue())); } - request.GetUrl().AppendQuery("comp", "lease"); + request.GetUrl().AppendQueryParameter("comp", "lease"); request.AddHeader("x-ms-lease-action", "acquire"); request.AddHeader("x-ms-lease-duration", std::to_string(options.LeaseDuration)); if (options.ProposedLeaseId.HasValue()) @@ -6614,9 +6667,10 @@ namespace Azure { namespace Storage { namespace Blobs { request.AddHeader("x-ms-version", c_ApiVersion); if (options.Timeout.HasValue()) { - request.GetUrl().AppendQuery("timeout", std::to_string(options.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + "timeout", std::to_string(options.Timeout.GetValue())); } - request.GetUrl().AppendQuery("comp", "lease"); + request.GetUrl().AppendQueryParameter("comp", "lease"); request.AddHeader("x-ms-lease-action", "renew"); request.AddHeader("x-ms-lease-id", options.LeaseId); if (options.IfModifiedSince.HasValue()) @@ -6680,9 +6734,10 @@ namespace Azure { namespace Storage { namespace Blobs { request.AddHeader("x-ms-version", c_ApiVersion); if (options.Timeout.HasValue()) { - request.GetUrl().AppendQuery("timeout", std::to_string(options.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + "timeout", std::to_string(options.Timeout.GetValue())); } - request.GetUrl().AppendQuery("comp", "lease"); + request.GetUrl().AppendQueryParameter("comp", "lease"); request.AddHeader("x-ms-lease-action", "change"); request.AddHeader("x-ms-lease-id", options.LeaseId); request.AddHeader("x-ms-proposed-lease-id", options.ProposedLeaseId); @@ -6746,9 +6801,10 @@ namespace Azure { namespace Storage { namespace Blobs { request.AddHeader("x-ms-version", c_ApiVersion); if (options.Timeout.HasValue()) { - request.GetUrl().AppendQuery("timeout", std::to_string(options.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + "timeout", std::to_string(options.Timeout.GetValue())); } - request.GetUrl().AppendQuery("comp", "lease"); + request.GetUrl().AppendQueryParameter("comp", "lease"); request.AddHeader("x-ms-lease-action", "release"); request.AddHeader("x-ms-lease-id", options.LeaseId); if (options.IfModifiedSince.HasValue()) @@ -6816,9 +6872,10 @@ namespace Azure { namespace Storage { namespace Blobs { request.AddHeader("x-ms-version", c_ApiVersion); if (options.Timeout.HasValue()) { - request.GetUrl().AppendQuery("timeout", std::to_string(options.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + "timeout", std::to_string(options.Timeout.GetValue())); } - request.GetUrl().AppendQuery("comp", "lease"); + request.GetUrl().AppendQueryParameter("comp", "lease"); request.AddHeader("x-ms-lease-action", "break"); if (options.BreakPeriod.HasValue()) { @@ -7026,7 +7083,8 @@ namespace Azure { namespace Storage { namespace Blobs { request.AddHeader("x-ms-version", c_ApiVersion); if (options.Timeout.HasValue()) { - request.GetUrl().AppendQuery("timeout", std::to_string(options.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + "timeout", std::to_string(options.Timeout.GetValue())); } if (options.EncryptionKey.HasValue()) { @@ -7198,12 +7256,14 @@ namespace Azure { namespace Storage { namespace Blobs { auto request = Azure::Core::Http::Request(Azure::Core::Http::HttpMethod::Put, url, requestBody); request.AddHeader("Content-Length", std::to_string(requestBody->Length())); - request.GetUrl().AppendQuery("comp", "block"); - request.GetUrl().AppendQuery("blockid", options.BlockId); + request.GetUrl().AppendQueryParameter("comp", "block"); + request.GetUrl().AppendQueryParameter( + "blockid", Details::UrlEncodeQueryParameter(options.BlockId)); request.AddHeader("x-ms-version", c_ApiVersion); if (options.Timeout.HasValue()) { - request.GetUrl().AppendQuery("timeout", std::to_string(options.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + "timeout", std::to_string(options.Timeout.GetValue())); } if (options.TransactionalContentMd5.HasValue()) { @@ -7308,12 +7368,14 @@ namespace Azure { namespace Storage { namespace Blobs { unused(options); auto request = Azure::Core::Http::Request(Azure::Core::Http::HttpMethod::Put, url); request.AddHeader("Content-Length", "0"); - request.GetUrl().AppendQuery("comp", "block"); - request.GetUrl().AppendQuery("blockid", options.BlockId); + request.GetUrl().AppendQueryParameter("comp", "block"); + request.GetUrl().AppendQueryParameter( + "blockid", Details::UrlEncodeQueryParameter(options.BlockId)); request.AddHeader("x-ms-version", c_ApiVersion); if (options.Timeout.HasValue()) { - request.GetUrl().AppendQuery("timeout", std::to_string(options.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + "timeout", std::to_string(options.Timeout.GetValue())); } request.AddHeader("x-ms-copy-source", options.SourceUri); if (options.SourceRange.HasValue()) @@ -7463,11 +7525,12 @@ namespace Azure { namespace Storage { namespace Blobs { auto request = Azure::Core::Http::Request(Azure::Core::Http::HttpMethod::Put, url, &xml_body_stream); request.AddHeader("Content-Length", std::to_string(xml_body_stream.Length())); - request.GetUrl().AppendQuery("comp", "blocklist"); + request.GetUrl().AppendQueryParameter("comp", "blocklist"); request.AddHeader("x-ms-version", c_ApiVersion); if (options.Timeout.HasValue()) { - request.GetUrl().AppendQuery("timeout", std::to_string(options.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + "timeout", std::to_string(options.Timeout.GetValue())); } if (!options.HttpHeaders.ContentType.empty()) { @@ -7609,17 +7672,19 @@ namespace Azure { namespace Storage { namespace Blobs { { unused(options); auto request = Azure::Core::Http::Request(Azure::Core::Http::HttpMethod::Get, url); - request.GetUrl().AppendQuery("comp", "blocklist"); + request.GetUrl().AppendQueryParameter("comp", "blocklist"); if (options.ListType.HasValue()) { std::string block_list_type_option = BlockListTypeOptionToString(options.ListType.GetValue()); - request.GetUrl().AppendQuery("blocklisttype", block_list_type_option); + request.GetUrl().AppendQueryParameter( + "blocklisttype", Details::UrlEncodeQueryParameter(block_list_type_option)); } request.AddHeader("x-ms-version", c_ApiVersion); if (options.Timeout.HasValue()) { - request.GetUrl().AppendQuery("timeout", std::to_string(options.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + "timeout", std::to_string(options.Timeout.GetValue())); } if (options.LeaseId.HasValue()) { @@ -7835,7 +7900,8 @@ namespace Azure { namespace Storage { namespace Blobs { request.AddHeader("x-ms-version", c_ApiVersion); if (options.Timeout.HasValue()) { - request.GetUrl().AppendQuery("timeout", std::to_string(options.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + "timeout", std::to_string(options.Timeout.GetValue())); } if (!options.HttpHeaders.ContentType.empty()) { @@ -8000,11 +8066,12 @@ namespace Azure { namespace Storage { namespace Blobs { auto request = Azure::Core::Http::Request(Azure::Core::Http::HttpMethod::Put, url, requestBody); request.AddHeader("Content-Length", std::to_string(requestBody->Length())); - request.GetUrl().AppendQuery("comp", "page"); + request.GetUrl().AppendQueryParameter("comp", "page"); request.AddHeader("x-ms-version", c_ApiVersion); if (options.Timeout.HasValue()) { - request.GetUrl().AppendQuery("timeout", std::to_string(options.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + "timeout", std::to_string(options.Timeout.GetValue())); } request.AddHeader( "x-ms-range", @@ -8160,11 +8227,12 @@ namespace Azure { namespace Storage { namespace Blobs { unused(options); auto request = Azure::Core::Http::Request(Azure::Core::Http::HttpMethod::Put, url); request.AddHeader("Content-Length", "0"); - request.GetUrl().AppendQuery("comp", "page"); + request.GetUrl().AppendQueryParameter("comp", "page"); request.AddHeader("x-ms-version", c_ApiVersion); if (options.Timeout.HasValue()) { - request.GetUrl().AppendQuery("timeout", std::to_string(options.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + "timeout", std::to_string(options.Timeout.GetValue())); } request.AddHeader( "x-ms-range", @@ -8322,11 +8390,12 @@ namespace Azure { namespace Storage { namespace Blobs { unused(options); auto request = Azure::Core::Http::Request(Azure::Core::Http::HttpMethod::Put, url); request.AddHeader("Content-Length", "0"); - request.GetUrl().AppendQuery("comp", "page"); + request.GetUrl().AppendQueryParameter("comp", "page"); request.AddHeader("x-ms-version", c_ApiVersion); if (options.Timeout.HasValue()) { - request.GetUrl().AppendQuery("timeout", std::to_string(options.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + "timeout", std::to_string(options.Timeout.GetValue())); } request.AddHeader( "x-ms-range", @@ -8457,11 +8526,12 @@ namespace Azure { namespace Storage { namespace Blobs { unused(options); auto request = Azure::Core::Http::Request(Azure::Core::Http::HttpMethod::Put, url); request.AddHeader("Content-Length", "0"); - request.GetUrl().AppendQuery("comp", "properties"); + request.GetUrl().AppendQueryParameter("comp", "properties"); request.AddHeader("x-ms-version", c_ApiVersion); if (options.Timeout.HasValue()) { - request.GetUrl().AppendQuery("timeout", std::to_string(options.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + "timeout", std::to_string(options.Timeout.GetValue())); } request.AddHeader("x-ms-blob-content-length", std::to_string(options.BlobContentLength)); if (options.LeaseId.HasValue()) @@ -8564,15 +8634,18 @@ namespace Azure { namespace Storage { namespace Blobs { { unused(options); auto request = Azure::Core::Http::Request(Azure::Core::Http::HttpMethod::Get, url); - request.GetUrl().AppendQuery("comp", "pagelist"); + request.GetUrl().AppendQueryParameter("comp", "pagelist"); if (options.PreviousSnapshot.HasValue()) { - request.GetUrl().AppendQuery("prevsnapshot", options.PreviousSnapshot.GetValue()); + request.GetUrl().AppendQueryParameter( + "prevsnapshot", + Details::UrlEncodeQueryParameter(options.PreviousSnapshot.GetValue())); } request.AddHeader("x-ms-version", c_ApiVersion); if (options.Timeout.HasValue()) { - request.GetUrl().AppendQuery("timeout", std::to_string(options.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + "timeout", std::to_string(options.Timeout.GetValue())); } if (options.Range.HasValue()) { @@ -8661,11 +8734,12 @@ namespace Azure { namespace Storage { namespace Blobs { unused(options); auto request = Azure::Core::Http::Request(Azure::Core::Http::HttpMethod::Put, url); request.AddHeader("Content-Length", "0"); - request.GetUrl().AppendQuery("comp", "incrementalcopy"); + request.GetUrl().AppendQueryParameter("comp", "incrementalcopy"); request.AddHeader("x-ms-version", c_ApiVersion); if (options.Timeout.HasValue()) { - request.GetUrl().AppendQuery("timeout", std::to_string(options.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + "timeout", std::to_string(options.Timeout.GetValue())); } request.AddHeader("x-ms-copy-source", options.CopySource); if (options.IfModifiedSince.HasValue()) @@ -8911,7 +8985,8 @@ namespace Azure { namespace Storage { namespace Blobs { request.AddHeader("x-ms-version", c_ApiVersion); if (options.Timeout.HasValue()) { - request.GetUrl().AppendQuery("timeout", std::to_string(options.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + "timeout", std::to_string(options.Timeout.GetValue())); } if (!options.HttpHeaders.ContentType.empty()) { @@ -9064,11 +9139,12 @@ namespace Azure { namespace Storage { namespace Blobs { auto request = Azure::Core::Http::Request(Azure::Core::Http::HttpMethod::Put, url, requestBody); request.AddHeader("Content-Length", std::to_string(requestBody->Length())); - request.GetUrl().AppendQuery("comp", "appendblock"); + request.GetUrl().AppendQueryParameter("comp", "appendblock"); request.AddHeader("x-ms-version", c_ApiVersion); if (options.Timeout.HasValue()) { - request.GetUrl().AppendQuery("timeout", std::to_string(options.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + "timeout", std::to_string(options.Timeout.GetValue())); } if (options.TransactionalContentMd5.HasValue()) { @@ -9210,11 +9286,12 @@ namespace Azure { namespace Storage { namespace Blobs { unused(options); auto request = Azure::Core::Http::Request(Azure::Core::Http::HttpMethod::Put, url); request.AddHeader("Content-Length", "0"); - request.GetUrl().AppendQuery("comp", "appendblock"); + request.GetUrl().AppendQueryParameter("comp", "appendblock"); request.AddHeader("x-ms-version", c_ApiVersion); if (options.Timeout.HasValue()) { - request.GetUrl().AppendQuery("timeout", std::to_string(options.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + "timeout", std::to_string(options.Timeout.GetValue())); } request.AddHeader("x-ms-copy-source", options.SourceUri); if (options.SourceRange.HasValue()) @@ -9364,11 +9441,12 @@ namespace Azure { namespace Storage { namespace Blobs { unused(options); auto request = Azure::Core::Http::Request(Azure::Core::Http::HttpMethod::Put, url); request.AddHeader("Content-Length", "0"); - request.GetUrl().AppendQuery("comp", "seal"); + request.GetUrl().AppendQueryParameter("comp", "seal"); request.AddHeader("x-ms-version", c_ApiVersion); if (options.Timeout.HasValue()) { - request.GetUrl().AppendQuery("timeout", std::to_string(options.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + "timeout", std::to_string(options.Timeout.GetValue())); } if (options.LeaseId.HasValue()) { @@ -9437,11 +9515,12 @@ namespace Azure { namespace Storage { namespace Blobs { auto request = Azure::Core::Http::Request(Azure::Core::Http::HttpMethod::Post, url, requestBody); request.AddHeader("Content-Length", std::to_string(requestBody->Length())); - request.GetUrl().AppendQuery("comp", "batch"); + request.GetUrl().AppendQueryParameter("comp", "batch"); request.AddHeader("x-ms-version", c_ApiVersion); if (options.Timeout.HasValue()) { - request.GetUrl().AppendQuery("timeout", std::to_string(options.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + "timeout", std::to_string(options.Timeout.GetValue())); } request.AddHeader("Content-Type", options.ContentType); auto pHttpResponse = pipeline.Send(context, request); diff --git a/sdk/storage/azure-storage-blobs/src/append_blob_client.cpp b/sdk/storage/azure-storage-blobs/src/append_blob_client.cpp index 90e609a94..fbda00925 100644 --- a/sdk/storage/azure-storage-blobs/src/append_blob_client.cpp +++ b/sdk/storage/azure-storage-blobs/src/append_blob_client.cpp @@ -49,11 +49,12 @@ namespace Azure { namespace Storage { namespace Blobs { AppendBlobClient newClient(*this); if (snapshot.empty()) { - newClient.m_blobUrl.RemoveQuery(Details::c_HttpQuerySnapshot); + newClient.m_blobUrl.RemoveQueryParameter(Details::c_HttpQuerySnapshot); } else { - newClient.m_blobUrl.AppendQuery(Details::c_HttpQuerySnapshot, snapshot); + newClient.m_blobUrl.AppendQueryParameter( + Details::c_HttpQuerySnapshot, Details::UrlEncodeQueryParameter(snapshot)); } return newClient; } @@ -63,11 +64,12 @@ namespace Azure { namespace Storage { namespace Blobs { AppendBlobClient newClient(*this); if (versionId.empty()) { - newClient.m_blobUrl.RemoveQuery(Details::c_HttpQueryVersionId); + newClient.m_blobUrl.RemoveQueryParameter(Details::c_HttpQueryVersionId); } else { - newClient.m_blobUrl.AppendQuery(Details::c_HttpQueryVersionId, versionId); + newClient.m_blobUrl.AppendQueryParameter( + Details::c_HttpQueryVersionId, Details::UrlEncodeQueryParameter(versionId)); } return newClient; } diff --git a/sdk/storage/azure-storage-blobs/src/blob_client.cpp b/sdk/storage/azure-storage-blobs/src/blob_client.cpp index f1c36283a..e390d4e76 100644 --- a/sdk/storage/azure-storage-blobs/src/blob_client.cpp +++ b/sdk/storage/azure-storage-blobs/src/blob_client.cpp @@ -128,11 +128,12 @@ namespace Azure { namespace Storage { namespace Blobs { BlobClient newClient(*this); if (snapshot.empty()) { - newClient.m_blobUrl.RemoveQuery(Details::c_HttpQuerySnapshot); + newClient.m_blobUrl.RemoveQueryParameter(Details::c_HttpQuerySnapshot); } else { - newClient.m_blobUrl.AppendQuery(Details::c_HttpQuerySnapshot, snapshot); + newClient.m_blobUrl.AppendQueryParameter( + Details::c_HttpQuerySnapshot, Details::UrlEncodeQueryParameter(snapshot)); } return newClient; } @@ -142,11 +143,12 @@ namespace Azure { namespace Storage { namespace Blobs { BlobClient newClient(*this); if (versionId.empty()) { - newClient.m_blobUrl.RemoveQuery(Details::c_HttpQueryVersionId); + newClient.m_blobUrl.RemoveQueryParameter(Details::c_HttpQueryVersionId); } else { - newClient.m_blobUrl.AppendQuery(Details::c_HttpQueryVersionId, versionId); + newClient.m_blobUrl.AppendQueryParameter( + Details::c_HttpQueryVersionId, Details::UrlEncodeQueryParameter(versionId)); } return newClient; } diff --git a/sdk/storage/azure-storage-blobs/src/blob_sas_builder.cpp b/sdk/storage/azure-storage-blobs/src/blob_sas_builder.cpp index c5ebc9172..e88afcaa5 100644 --- a/sdk/storage/azure-storage-blobs/src/blob_sas_builder.cpp +++ b/sdk/storage/azure-storage-blobs/src/blob_sas_builder.cpp @@ -138,49 +138,49 @@ namespace Azure { namespace Storage { namespace Blobs { = Base64Encode(Details::HmacSha256(stringToSign, Base64Decode(credential.GetAccountKey()))); Azure::Core::Http::Url builder; - builder.AppendQuery("sv", Version); - builder.AppendQuery("spr", protocol); + builder.AppendQueryParameter("sv", Details::UrlEncodeQueryParameter(Version)); + builder.AppendQueryParameter("spr", Details::UrlEncodeQueryParameter(protocol)); if (StartsOn.HasValue()) { - builder.AppendQuery("st", StartsOn.GetValue()); + builder.AppendQueryParameter("st", Details::UrlEncodeQueryParameter(StartsOn.GetValue())); } if (!ExpiresOn.empty()) { - builder.AppendQuery("se", ExpiresOn); + builder.AppendQueryParameter("se", Details::UrlEncodeQueryParameter(ExpiresOn)); } if (IPRange.HasValue()) { - builder.AppendQuery("sip", IPRange.GetValue()); + builder.AppendQueryParameter("sip", Details::UrlEncodeQueryParameter(IPRange.GetValue())); } if (!Identifier.empty()) { - builder.AppendQuery("si", Identifier); + builder.AppendQueryParameter("si", Details::UrlEncodeQueryParameter(Identifier)); } - builder.AppendQuery("sr", resource); + builder.AppendQueryParameter("sr", Details::UrlEncodeQueryParameter(resource)); if (!Permissions.empty()) { - builder.AppendQuery("sp", Permissions); + builder.AppendQueryParameter("sp", Details::UrlEncodeQueryParameter(Permissions)); } - builder.AppendQuery("sig", signature); + builder.AppendQueryParameter("sig", Details::UrlEncodeQueryParameter(signature)); if (!CacheControl.empty()) { - builder.AppendQuery("rscc", CacheControl); + builder.AppendQueryParameter("rscc", Details::UrlEncodeQueryParameter(CacheControl)); } if (!ContentDisposition.empty()) { - builder.AppendQuery("rscd", ContentDisposition); + builder.AppendQueryParameter("rscd", Details::UrlEncodeQueryParameter(ContentDisposition)); } if (!ContentEncoding.empty()) { - builder.AppendQuery("rsce", ContentEncoding); + builder.AppendQueryParameter("rsce", Details::UrlEncodeQueryParameter(ContentEncoding)); } if (!ContentLanguage.empty()) { - builder.AppendQuery("rscl", ContentLanguage); + builder.AppendQueryParameter("rscl", Details::UrlEncodeQueryParameter(ContentLanguage)); } if (!ContentType.empty()) { - builder.AppendQuery("rsct", ContentType); + builder.AppendQueryParameter("rsct", Details::UrlEncodeQueryParameter(ContentType)); } return builder.GetAbsoluteUrl(); @@ -222,46 +222,52 @@ namespace Azure { namespace Storage { namespace Blobs { = Base64Encode(Details::HmacSha256(stringToSign, Base64Decode(userDelegationKey.Value))); Azure::Core::Http::Url builder; - builder.AppendQuery("sv", Version); - builder.AppendQuery("sr", resource); + builder.AppendQueryParameter("sv", Details::UrlEncodeQueryParameter(Version)); + builder.AppendQueryParameter("sr", Details::UrlEncodeQueryParameter(resource)); if (StartsOn.HasValue()) { - builder.AppendQuery("st", StartsOn.GetValue()); + builder.AppendQueryParameter("st", Details::UrlEncodeQueryParameter(StartsOn.GetValue())); } - builder.AppendQuery("se", ExpiresOn); - builder.AppendQuery("sp", Permissions); + builder.AppendQueryParameter("se", Details::UrlEncodeQueryParameter(ExpiresOn)); + builder.AppendQueryParameter("sp", Details::UrlEncodeQueryParameter(Permissions)); if (IPRange.HasValue()) { - builder.AppendQuery("sip", IPRange.GetValue()); + builder.AppendQueryParameter("sip", Details::UrlEncodeQueryParameter(IPRange.GetValue())); } - builder.AppendQuery("spr", protocol); - builder.AppendQuery("skoid", userDelegationKey.SignedObjectId); - builder.AppendQuery("sktid", userDelegationKey.SignedTenantId); - builder.AppendQuery("skt", userDelegationKey.SignedStartsOn); - builder.AppendQuery("ske", userDelegationKey.SignedExpiresOn); - builder.AppendQuery("sks", userDelegationKey.SignedService); - builder.AppendQuery("skv", userDelegationKey.SignedVersion); + builder.AppendQueryParameter("spr", Details::UrlEncodeQueryParameter(protocol)); + builder.AppendQueryParameter( + "skoid", Details::UrlEncodeQueryParameter(userDelegationKey.SignedObjectId)); + builder.AppendQueryParameter( + "sktid", Details::UrlEncodeQueryParameter(userDelegationKey.SignedTenantId)); + builder.AppendQueryParameter( + "skt", Details::UrlEncodeQueryParameter(userDelegationKey.SignedStartsOn)); + builder.AppendQueryParameter( + "ske", Details::UrlEncodeQueryParameter(userDelegationKey.SignedExpiresOn)); + builder.AppendQueryParameter( + "sks", Details::UrlEncodeQueryParameter(userDelegationKey.SignedService)); + builder.AppendQueryParameter( + "skv", Details::UrlEncodeQueryParameter(userDelegationKey.SignedVersion)); if (!CacheControl.empty()) { - builder.AppendQuery("rscc", CacheControl); + builder.AppendQueryParameter("rscc", Details::UrlEncodeQueryParameter(CacheControl)); } if (!ContentDisposition.empty()) { - builder.AppendQuery("rscd", ContentDisposition); + builder.AppendQueryParameter("rscd", Details::UrlEncodeQueryParameter(ContentDisposition)); } if (!ContentEncoding.empty()) { - builder.AppendQuery("rsce", ContentEncoding); + builder.AppendQueryParameter("rsce", Details::UrlEncodeQueryParameter(ContentEncoding)); } if (!ContentLanguage.empty()) { - builder.AppendQuery("rscl", ContentLanguage); + builder.AppendQueryParameter("rscl", Details::UrlEncodeQueryParameter(ContentLanguage)); } if (!ContentType.empty()) { - builder.AppendQuery("rsct", ContentType); + builder.AppendQueryParameter("rsct", Details::UrlEncodeQueryParameter(ContentType)); } - builder.AppendQuery("sig", signature); + builder.AppendQueryParameter("sig", Details::UrlEncodeQueryParameter(signature)); return builder.GetAbsoluteUrl(); } diff --git a/sdk/storage/azure-storage-blobs/src/block_blob_client.cpp b/sdk/storage/azure-storage-blobs/src/block_blob_client.cpp index b843c614d..13b94516f 100644 --- a/sdk/storage/azure-storage-blobs/src/block_blob_client.cpp +++ b/sdk/storage/azure-storage-blobs/src/block_blob_client.cpp @@ -52,11 +52,12 @@ namespace Azure { namespace Storage { namespace Blobs { BlockBlobClient newClient(*this); if (snapshot.empty()) { - newClient.m_blobUrl.RemoveQuery(Details::c_HttpQuerySnapshot); + newClient.m_blobUrl.RemoveQueryParameter(Details::c_HttpQuerySnapshot); } else { - newClient.m_blobUrl.AppendQuery(Details::c_HttpQuerySnapshot, snapshot); + newClient.m_blobUrl.AppendQueryParameter( + Details::c_HttpQuerySnapshot, Details::UrlEncodeQueryParameter(snapshot)); } return newClient; } @@ -66,11 +67,12 @@ namespace Azure { namespace Storage { namespace Blobs { BlockBlobClient newClient(*this); if (versionId.empty()) { - newClient.m_blobUrl.RemoveQuery(Details::c_HttpQueryVersionId); + newClient.m_blobUrl.RemoveQueryParameter(Details::c_HttpQueryVersionId); } else { - newClient.m_blobUrl.AppendQuery(Details::c_HttpQueryVersionId, versionId); + newClient.m_blobUrl.AppendQueryParameter( + Details::c_HttpQueryVersionId, Details::UrlEncodeQueryParameter(versionId)); } return newClient; } diff --git a/sdk/storage/azure-storage-blobs/src/page_blob_client.cpp b/sdk/storage/azure-storage-blobs/src/page_blob_client.cpp index 1e9f144f6..0b0e6b5fc 100644 --- a/sdk/storage/azure-storage-blobs/src/page_blob_client.cpp +++ b/sdk/storage/azure-storage-blobs/src/page_blob_client.cpp @@ -49,11 +49,12 @@ namespace Azure { namespace Storage { namespace Blobs { PageBlobClient newClient(*this); if (snapshot.empty()) { - newClient.m_blobUrl.RemoveQuery(Details::c_HttpQuerySnapshot); + newClient.m_blobUrl.RemoveQueryParameter(Details::c_HttpQuerySnapshot); } else { - newClient.m_blobUrl.AppendQuery(Details::c_HttpQuerySnapshot, snapshot); + newClient.m_blobUrl.AppendQueryParameter( + Details::c_HttpQuerySnapshot, Details::UrlEncodeQueryParameter(snapshot)); } return newClient; } @@ -63,11 +64,12 @@ namespace Azure { namespace Storage { namespace Blobs { PageBlobClient newClient(*this); if (versionId.empty()) { - newClient.m_blobUrl.RemoveQuery(Details::c_HttpQueryVersionId); + newClient.m_blobUrl.RemoveQueryParameter(Details::c_HttpQueryVersionId); } else { - newClient.m_blobUrl.AppendQuery(Details::c_HttpQueryVersionId, versionId); + newClient.m_blobUrl.AppendQueryParameter( + Details::c_HttpQueryVersionId, Details::UrlEncodeQueryParameter(versionId)); } return newClient; } diff --git a/sdk/storage/azure-storage-blobs/test/blob_sas_test.cpp b/sdk/storage/azure-storage-blobs/test/blob_sas_test.cpp index 2b1d896ae..440610df4 100644 --- a/sdk/storage/azure-storage-blobs/test/blob_sas_test.cpp +++ b/sdk/storage/azure-storage-blobs/test/blob_sas_test.cpp @@ -430,7 +430,7 @@ namespace Azure { namespace Storage { namespace Test { auto verify_blob_snapshot_read = [&](const std::string sas) { Azure::Core::Http::Url blobSnapshotUriWithSas(blobSnapshotUri); - blobSnapshotUriWithSas.AppendQueries(sas); + blobSnapshotUriWithSas.AppendQueryParameters(sas); auto blobSnapshotClient = Blobs::AppendBlobClient(blobSnapshotUriWithSas.GetAbsoluteUrl()); auto downloadedContent = blobSnapshotClient.Download(); EXPECT_TRUE(ReadBodyStream(downloadedContent->BodyStream).empty()); @@ -438,7 +438,7 @@ namespace Azure { namespace Storage { namespace Test { auto verify_blob_snapshot_delete = [&](const std::string sas) { Azure::Core::Http::Url blobSnapshotUriWithSas(blobSnapshotUri); - blobSnapshotUriWithSas.AppendQueries(sas); + blobSnapshotUriWithSas.AppendQueryParameters(sas); auto blobSnapshotClient = Blobs::AppendBlobClient(blobSnapshotUriWithSas.GetAbsoluteUrl()); EXPECT_NO_THROW(blobSnapshotClient.Delete()); }; @@ -485,7 +485,7 @@ namespace Azure { namespace Storage { namespace Test { auto verify_blob_version_read = [&](const std::string sas) { Azure::Core::Http::Url blobVersionUriWithSas(blobVersionUri); - blobVersionUriWithSas.AppendQueries(sas); + blobVersionUriWithSas.AppendQueryParameters(sas); auto blobVersionClient = Blobs::AppendBlobClient(blobVersionUriWithSas.GetAbsoluteUrl()); auto downloadedContent = blobVersionClient.Download(); EXPECT_TRUE(ReadBodyStream(downloadedContent->BodyStream).empty()); @@ -493,7 +493,7 @@ namespace Azure { namespace Storage { namespace Test { auto verify_blob_delete_version = [&](const std::string& sas) { Azure::Core::Http::Url blobVersionUriWithSas(blobVersionUri); - blobVersionUriWithSas.AppendQueries(sas); + blobVersionUriWithSas.AppendQueryParameters(sas); auto blobVersionClient = Blobs::AppendBlobClient(blobVersionUriWithSas.GetAbsoluteUrl()); blobVersionClient.Delete(); }; diff --git a/sdk/storage/azure-storage-blobs/test/page_blob_client_test.cpp b/sdk/storage/azure-storage-blobs/test/page_blob_client_test.cpp index c9a0264a2..a88b87235 100644 --- a/sdk/storage/azure-storage-blobs/test/page_blob_client_test.cpp +++ b/sdk/storage/azure-storage-blobs/test/page_blob_client_test.cpp @@ -146,7 +146,7 @@ namespace Azure { namespace Storage { namespace Test { StandardStorageConnectionString(), m_containerName, RandomString()); std::string snapshot = m_pageBlobClient->CreateSnapshot()->Snapshot; Azure::Core::Http::Url sourceUri(m_pageBlobClient->WithSnapshot(snapshot).GetUri()); - sourceUri.AppendQueries(GetSas()); + sourceUri.AppendQueryParameters(GetSas()); auto copyInfo = pageBlobClient.StartCopyIncremental(sourceUri.GetAbsoluteUrl()); EXPECT_FALSE(copyInfo->ETag.empty()); EXPECT_FALSE(copyInfo->LastModified.empty()); diff --git a/sdk/storage/azure-storage-common/inc/azure/storage/common/crypt.hpp b/sdk/storage/azure-storage-common/inc/azure/storage/common/crypt.hpp index 0079a4085..6ff40ca1b 100644 --- a/sdk/storage/azure-storage-common/inc/azure/storage/common/crypt.hpp +++ b/sdk/storage/azure-storage-common/inc/azure/storage/common/crypt.hpp @@ -63,5 +63,6 @@ namespace Azure { namespace Storage { namespace Details { std::string Sha256(const std::string& text); std::string HmacSha256(const std::string& text, const std::string& key); + std::string UrlEncodeQueryParameter(const std::string& value); } // namespace Details }} // namespace Azure::Storage diff --git a/sdk/storage/azure-storage-common/src/account_sas_builder.cpp b/sdk/storage/azure-storage-common/src/account_sas_builder.cpp index 277645623..e37bdc632 100644 --- a/sdk/storage/azure-storage-common/src/account_sas_builder.cpp +++ b/sdk/storage/azure-storage-common/src/account_sas_builder.cpp @@ -105,21 +105,21 @@ namespace Azure { namespace Storage { = Base64Encode(Details::HmacSha256(stringToSign, Base64Decode(credential.GetAccountKey()))); Azure::Core::Http::Url builder; - builder.AppendQuery("sv", Version); - builder.AppendQuery("ss", services); - builder.AppendQuery("srt", resourceTypes); - builder.AppendQuery("sp", Permissions); + builder.AppendQueryParameter("sv", Details::UrlEncodeQueryParameter(Version)); + builder.AppendQueryParameter("ss", Details::UrlEncodeQueryParameter(services)); + builder.AppendQueryParameter("srt", Details::UrlEncodeQueryParameter(resourceTypes)); + builder.AppendQueryParameter("sp", Details::UrlEncodeQueryParameter(Permissions)); if (StartsOn.HasValue()) { - builder.AppendQuery("st", StartsOn.GetValue()); + builder.AppendQueryParameter("st", Details::UrlEncodeQueryParameter(StartsOn.GetValue())); } - builder.AppendQuery("se", ExpiresOn); + builder.AppendQueryParameter("se", Details::UrlEncodeQueryParameter(ExpiresOn)); if (IPRange.HasValue()) { - builder.AppendQuery("sip", IPRange.GetValue()); + builder.AppendQueryParameter("sip", Details::UrlEncodeQueryParameter(IPRange.GetValue())); } - builder.AppendQuery("spr", protocol); - builder.AppendQuery("sig", signature); + builder.AppendQueryParameter("spr", Details::UrlEncodeQueryParameter(protocol)); + builder.AppendQueryParameter("sig", Details::UrlEncodeQueryParameter(signature)); return builder.GetAbsoluteUrl(); } diff --git a/sdk/storage/azure-storage-common/src/crypt.cpp b/sdk/storage/azure-storage-common/src/crypt.cpp index 871d5c7a9..e50747708 100644 --- a/sdk/storage/azure-storage-common/src/crypt.cpp +++ b/sdk/storage/azure-storage-common/src/crypt.cpp @@ -16,11 +16,59 @@ #endif #include +#include #include "azure/storage/common/storage_common.hpp" namespace Azure { namespace Storage { + namespace Details { + std::string UrlEncodeQueryParameter(const std::string& value) + { + static const char* unreserved + = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~"; + static const char* subdelimiters = "!$&'()*+,;="; + + const static std::vector shouldEncodeTable = []() { + std::string queryCharacters + = std::string(unreserved) + std::string(subdelimiters) + "%/:@?"; + + std::vector ret(256, true); + for (char c : queryCharacters) + { + ret[c] = false; + } + // we also encode % and + + ret['%'] = true; + ret['+'] = true; + // Surprisingly, '=' also needs to be encoded because Azure Storage server side is so + // strict. We are applying this function to query key and value respectively, so this won't + // affect that = used to separate key and query. + ret['='] = true; + return ret; + }(); + + const char* hex = "0123456789ABCDEF"; + + std::string encoded; + for (char c : value) + { + unsigned char uc = c; + if (shouldEncodeTable[uc]) + { + encoded += '%'; + encoded += hex[(uc >> 4) & 0x0f]; + encoded += hex[uc & 0x0f]; + } + else + { + encoded += c; + } + } + return encoded; + } + } // namespace Details + #ifdef _WIN32 namespace Details { diff --git a/sdk/storage/azure-storage-common/src/shared_key_policy.cpp b/sdk/storage/azure-storage-common/src/shared_key_policy.cpp index b9ad8ae33..96bc71412 100644 --- a/sdk/storage/azure-storage-common/src/shared_key_policy.cpp +++ b/sdk/storage/azure-storage-common/src/shared_key_policy.cpp @@ -66,13 +66,14 @@ namespace Azure { namespace Storage { // canonicalized resource string_to_sign += "/" + m_credential->AccountName + "/" + request.GetUrl().GetPath() + "\n"; - for (const auto& query : request.GetUrl().GetQuery()) + for (const auto& query : request.GetUrl().GetQueryParameters()) { std::string key = query.first; std::transform(key.begin(), key.end(), key.begin(), [](char c) { return static_cast(std::tolower(static_cast(c))); }); - ordered_kv.emplace_back(std::make_pair(std::move(key), query.second)); + ordered_kv.emplace_back(std::make_pair( + Azure::Core::Http::Url::Decode(key), Azure::Core::Http::Url::Decode(query.second))); } std::sort(ordered_kv.begin(), ordered_kv.end()); for (const auto& p : ordered_kv) diff --git a/sdk/storage/azure-storage-common/src/storage_credential.cpp b/sdk/storage/azure-storage-common/src/storage_credential.cpp index 9d1196551..16ee8988b 100644 --- a/sdk/storage/azure-storage-common/src/storage_credential.cpp +++ b/sdk/storage/azure-storage-common/src/storage_credential.cpp @@ -96,10 +96,10 @@ namespace Azure { namespace Storage { namespace Details { std::string sas = getWithDefault(connectionStringMap, "SharedAccessSignature"); if (!sas.empty()) { - connectionStringParts.BlobServiceUri.AppendQueries(sas); - connectionStringParts.DataLakeServiceUri.AppendQueries(sas); - connectionStringParts.FileServiceUri.AppendQueries(sas); - connectionStringParts.QueueServiceUri.AppendQueries(sas); + connectionStringParts.BlobServiceUri.AppendQueryParameters(sas); + connectionStringParts.DataLakeServiceUri.AppendQueryParameters(sas); + connectionStringParts.FileServiceUri.AppendQueryParameters(sas); + connectionStringParts.QueueServiceUri.AppendQueryParameters(sas); } return connectionStringParts; diff --git a/sdk/storage/azure-storage-files-datalake/inc/azure/storage/files/datalake/protocol/datalake_rest_client.hpp b/sdk/storage/azure-storage-files-datalake/inc/azure/storage/files/datalake/protocol/datalake_rest_client.hpp index a45bb31ff..c7189da1e 100644 --- a/sdk/storage/azure-storage-files-datalake/inc/azure/storage/files/datalake/protocol/datalake_rest_client.hpp +++ b/sdk/storage/azure-storage-files-datalake/inc/azure/storage/files/datalake/protocol/datalake_rest_client.hpp @@ -8,6 +8,7 @@ #include "azure/core/http/pipeline.hpp" #include "azure/core/nullable.hpp" #include "azure/core/response.hpp" +#include "azure/storage/common/crypt.hpp" #include "azure/storage/common/json.hpp" #include "azure/storage/common/storage_common.hpp" #include "azure/storage/common/storage_error.hpp" @@ -898,22 +899,26 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { const ListFileSystemsOptions& listFileSystemsOptions) { Azure::Core::Http::Request request(Azure::Core::Http::HttpMethod::Get, url); - request.GetUrl().AppendQuery(Details::c_QueryResource, "account"); + request.GetUrl().AppendQueryParameter(Details::c_QueryResource, "account"); if (listFileSystemsOptions.Prefix.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryPrefix, listFileSystemsOptions.Prefix.GetValue()); + request.GetUrl().AppendQueryParameter( + Details::c_QueryPrefix, + Storage::Details::UrlEncodeQueryParameter(listFileSystemsOptions.Prefix.GetValue())); } if (listFileSystemsOptions.Continuation.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryContinuation, listFileSystemsOptions.Continuation.GetValue()); + request.GetUrl().AppendQueryParameter( + Details::c_QueryContinuation, + Storage::Details::UrlEncodeQueryParameter( + listFileSystemsOptions.Continuation.GetValue())); } if (listFileSystemsOptions.MaxResults.HasValue()) { - request.GetUrl().AppendQuery( + request.GetUrl().AppendQueryParameter( Details::c_QueryMaxResults, - std::to_string(listFileSystemsOptions.MaxResults.GetValue())); + Storage::Details::UrlEncodeQueryParameter( + std::to_string(listFileSystemsOptions.MaxResults.GetValue()))); } if (listFileSystemsOptions.ClientRequestId.HasValue()) { @@ -922,8 +927,10 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { } if (listFileSystemsOptions.Timeout.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryTimeout, std::to_string(listFileSystemsOptions.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + Details::c_QueryTimeout, + Storage::Details::UrlEncodeQueryParameter( + std::to_string(listFileSystemsOptions.Timeout.GetValue()))); } request.AddHeader( Details::c_HeaderApiVersionParameter, listFileSystemsOptions.ApiVersionParameter); @@ -995,7 +1002,9 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { { Azure::Core::Http::Request request(Azure::Core::Http::HttpMethod::Put, url); request.AddHeader(Details::c_HeaderContentLength, "0"); - request.GetUrl().AppendQuery(Details::c_QueryFileSystemResource, "filesystem"); + request.GetUrl().AppendQueryParameter( + Details::c_QueryFileSystemResource, + Storage::Details::UrlEncodeQueryParameter("filesystem")); if (createOptions.ClientRequestId.HasValue()) { request.AddHeader( @@ -1003,8 +1012,10 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { } if (createOptions.Timeout.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryTimeout, std::to_string(createOptions.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + Details::c_QueryTimeout, + Storage::Details::UrlEncodeQueryParameter( + std::to_string(createOptions.Timeout.GetValue()))); } request.AddHeader(Details::c_HeaderApiVersionParameter, createOptions.ApiVersionParameter); if (createOptions.Properties.HasValue()) @@ -1052,7 +1063,9 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { const SetPropertiesOptions& setPropertiesOptions) { Azure::Core::Http::Request request(Azure::Core::Http::HttpMethod::Patch, url); - request.GetUrl().AppendQuery(Details::c_QueryFileSystemResource, "filesystem"); + request.GetUrl().AppendQueryParameter( + Details::c_QueryFileSystemResource, + Storage::Details::UrlEncodeQueryParameter("filesystem")); if (setPropertiesOptions.ClientRequestId.HasValue()) { request.AddHeader( @@ -1060,8 +1073,10 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { } if (setPropertiesOptions.Timeout.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryTimeout, std::to_string(setPropertiesOptions.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + Details::c_QueryTimeout, + Storage::Details::UrlEncodeQueryParameter( + std::to_string(setPropertiesOptions.Timeout.GetValue()))); } request.AddHeader( Details::c_HeaderApiVersionParameter, setPropertiesOptions.ApiVersionParameter); @@ -1106,7 +1121,9 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { const GetPropertiesOptions& getPropertiesOptions) { Azure::Core::Http::Request request(Azure::Core::Http::HttpMethod::Head, url); - request.GetUrl().AppendQuery(Details::c_QueryFileSystemResource, "filesystem"); + request.GetUrl().AppendQueryParameter( + Details::c_QueryFileSystemResource, + Storage::Details::UrlEncodeQueryParameter("filesystem")); if (getPropertiesOptions.ClientRequestId.HasValue()) { request.AddHeader( @@ -1114,8 +1131,10 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { } if (getPropertiesOptions.Timeout.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryTimeout, std::to_string(getPropertiesOptions.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + Details::c_QueryTimeout, + Storage::Details::UrlEncodeQueryParameter( + std::to_string(getPropertiesOptions.Timeout.GetValue()))); } request.AddHeader( Details::c_HeaderApiVersionParameter, getPropertiesOptions.ApiVersionParameter); @@ -1150,7 +1169,9 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { const DeleteOptions& deleteOptions) { Azure::Core::Http::Request request(Azure::Core::Http::HttpMethod::Delete, url); - request.GetUrl().AppendQuery(Details::c_QueryFileSystemResource, "filesystem"); + request.GetUrl().AppendQueryParameter( + Details::c_QueryFileSystemResource, + Storage::Details::UrlEncodeQueryParameter("filesystem")); if (deleteOptions.ClientRequestId.HasValue()) { request.AddHeader( @@ -1158,8 +1179,10 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { } if (deleteOptions.Timeout.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryTimeout, std::to_string(deleteOptions.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + Details::c_QueryTimeout, + Storage::Details::UrlEncodeQueryParameter( + std::to_string(deleteOptions.Timeout.GetValue()))); } request.AddHeader(Details::c_HeaderApiVersionParameter, deleteOptions.ApiVersionParameter); if (deleteOptions.IfModifiedSince.HasValue()) @@ -1220,7 +1243,9 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { const ListPathsOptions& listPathsOptions) { Azure::Core::Http::Request request(Azure::Core::Http::HttpMethod::Get, url); - request.GetUrl().AppendQuery(Details::c_QueryFileSystemResource, "filesystem"); + request.GetUrl().AppendQueryParameter( + Details::c_QueryFileSystemResource, + Storage::Details::UrlEncodeQueryParameter("filesystem")); if (listPathsOptions.ClientRequestId.HasValue()) { request.AddHeader( @@ -1228,33 +1253,42 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { } if (listPathsOptions.Timeout.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryTimeout, std::to_string(listPathsOptions.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + Details::c_QueryTimeout, + Storage::Details::UrlEncodeQueryParameter( + std::to_string(listPathsOptions.Timeout.GetValue()))); } request.AddHeader( Details::c_HeaderApiVersionParameter, listPathsOptions.ApiVersionParameter); if (listPathsOptions.Continuation.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryContinuation, listPathsOptions.Continuation.GetValue()); + request.GetUrl().AppendQueryParameter( + Details::c_QueryContinuation, + Storage::Details::UrlEncodeQueryParameter(listPathsOptions.Continuation.GetValue())); } if (listPathsOptions.Directory.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryDirectory, listPathsOptions.Directory.GetValue()); + request.GetUrl().AppendQueryParameter( + Details::c_QueryDirectory, + Storage::Details::UrlEncodeQueryParameter(listPathsOptions.Directory.GetValue())); } - request.GetUrl().AppendQuery( + request.GetUrl().AppendQueryParameter( Details::c_QueryRecursiveRequired, - (listPathsOptions.RecursiveRequired ? "true" : "false")); + Storage::Details::UrlEncodeQueryParameter( + (listPathsOptions.RecursiveRequired ? "true" : "false"))); if (listPathsOptions.MaxResults.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryMaxResults, std::to_string(listPathsOptions.MaxResults.GetValue())); + request.GetUrl().AppendQueryParameter( + Details::c_QueryMaxResults, + Storage::Details::UrlEncodeQueryParameter( + std::to_string(listPathsOptions.MaxResults.GetValue()))); } if (listPathsOptions.Upn.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryUpn, (listPathsOptions.Upn.GetValue() ? "true" : "false")); + request.GetUrl().AppendQueryParameter( + Details::c_QueryUpn, + Storage::Details::UrlEncodeQueryParameter( + (listPathsOptions.Upn.GetValue() ? "true" : "false"))); } return ListPathsParseResult(context, pipeline.Send(context, request)); } @@ -1502,26 +1536,31 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { } if (createOptions.Timeout.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryTimeout, std::to_string(createOptions.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + Details::c_QueryTimeout, + Storage::Details::UrlEncodeQueryParameter( + std::to_string(createOptions.Timeout.GetValue()))); } request.AddHeader(Details::c_HeaderApiVersionParameter, createOptions.ApiVersionParameter); if (createOptions.Resource.HasValue()) { - request.GetUrl().AppendQuery( + request.GetUrl().AppendQueryParameter( Details::c_QueryPathResourceType, - PathResourceTypeToString(createOptions.Resource.GetValue())); + Storage::Details::UrlEncodeQueryParameter( + PathResourceTypeToString(createOptions.Resource.GetValue()))); } if (createOptions.Continuation.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryContinuation, createOptions.Continuation.GetValue()); + request.GetUrl().AppendQueryParameter( + Details::c_QueryContinuation, + Storage::Details::UrlEncodeQueryParameter(createOptions.Continuation.GetValue())); } if (createOptions.Mode.HasValue()) { - request.GetUrl().AppendQuery( + request.GetUrl().AppendQueryParameter( Details::c_QueryPathRenameMode, - PathRenameModeToString(createOptions.Mode.GetValue())); + Storage::Details::UrlEncodeQueryParameter( + PathRenameModeToString(createOptions.Mode.GetValue()))); } if (createOptions.CacheControl.HasValue()) { @@ -1766,45 +1805,60 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { } if (updateOptions.Timeout.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryTimeout, std::to_string(updateOptions.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + Details::c_QueryTimeout, + Storage::Details::UrlEncodeQueryParameter( + std::to_string(updateOptions.Timeout.GetValue()))); } request.AddHeader(Details::c_HeaderApiVersionParameter, updateOptions.ApiVersionParameter); - request.GetUrl().AppendQuery( - Details::c_QueryPathUpdateAction, PathUpdateActionToString(updateOptions.Action)); + request.GetUrl().AppendQueryParameter( + Details::c_QueryPathUpdateAction, + Storage::Details::UrlEncodeQueryParameter( + PathUpdateActionToString(updateOptions.Action))); if (updateOptions.MaxRecords.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryMaxRecords, std::to_string(updateOptions.MaxRecords.GetValue())); + request.GetUrl().AppendQueryParameter( + Details::c_QueryMaxRecords, + Storage::Details::UrlEncodeQueryParameter( + std::to_string(updateOptions.MaxRecords.GetValue()))); } if (updateOptions.Continuation.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryContinuation, updateOptions.Continuation.GetValue()); + request.GetUrl().AppendQueryParameter( + Details::c_QueryContinuation, + Storage::Details::UrlEncodeQueryParameter(updateOptions.Continuation.GetValue())); } - request.GetUrl().AppendQuery( + request.GetUrl().AppendQueryParameter( Details::c_QueryPathSetAccessControlRecursiveMode, - PathSetAccessControlRecursiveModeToString(updateOptions.Mode)); + Storage::Details::UrlEncodeQueryParameter( + PathSetAccessControlRecursiveModeToString(updateOptions.Mode))); if (updateOptions.ForceFlag.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryForceFlag, (updateOptions.ForceFlag.GetValue() ? "true" : "false")); + request.GetUrl().AppendQueryParameter( + Details::c_QueryForceFlag, + Storage::Details::UrlEncodeQueryParameter( + (updateOptions.ForceFlag.GetValue() ? "true" : "false"))); } if (updateOptions.Position.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryPosition, std::to_string(updateOptions.Position.GetValue())); + request.GetUrl().AppendQueryParameter( + Details::c_QueryPosition, + Storage::Details::UrlEncodeQueryParameter( + std::to_string(updateOptions.Position.GetValue()))); } if (updateOptions.RetainUncommittedData.HasValue()) { - request.GetUrl().AppendQuery( + request.GetUrl().AppendQueryParameter( Details::c_QueryRetainUncommittedData, - (updateOptions.RetainUncommittedData.GetValue() ? "true" : "false")); + Storage::Details::UrlEncodeQueryParameter( + (updateOptions.RetainUncommittedData.GetValue() ? "true" : "false"))); } if (updateOptions.Close.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryClose, (updateOptions.Close.GetValue() ? "true" : "false")); + request.GetUrl().AppendQueryParameter( + Details::c_QueryClose, + Storage::Details::UrlEncodeQueryParameter( + (updateOptions.Close.GetValue() ? "true" : "false"))); } if (updateOptions.ContentLength.HasValue()) { @@ -1955,8 +2009,10 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { } if (leaseOptions.Timeout.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryTimeout, std::to_string(leaseOptions.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + Details::c_QueryTimeout, + Storage::Details::UrlEncodeQueryParameter( + std::to_string(leaseOptions.Timeout.GetValue()))); } request.AddHeader(Details::c_HeaderApiVersionParameter, leaseOptions.ApiVersionParameter); request.AddHeader( @@ -2058,8 +2114,10 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { } if (readOptions.Timeout.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryTimeout, std::to_string(readOptions.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + Details::c_QueryTimeout, + Storage::Details::UrlEncodeQueryParameter( + std::to_string(readOptions.Timeout.GetValue()))); } request.AddHeader(Details::c_HeaderApiVersionParameter, readOptions.ApiVersionParameter); if (readOptions.Range.HasValue()) @@ -2153,21 +2211,26 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { } if (getPropertiesOptions.Timeout.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryTimeout, std::to_string(getPropertiesOptions.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + Details::c_QueryTimeout, + Storage::Details::UrlEncodeQueryParameter( + std::to_string(getPropertiesOptions.Timeout.GetValue()))); } request.AddHeader( Details::c_HeaderApiVersionParameter, getPropertiesOptions.ApiVersionParameter); if (getPropertiesOptions.Action.HasValue()) { - request.GetUrl().AppendQuery( + request.GetUrl().AppendQueryParameter( Details::c_QueryPathGetPropertiesAction, - PathGetPropertiesActionToString(getPropertiesOptions.Action.GetValue())); + Storage::Details::UrlEncodeQueryParameter( + PathGetPropertiesActionToString(getPropertiesOptions.Action.GetValue()))); } if (getPropertiesOptions.Upn.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryUpn, (getPropertiesOptions.Upn.GetValue() ? "true" : "false")); + request.GetUrl().AppendQueryParameter( + Details::c_QueryUpn, + Storage::Details::UrlEncodeQueryParameter( + (getPropertiesOptions.Upn.GetValue() ? "true" : "false"))); } if (getPropertiesOptions.LeaseIdOptional.HasValue()) { @@ -2247,20 +2310,24 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { } if (deleteOptions.Timeout.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryTimeout, std::to_string(deleteOptions.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + Details::c_QueryTimeout, + Storage::Details::UrlEncodeQueryParameter( + std::to_string(deleteOptions.Timeout.GetValue()))); } request.AddHeader(Details::c_HeaderApiVersionParameter, deleteOptions.ApiVersionParameter); if (deleteOptions.RecursiveOptional.HasValue()) { - request.GetUrl().AppendQuery( + request.GetUrl().AppendQueryParameter( Details::c_QueryRecursiveOptional, - (deleteOptions.RecursiveOptional.GetValue() ? "true" : "false")); + Storage::Details::UrlEncodeQueryParameter( + (deleteOptions.RecursiveOptional.GetValue() ? "true" : "false"))); } if (deleteOptions.Continuation.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryContinuation, deleteOptions.Continuation.GetValue()); + request.GetUrl().AppendQueryParameter( + Details::c_QueryContinuation, + Storage::Details::UrlEncodeQueryParameter(deleteOptions.Continuation.GetValue())); } if (deleteOptions.LeaseIdOptional.HasValue()) { @@ -2337,11 +2404,13 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { const SetAccessControlOptions& setAccessControlOptions) { Azure::Core::Http::Request request(Azure::Core::Http::HttpMethod::Patch, url); - request.GetUrl().AppendQuery(Details::c_QueryAction, "setAccessControl"); + request.GetUrl().AppendQueryParameter(Details::c_QueryAction, "setAccessControl"); if (setAccessControlOptions.Timeout.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryTimeout, std::to_string(setAccessControlOptions.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + Details::c_QueryTimeout, + Storage::Details::UrlEncodeQueryParameter( + std::to_string(setAccessControlOptions.Timeout.GetValue()))); } if (setAccessControlOptions.LeaseIdOptional.HasValue()) { @@ -2445,33 +2514,38 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { const SetAccessControlRecursiveOptions& setAccessControlRecursiveOptions) { Azure::Core::Http::Request request(Azure::Core::Http::HttpMethod::Patch, url); - request.GetUrl().AppendQuery(Details::c_QueryAction, "setAccessControlRecursive"); + request.GetUrl().AppendQueryParameter(Details::c_QueryAction, "setAccessControlRecursive"); if (setAccessControlRecursiveOptions.Timeout.HasValue()) { - request.GetUrl().AppendQuery( + request.GetUrl().AppendQueryParameter( Details::c_QueryTimeout, - std::to_string(setAccessControlRecursiveOptions.Timeout.GetValue())); + Storage::Details::UrlEncodeQueryParameter( + std::to_string(setAccessControlRecursiveOptions.Timeout.GetValue()))); } if (setAccessControlRecursiveOptions.Continuation.HasValue()) { - request.GetUrl().AppendQuery( + request.GetUrl().AppendQueryParameter( Details::c_QueryContinuation, - setAccessControlRecursiveOptions.Continuation.GetValue()); + Storage::Details::UrlEncodeQueryParameter( + setAccessControlRecursiveOptions.Continuation.GetValue())); } - request.GetUrl().AppendQuery( + request.GetUrl().AppendQueryParameter( Details::c_QueryPathSetAccessControlRecursiveMode, - PathSetAccessControlRecursiveModeToString(setAccessControlRecursiveOptions.Mode)); + Storage::Details::UrlEncodeQueryParameter( + PathSetAccessControlRecursiveModeToString(setAccessControlRecursiveOptions.Mode))); if (setAccessControlRecursiveOptions.ForceFlag.HasValue()) { - request.GetUrl().AppendQuery( + request.GetUrl().AppendQueryParameter( Details::c_QueryForceFlag, - (setAccessControlRecursiveOptions.ForceFlag.GetValue() ? "true" : "false")); + Storage::Details::UrlEncodeQueryParameter( + (setAccessControlRecursiveOptions.ForceFlag.GetValue() ? "true" : "false"))); } if (setAccessControlRecursiveOptions.MaxRecords.HasValue()) { - request.GetUrl().AppendQuery( + request.GetUrl().AppendQueryParameter( Details::c_QueryMaxRecords, - std::to_string(setAccessControlRecursiveOptions.MaxRecords.GetValue())); + Storage::Details::UrlEncodeQueryParameter( + std::to_string(setAccessControlRecursiveOptions.MaxRecords.GetValue()))); } if (setAccessControlRecursiveOptions.Acl.HasValue()) { @@ -2575,27 +2649,34 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { const FlushDataOptions& flushDataOptions) { Azure::Core::Http::Request request(Azure::Core::Http::HttpMethod::Patch, url); - request.GetUrl().AppendQuery(Details::c_QueryAction, "flush"); + request.GetUrl().AppendQueryParameter(Details::c_QueryAction, "flush"); if (flushDataOptions.Timeout.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryTimeout, std::to_string(flushDataOptions.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + Details::c_QueryTimeout, + Storage::Details::UrlEncodeQueryParameter( + std::to_string(flushDataOptions.Timeout.GetValue()))); } if (flushDataOptions.Position.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryPosition, std::to_string(flushDataOptions.Position.GetValue())); + request.GetUrl().AppendQueryParameter( + Details::c_QueryPosition, + Storage::Details::UrlEncodeQueryParameter( + std::to_string(flushDataOptions.Position.GetValue()))); } if (flushDataOptions.RetainUncommittedData.HasValue()) { - request.GetUrl().AppendQuery( + request.GetUrl().AppendQueryParameter( Details::c_QueryRetainUncommittedData, - (flushDataOptions.RetainUncommittedData.GetValue() ? "true" : "false")); + Storage::Details::UrlEncodeQueryParameter( + (flushDataOptions.RetainUncommittedData.GetValue() ? "true" : "false"))); } if (flushDataOptions.Close.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryClose, (flushDataOptions.Close.GetValue() ? "true" : "false")); + request.GetUrl().AppendQueryParameter( + Details::c_QueryClose, + Storage::Details::UrlEncodeQueryParameter( + (flushDataOptions.Close.GetValue() ? "true" : "false"))); } if (flushDataOptions.ContentLength.HasValue()) { @@ -2710,16 +2791,20 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { { Azure::Core::Http::Request request( Azure::Core::Http::HttpMethod::Patch, std::move(url), &bodyStream); - request.GetUrl().AppendQuery(Details::c_QueryAction, "append"); + request.GetUrl().AppendQueryParameter(Details::c_QueryAction, "append"); if (appendDataOptions.Position.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryPosition, std::to_string(appendDataOptions.Position.GetValue())); + request.GetUrl().AppendQueryParameter( + Details::c_QueryPosition, + Storage::Details::UrlEncodeQueryParameter( + std::to_string(appendDataOptions.Position.GetValue()))); } if (appendDataOptions.Timeout.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryTimeout, std::to_string(appendDataOptions.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + Details::c_QueryTimeout, + Storage::Details::UrlEncodeQueryParameter( + std::to_string(appendDataOptions.Timeout.GetValue()))); } if (appendDataOptions.ContentLength.HasValue()) { @@ -2778,11 +2863,13 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { { Azure::Core::Http::Request request(Azure::Core::Http::HttpMethod::Put, url); request.AddHeader(Details::c_HeaderContentLength, "0"); - request.GetUrl().AppendQuery(Details::c_QueryComp, "expiry"); + request.GetUrl().AppendQueryParameter(Details::c_QueryComp, "expiry"); if (setExpiryOptions.Timeout.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryTimeout, std::to_string(setExpiryOptions.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + Details::c_QueryTimeout, + Storage::Details::UrlEncodeQueryParameter( + std::to_string(setExpiryOptions.Timeout.GetValue()))); } request.AddHeader( Details::c_HeaderApiVersionParameter, setExpiryOptions.ApiVersionParameter); diff --git a/sdk/storage/azure-storage-files-datalake/src/datalake_sas_builder.cpp b/sdk/storage/azure-storage-files-datalake/src/datalake_sas_builder.cpp index e0030a116..5b750fb6f 100644 --- a/sdk/storage/azure-storage-files-datalake/src/datalake_sas_builder.cpp +++ b/sdk/storage/azure-storage-files-datalake/src/datalake_sas_builder.cpp @@ -133,49 +133,54 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { Storage::Details::HmacSha256(stringToSign, Base64Decode(credential.GetAccountKey()))); Azure::Core::Http::Url builder; - builder.AppendQuery("sv", Version); - builder.AppendQuery("spr", protocol); + builder.AppendQueryParameter("sv", Storage::Details::UrlEncodeQueryParameter(Version)); + builder.AppendQueryParameter("spr", Storage::Details::UrlEncodeQueryParameter(protocol)); if (StartsOn.HasValue()) { - builder.AppendQuery("st", StartsOn.GetValue()); + builder.AppendQueryParameter( + "st", Storage::Details::UrlEncodeQueryParameter(StartsOn.GetValue())); } if (!ExpiresOn.empty()) { - builder.AppendQuery("se", ExpiresOn); + builder.AppendQueryParameter("se", Storage::Details::UrlEncodeQueryParameter(ExpiresOn)); } if (IPRange.HasValue()) { - builder.AppendQuery("sip", IPRange.GetValue()); + builder.AppendQueryParameter( + "sip", Storage::Details::UrlEncodeQueryParameter(IPRange.GetValue())); } if (!Identifier.empty()) { - builder.AppendQuery("si", Identifier); + builder.AppendQueryParameter("si", Storage::Details::UrlEncodeQueryParameter(Identifier)); } - builder.AppendQuery("sr", resource); + builder.AppendQueryParameter("sr", Storage::Details::UrlEncodeQueryParameter(resource)); if (!Permissions.empty()) { - builder.AppendQuery("sp", Permissions); + builder.AppendQueryParameter("sp", Storage::Details::UrlEncodeQueryParameter(Permissions)); } - builder.AppendQuery("sig", signature); + builder.AppendQueryParameter("sig", Storage::Details::UrlEncodeQueryParameter(signature)); if (!CacheControl.empty()) { - builder.AppendQuery("rscc", CacheControl); + builder.AppendQueryParameter("rscc", Storage::Details::UrlEncodeQueryParameter(CacheControl)); } if (!ContentDisposition.empty()) { - builder.AppendQuery("rscd", ContentDisposition); + builder.AppendQueryParameter( + "rscd", Storage::Details::UrlEncodeQueryParameter(ContentDisposition)); } if (!ContentEncoding.empty()) { - builder.AppendQuery("rsce", ContentEncoding); + builder.AppendQueryParameter( + "rsce", Storage::Details::UrlEncodeQueryParameter(ContentEncoding)); } if (!ContentLanguage.empty()) { - builder.AppendQuery("rscl", ContentLanguage); + builder.AppendQueryParameter( + "rscl", Storage::Details::UrlEncodeQueryParameter(ContentLanguage)); } if (!ContentType.empty()) { - builder.AppendQuery("rsct", ContentType); + builder.AppendQueryParameter("rsct", Storage::Details::UrlEncodeQueryParameter(ContentType)); } return builder.GetAbsoluteUrl(); @@ -206,62 +211,78 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { Storage::Details::HmacSha256(stringToSign, Base64Decode(userDelegationKey.Value))); Azure::Core::Http::Url builder; - builder.AppendQuery("sv", Version); - builder.AppendQuery("sr", resource); + builder.AppendQueryParameter("sv", Storage::Details::UrlEncodeQueryParameter(Version)); + builder.AppendQueryParameter("sr", Storage::Details::UrlEncodeQueryParameter(resource)); if (StartsOn.HasValue()) { - builder.AppendQuery("st", StartsOn.GetValue()); + builder.AppendQueryParameter( + "st", Storage::Details::UrlEncodeQueryParameter(StartsOn.GetValue())); } - builder.AppendQuery("se", ExpiresOn); - builder.AppendQuery("sp", Permissions); + builder.AppendQueryParameter("se", Storage::Details::UrlEncodeQueryParameter(ExpiresOn)); + builder.AppendQueryParameter("sp", Permissions); if (IPRange.HasValue()) { - builder.AppendQuery("sip", IPRange.GetValue()); + builder.AppendQueryParameter( + "sip", Storage::Details::UrlEncodeQueryParameter(IPRange.GetValue())); } - builder.AppendQuery("spr", protocol); - builder.AppendQuery("skoid", userDelegationKey.SignedObjectId); - builder.AppendQuery("sktid", userDelegationKey.SignedTenantId); - builder.AppendQuery("skt", userDelegationKey.SignedStartsOn); - builder.AppendQuery("ske", userDelegationKey.SignedExpiresOn); - builder.AppendQuery("sks", userDelegationKey.SignedService); - builder.AppendQuery("skv", userDelegationKey.SignedVersion); + builder.AppendQueryParameter("spr", Storage::Details::UrlEncodeQueryParameter(protocol)); + builder.AppendQueryParameter( + "skoid", Storage::Details::UrlEncodeQueryParameter(userDelegationKey.SignedObjectId)); + builder.AppendQueryParameter( + "sktid", Storage::Details::UrlEncodeQueryParameter(userDelegationKey.SignedTenantId)); + builder.AppendQueryParameter( + "skt", Storage::Details::UrlEncodeQueryParameter(userDelegationKey.SignedStartsOn)); + builder.AppendQueryParameter( + "ske", Storage::Details::UrlEncodeQueryParameter(userDelegationKey.SignedExpiresOn)); + builder.AppendQueryParameter( + "sks", Storage::Details::UrlEncodeQueryParameter(userDelegationKey.SignedService)); + builder.AppendQueryParameter( + "skv", Storage::Details::UrlEncodeQueryParameter(userDelegationKey.SignedVersion)); if (!PreauthorizedAgentObjectId.empty()) { - builder.AppendQuery("saoid", PreauthorizedAgentObjectId); + builder.AppendQueryParameter( + "saoid", Storage::Details::UrlEncodeQueryParameter(PreauthorizedAgentObjectId)); } if (!AgentObjectId.empty()) { - builder.AppendQuery("suoid", AgentObjectId); + builder.AppendQueryParameter( + "suoid", Storage::Details::UrlEncodeQueryParameter(AgentObjectId)); } if (!CorrelationId.empty()) { - builder.AppendQuery("scid", CorrelationId); + builder.AppendQueryParameter( + "scid", Storage::Details::UrlEncodeQueryParameter(CorrelationId)); } if (DirectoryDepth.HasValue()) { - builder.AppendQuery("sdd", std::to_string(DirectoryDepth.GetValue())); + builder.AppendQueryParameter( + "sdd", + Storage::Details::UrlEncodeQueryParameter(std::to_string(DirectoryDepth.GetValue()))); } if (!CacheControl.empty()) { - builder.AppendQuery("rscc", CacheControl); + builder.AppendQueryParameter("rscc", Storage::Details::UrlEncodeQueryParameter(CacheControl)); } if (!ContentDisposition.empty()) { - builder.AppendQuery("rscd", ContentDisposition); + builder.AppendQueryParameter( + "rscd", Storage::Details::UrlEncodeQueryParameter(ContentDisposition)); } if (!ContentEncoding.empty()) { - builder.AppendQuery("rsce", ContentEncoding); + builder.AppendQueryParameter( + "rsce", Storage::Details::UrlEncodeQueryParameter(ContentEncoding)); } if (!ContentLanguage.empty()) { - builder.AppendQuery("rscl", ContentLanguage); + builder.AppendQueryParameter( + "rscl", Storage::Details::UrlEncodeQueryParameter(ContentLanguage)); } if (!ContentType.empty()) { - builder.AppendQuery("rsct", ContentType); + builder.AppendQueryParameter("rsct", Storage::Details::UrlEncodeQueryParameter(ContentType)); } - builder.AppendQuery("sig", signature); + builder.AppendQueryParameter("sig", Storage::Details::UrlEncodeQueryParameter(signature)); return builder.GetAbsoluteUrl(); } diff --git a/sdk/storage/azure-storage-files-shares/inc/azure/storage/files/shares/protocol/share_rest_client.hpp b/sdk/storage/azure-storage-files-shares/inc/azure/storage/files/shares/protocol/share_rest_client.hpp index 8085266c5..65903c1b6 100644 --- a/sdk/storage/azure-storage-files-shares/inc/azure/storage/files/shares/protocol/share_rest_client.hpp +++ b/sdk/storage/azure-storage-files-shares/inc/azure/storage/files/shares/protocol/share_rest_client.hpp @@ -8,6 +8,7 @@ #include "azure/core/http/pipeline.hpp" #include "azure/core/nullable.hpp" #include "azure/core/response.hpp" +#include "azure/storage/common/crypt.hpp" #include "azure/storage/common/json.hpp" #include "azure/storage/common/storage_common.hpp" #include "azure/storage/common/storage_error.hpp" @@ -1210,12 +1211,14 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { reinterpret_cast(xml_body.data()), xml_body.length()); auto request = Azure::Core::Http::Request(Azure::Core::Http::HttpMethod::Put, url, &body); request.AddHeader("Content-Length", std::to_string(body.Length())); - request.GetUrl().AppendQuery(Details::c_QueryRestype, "service"); - request.GetUrl().AppendQuery(Details::c_QueryComp, "properties"); + request.GetUrl().AppendQueryParameter(Details::c_QueryRestype, "service"); + request.GetUrl().AppendQueryParameter(Details::c_QueryComp, "properties"); if (setPropertiesOptions.Timeout.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryTimeout, std::to_string(setPropertiesOptions.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + Details::c_QueryTimeout, + Storage::Details::UrlEncodeQueryParameter( + std::to_string(setPropertiesOptions.Timeout.GetValue()))); } request.AddHeader(Details::c_HeaderVersion, setPropertiesOptions.ApiVersionParameter); return SetPropertiesParseResult(context, pipeline.Send(context, request)); @@ -1239,12 +1242,14 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { const GetPropertiesOptions& getPropertiesOptions) { Azure::Core::Http::Request request(Azure::Core::Http::HttpMethod::Get, url); - request.GetUrl().AppendQuery(Details::c_QueryRestype, "service"); - request.GetUrl().AppendQuery(Details::c_QueryComp, "properties"); + request.GetUrl().AppendQueryParameter(Details::c_QueryRestype, "service"); + request.GetUrl().AppendQueryParameter(Details::c_QueryComp, "properties"); if (getPropertiesOptions.Timeout.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryTimeout, std::to_string(getPropertiesOptions.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + Details::c_QueryTimeout, + Storage::Details::UrlEncodeQueryParameter( + std::to_string(getPropertiesOptions.Timeout.GetValue()))); } request.AddHeader(Details::c_HeaderVersion, getPropertiesOptions.ApiVersionParameter); return GetPropertiesParseResult(context, pipeline.Send(context, request)); @@ -1283,33 +1288,41 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { const ListSharesSegmentOptions& listSharesSegmentOptions) { Azure::Core::Http::Request request(Azure::Core::Http::HttpMethod::Get, url); - request.GetUrl().AppendQuery(Details::c_QueryComp, "list"); + request.GetUrl().AppendQueryParameter(Details::c_QueryComp, "list"); if (listSharesSegmentOptions.Prefix.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryPrefix, listSharesSegmentOptions.Prefix.GetValue()); + request.GetUrl().AppendQueryParameter( + Details::c_QueryPrefix, + Storage::Details::UrlEncodeQueryParameter( + listSharesSegmentOptions.Prefix.GetValue())); } if (listSharesSegmentOptions.Marker.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryMarker, listSharesSegmentOptions.Marker.GetValue()); + request.GetUrl().AppendQueryParameter( + Details::c_QueryMarker, + Storage::Details::UrlEncodeQueryParameter( + listSharesSegmentOptions.Marker.GetValue())); } if (listSharesSegmentOptions.MaxResults.HasValue()) { - request.GetUrl().AppendQuery( + request.GetUrl().AppendQueryParameter( Details::c_QueryMaxResults, - std::to_string(listSharesSegmentOptions.MaxResults.GetValue())); + Storage::Details::UrlEncodeQueryParameter( + std::to_string(listSharesSegmentOptions.MaxResults.GetValue()))); } if (listSharesSegmentOptions.ListSharesInclude.HasValue()) { - request.GetUrl().AppendQuery( + request.GetUrl().AppendQueryParameter( Details::c_QueryListSharesInclude, - ListSharesIncludeTypeToString(listSharesSegmentOptions.ListSharesInclude.GetValue())); + Storage::Details::UrlEncodeQueryParameter(ListSharesIncludeTypeToString( + listSharesSegmentOptions.ListSharesInclude.GetValue()))); } if (listSharesSegmentOptions.Timeout.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryTimeout, std::to_string(listSharesSegmentOptions.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + Details::c_QueryTimeout, + Storage::Details::UrlEncodeQueryParameter( + std::to_string(listSharesSegmentOptions.Timeout.GetValue()))); } request.AddHeader(Details::c_HeaderVersion, listSharesSegmentOptions.ApiVersionParameter); return ListSharesSegmentParseResult(context, pipeline.Send(context, request)); @@ -2575,11 +2588,13 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { { Azure::Core::Http::Request request(Azure::Core::Http::HttpMethod::Put, url); request.AddHeader(Details::c_HeaderContentLength, "0"); - request.GetUrl().AppendQuery(Details::c_QueryRestype, "share"); + request.GetUrl().AppendQueryParameter(Details::c_QueryRestype, "share"); if (createOptions.Timeout.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryTimeout, std::to_string(createOptions.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + Details::c_QueryTimeout, + Storage::Details::UrlEncodeQueryParameter( + std::to_string(createOptions.Timeout.GetValue()))); } std::set metadataKeys; for (const auto& pair : createOptions.Metadata) @@ -2628,16 +2643,20 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { const GetPropertiesOptions& getPropertiesOptions) { Azure::Core::Http::Request request(Azure::Core::Http::HttpMethod::Get, url); - request.GetUrl().AppendQuery(Details::c_QueryRestype, "share"); + request.GetUrl().AppendQueryParameter(Details::c_QueryRestype, "share"); if (getPropertiesOptions.ShareSnapshot.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryShareSnapshot, getPropertiesOptions.ShareSnapshot.GetValue()); + request.GetUrl().AppendQueryParameter( + Details::c_QueryShareSnapshot, + Storage::Details::UrlEncodeQueryParameter( + getPropertiesOptions.ShareSnapshot.GetValue())); } if (getPropertiesOptions.Timeout.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryTimeout, std::to_string(getPropertiesOptions.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + Details::c_QueryTimeout, + Storage::Details::UrlEncodeQueryParameter( + std::to_string(getPropertiesOptions.Timeout.GetValue()))); } request.AddHeader(Details::c_HeaderVersion, getPropertiesOptions.ApiVersionParameter); if (getPropertiesOptions.LeaseIdOptional.HasValue()) @@ -2675,16 +2694,19 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { const DeleteOptions& deleteOptions) { Azure::Core::Http::Request request(Azure::Core::Http::HttpMethod::Delete, url); - request.GetUrl().AppendQuery(Details::c_QueryRestype, "share"); + request.GetUrl().AppendQueryParameter(Details::c_QueryRestype, "share"); if (deleteOptions.ShareSnapshot.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryShareSnapshot, deleteOptions.ShareSnapshot.GetValue()); + request.GetUrl().AppendQueryParameter( + Details::c_QueryShareSnapshot, + Storage::Details::UrlEncodeQueryParameter(deleteOptions.ShareSnapshot.GetValue())); } if (deleteOptions.Timeout.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryTimeout, std::to_string(deleteOptions.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + Details::c_QueryTimeout, + Storage::Details::UrlEncodeQueryParameter( + std::to_string(deleteOptions.Timeout.GetValue()))); } request.AddHeader(Details::c_HeaderVersion, deleteOptions.ApiVersionParameter); if (deleteOptions.XMsDeleteSnapshots.HasValue()) @@ -2736,13 +2758,15 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { { Azure::Core::Http::Request request(Azure::Core::Http::HttpMethod::Put, url); request.AddHeader(Details::c_HeaderContentLength, "0"); - request.GetUrl().AppendQuery(Details::c_QueryComp, "lease"); + request.GetUrl().AppendQueryParameter(Details::c_QueryComp, "lease"); request.AddHeader(Details::c_HeaderAction, "acquire"); - request.GetUrl().AppendQuery(Details::c_QueryRestype, "share"); + request.GetUrl().AppendQueryParameter(Details::c_QueryRestype, "share"); if (acquireLeaseOptions.Timeout.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryTimeout, std::to_string(acquireLeaseOptions.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + Details::c_QueryTimeout, + Storage::Details::UrlEncodeQueryParameter( + std::to_string(acquireLeaseOptions.Timeout.GetValue()))); } request.AddHeader( Details::c_HeaderDuration, std::to_string(acquireLeaseOptions.LeaseDuration)); @@ -2755,8 +2779,10 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { request.AddHeader(Details::c_HeaderVersion, acquireLeaseOptions.ApiVersionParameter); if (acquireLeaseOptions.ShareSnapshot.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryShareSnapshot, acquireLeaseOptions.ShareSnapshot.GetValue()); + request.GetUrl().AppendQueryParameter( + Details::c_QueryShareSnapshot, + Storage::Details::UrlEncodeQueryParameter( + acquireLeaseOptions.ShareSnapshot.GetValue())); } if (acquireLeaseOptions.ClientRequestId.HasValue()) { @@ -2793,20 +2819,24 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { { Azure::Core::Http::Request request(Azure::Core::Http::HttpMethod::Put, url); request.AddHeader(Details::c_HeaderContentLength, "0"); - request.GetUrl().AppendQuery(Details::c_QueryComp, "lease"); + request.GetUrl().AppendQueryParameter(Details::c_QueryComp, "lease"); request.AddHeader(Details::c_HeaderAction, "release"); - request.GetUrl().AppendQuery(Details::c_QueryRestype, "share"); + request.GetUrl().AppendQueryParameter(Details::c_QueryRestype, "share"); if (releaseLeaseOptions.Timeout.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryTimeout, std::to_string(releaseLeaseOptions.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + Details::c_QueryTimeout, + Storage::Details::UrlEncodeQueryParameter( + std::to_string(releaseLeaseOptions.Timeout.GetValue()))); } request.AddHeader(Details::c_HeaderLeaseId, releaseLeaseOptions.LeaseIdRequired); request.AddHeader(Details::c_HeaderVersion, releaseLeaseOptions.ApiVersionParameter); if (releaseLeaseOptions.ShareSnapshot.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryShareSnapshot, releaseLeaseOptions.ShareSnapshot.GetValue()); + request.GetUrl().AppendQueryParameter( + Details::c_QueryShareSnapshot, + Storage::Details::UrlEncodeQueryParameter( + releaseLeaseOptions.ShareSnapshot.GetValue())); } if (releaseLeaseOptions.ClientRequestId.HasValue()) { @@ -2848,13 +2878,15 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { { Azure::Core::Http::Request request(Azure::Core::Http::HttpMethod::Put, url); request.AddHeader(Details::c_HeaderContentLength, "0"); - request.GetUrl().AppendQuery(Details::c_QueryComp, "lease"); + request.GetUrl().AppendQueryParameter(Details::c_QueryComp, "lease"); request.AddHeader(Details::c_HeaderAction, "change"); - request.GetUrl().AppendQuery(Details::c_QueryRestype, "share"); + request.GetUrl().AppendQueryParameter(Details::c_QueryRestype, "share"); if (changeLeaseOptions.Timeout.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryTimeout, std::to_string(changeLeaseOptions.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + Details::c_QueryTimeout, + Storage::Details::UrlEncodeQueryParameter( + std::to_string(changeLeaseOptions.Timeout.GetValue()))); } request.AddHeader(Details::c_HeaderLeaseId, changeLeaseOptions.LeaseIdRequired); if (changeLeaseOptions.ProposedLeaseIdOptional.HasValue()) @@ -2866,8 +2898,10 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { request.AddHeader(Details::c_HeaderVersion, changeLeaseOptions.ApiVersionParameter); if (changeLeaseOptions.ShareSnapshot.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryShareSnapshot, changeLeaseOptions.ShareSnapshot.GetValue()); + request.GetUrl().AppendQueryParameter( + Details::c_QueryShareSnapshot, + Storage::Details::UrlEncodeQueryParameter( + changeLeaseOptions.ShareSnapshot.GetValue())); } if (changeLeaseOptions.ClientRequestId.HasValue()) { @@ -2904,20 +2938,24 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { { Azure::Core::Http::Request request(Azure::Core::Http::HttpMethod::Put, url); request.AddHeader(Details::c_HeaderContentLength, "0"); - request.GetUrl().AppendQuery(Details::c_QueryComp, "lease"); + request.GetUrl().AppendQueryParameter(Details::c_QueryComp, "lease"); request.AddHeader(Details::c_HeaderAction, "renew"); - request.GetUrl().AppendQuery(Details::c_QueryRestype, "share"); + request.GetUrl().AppendQueryParameter(Details::c_QueryRestype, "share"); if (renewLeaseOptions.Timeout.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryTimeout, std::to_string(renewLeaseOptions.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + Details::c_QueryTimeout, + Storage::Details::UrlEncodeQueryParameter( + std::to_string(renewLeaseOptions.Timeout.GetValue()))); } request.AddHeader(Details::c_HeaderLeaseId, renewLeaseOptions.LeaseIdRequired); request.AddHeader(Details::c_HeaderVersion, renewLeaseOptions.ApiVersionParameter); if (renewLeaseOptions.ShareSnapshot.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryShareSnapshot, renewLeaseOptions.ShareSnapshot.GetValue()); + request.GetUrl().AppendQueryParameter( + Details::c_QueryShareSnapshot, + Storage::Details::UrlEncodeQueryParameter( + renewLeaseOptions.ShareSnapshot.GetValue())); } if (renewLeaseOptions.ClientRequestId.HasValue()) { @@ -2966,13 +3004,15 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { { Azure::Core::Http::Request request(Azure::Core::Http::HttpMethod::Put, url); request.AddHeader(Details::c_HeaderContentLength, "0"); - request.GetUrl().AppendQuery(Details::c_QueryComp, "lease"); + request.GetUrl().AppendQueryParameter(Details::c_QueryComp, "lease"); request.AddHeader(Details::c_HeaderAction, "break"); - request.GetUrl().AppendQuery(Details::c_QueryRestype, "share"); + request.GetUrl().AppendQueryParameter(Details::c_QueryRestype, "share"); if (breakLeaseOptions.Timeout.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryTimeout, std::to_string(breakLeaseOptions.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + Details::c_QueryTimeout, + Storage::Details::UrlEncodeQueryParameter( + std::to_string(breakLeaseOptions.Timeout.GetValue()))); } if (breakLeaseOptions.LeaseBreakPeriod.HasValue()) { @@ -2992,8 +3032,10 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { } if (breakLeaseOptions.ShareSnapshot.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryShareSnapshot, breakLeaseOptions.ShareSnapshot.GetValue()); + request.GetUrl().AppendQueryParameter( + Details::c_QueryShareSnapshot, + Storage::Details::UrlEncodeQueryParameter( + breakLeaseOptions.ShareSnapshot.GetValue())); } return BreakLeaseParseResult(context, pipeline.Send(context, request)); } @@ -3019,12 +3061,14 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { { Azure::Core::Http::Request request(Azure::Core::Http::HttpMethod::Put, url); request.AddHeader(Details::c_HeaderContentLength, "0"); - request.GetUrl().AppendQuery(Details::c_QueryRestype, "share"); - request.GetUrl().AppendQuery(Details::c_QueryComp, "snapshot"); + request.GetUrl().AppendQueryParameter(Details::c_QueryRestype, "share"); + request.GetUrl().AppendQueryParameter(Details::c_QueryComp, "snapshot"); if (createSnapshotOptions.Timeout.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryTimeout, std::to_string(createSnapshotOptions.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + Details::c_QueryTimeout, + Storage::Details::UrlEncodeQueryParameter( + std::to_string(createSnapshotOptions.Timeout.GetValue()))); } std::set metadataKeys; for (const auto& pair : createSnapshotOptions.Metadata) @@ -3073,12 +3117,14 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { reinterpret_cast(json_body.data()), json_body.length()); auto request = Azure::Core::Http::Request(Azure::Core::Http::HttpMethod::Put, url, &body); request.AddHeader("Content-Length", std::to_string(body.Length())); - request.GetUrl().AppendQuery(Details::c_QueryRestype, "share"); - request.GetUrl().AppendQuery(Details::c_QueryComp, "filepermission"); + request.GetUrl().AppendQueryParameter(Details::c_QueryRestype, "share"); + request.GetUrl().AppendQueryParameter(Details::c_QueryComp, "filepermission"); if (createPermissionOptions.Timeout.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryTimeout, std::to_string(createPermissionOptions.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + Details::c_QueryTimeout, + Storage::Details::UrlEncodeQueryParameter( + std::to_string(createPermissionOptions.Timeout.GetValue()))); } request.AddHeader(Details::c_HeaderVersion, createPermissionOptions.ApiVersionParameter); return CreatePermissionParseResult(context, pipeline.Send(context, request)); @@ -3104,14 +3150,16 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { const GetPermissionOptions& getPermissionOptions) { Azure::Core::Http::Request request(Azure::Core::Http::HttpMethod::Get, url); - request.GetUrl().AppendQuery(Details::c_QueryRestype, "share"); - request.GetUrl().AppendQuery(Details::c_QueryComp, "filepermission"); + request.GetUrl().AppendQueryParameter(Details::c_QueryRestype, "share"); + request.GetUrl().AppendQueryParameter(Details::c_QueryComp, "filepermission"); request.AddHeader( Details::c_HeaderFilePermissionKey, getPermissionOptions.FilePermissionKeyRequired); if (getPermissionOptions.Timeout.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryTimeout, std::to_string(getPermissionOptions.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + Details::c_QueryTimeout, + Storage::Details::UrlEncodeQueryParameter( + std::to_string(getPermissionOptions.Timeout.GetValue()))); } request.AddHeader(Details::c_HeaderVersion, getPermissionOptions.ApiVersionParameter); return GetPermissionParseResult(context, pipeline.Send(context, request)); @@ -3141,12 +3189,14 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { { Azure::Core::Http::Request request(Azure::Core::Http::HttpMethod::Put, url); request.AddHeader(Details::c_HeaderContentLength, "0"); - request.GetUrl().AppendQuery(Details::c_QueryRestype, "share"); - request.GetUrl().AppendQuery(Details::c_QueryComp, "properties"); + request.GetUrl().AppendQueryParameter(Details::c_QueryRestype, "share"); + request.GetUrl().AppendQueryParameter(Details::c_QueryComp, "properties"); if (setQuotaOptions.Timeout.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryTimeout, std::to_string(setQuotaOptions.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + Details::c_QueryTimeout, + Storage::Details::UrlEncodeQueryParameter( + std::to_string(setQuotaOptions.Timeout.GetValue()))); } request.AddHeader(Details::c_HeaderVersion, setQuotaOptions.ApiVersionParameter); if (setQuotaOptions.ShareQuota.HasValue()) @@ -3185,12 +3235,14 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { { Azure::Core::Http::Request request(Azure::Core::Http::HttpMethod::Put, url); request.AddHeader(Details::c_HeaderContentLength, "0"); - request.GetUrl().AppendQuery(Details::c_QueryRestype, "share"); - request.GetUrl().AppendQuery(Details::c_QueryComp, "metadata"); + request.GetUrl().AppendQueryParameter(Details::c_QueryRestype, "share"); + request.GetUrl().AppendQueryParameter(Details::c_QueryComp, "metadata"); if (setMetadataOptions.Timeout.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryTimeout, std::to_string(setMetadataOptions.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + Details::c_QueryTimeout, + Storage::Details::UrlEncodeQueryParameter( + std::to_string(setMetadataOptions.Timeout.GetValue()))); } std::set metadataKeys; for (const auto& pair : setMetadataOptions.Metadata) @@ -3236,12 +3288,14 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { const GetAccessPolicyOptions& getAccessPolicyOptions) { Azure::Core::Http::Request request(Azure::Core::Http::HttpMethod::Get, url); - request.GetUrl().AppendQuery(Details::c_QueryRestype, "share"); - request.GetUrl().AppendQuery(Details::c_QueryComp, "acl"); + request.GetUrl().AppendQueryParameter(Details::c_QueryRestype, "share"); + request.GetUrl().AppendQueryParameter(Details::c_QueryComp, "acl"); if (getAccessPolicyOptions.Timeout.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryTimeout, std::to_string(getAccessPolicyOptions.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + Details::c_QueryTimeout, + Storage::Details::UrlEncodeQueryParameter( + std::to_string(getAccessPolicyOptions.Timeout.GetValue()))); } request.AddHeader(Details::c_HeaderVersion, getAccessPolicyOptions.ApiVersionParameter); if (getAccessPolicyOptions.LeaseIdOptional.HasValue()) @@ -3285,12 +3339,14 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { reinterpret_cast(xml_body.data()), xml_body.length()); auto request = Azure::Core::Http::Request(Azure::Core::Http::HttpMethod::Put, url, &body); request.AddHeader("Content-Length", std::to_string(body.Length())); - request.GetUrl().AppendQuery(Details::c_QueryRestype, "share"); - request.GetUrl().AppendQuery(Details::c_QueryComp, "acl"); + request.GetUrl().AppendQueryParameter(Details::c_QueryRestype, "share"); + request.GetUrl().AppendQueryParameter(Details::c_QueryComp, "acl"); if (setAccessPolicyOptions.Timeout.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryTimeout, std::to_string(setAccessPolicyOptions.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + Details::c_QueryTimeout, + Storage::Details::UrlEncodeQueryParameter( + std::to_string(setAccessPolicyOptions.Timeout.GetValue()))); } request.AddHeader(Details::c_HeaderVersion, setAccessPolicyOptions.ApiVersionParameter); if (setAccessPolicyOptions.LeaseIdOptional.HasValue()) @@ -3322,12 +3378,14 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { const GetStatisticsOptions& getStatisticsOptions) { Azure::Core::Http::Request request(Azure::Core::Http::HttpMethod::Get, url); - request.GetUrl().AppendQuery(Details::c_QueryRestype, "share"); - request.GetUrl().AppendQuery(Details::c_QueryComp, "stats"); + request.GetUrl().AppendQueryParameter(Details::c_QueryRestype, "share"); + request.GetUrl().AppendQueryParameter(Details::c_QueryComp, "stats"); if (getStatisticsOptions.Timeout.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryTimeout, std::to_string(getStatisticsOptions.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + Details::c_QueryTimeout, + Storage::Details::UrlEncodeQueryParameter( + std::to_string(getStatisticsOptions.Timeout.GetValue()))); } request.AddHeader(Details::c_HeaderVersion, getStatisticsOptions.ApiVersionParameter); if (getStatisticsOptions.LeaseIdOptional.HasValue()) @@ -3365,12 +3423,14 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { { Azure::Core::Http::Request request(Azure::Core::Http::HttpMethod::Put, url); request.AddHeader(Details::c_HeaderContentLength, "0"); - request.GetUrl().AppendQuery(Details::c_QueryRestype, "share"); - request.GetUrl().AppendQuery(Details::c_QueryComp, "undelete"); + request.GetUrl().AppendQueryParameter(Details::c_QueryRestype, "share"); + request.GetUrl().AppendQueryParameter(Details::c_QueryComp, "undelete"); if (restoreOptions.Timeout.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryTimeout, std::to_string(restoreOptions.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + Details::c_QueryTimeout, + Storage::Details::UrlEncodeQueryParameter( + std::to_string(restoreOptions.Timeout.GetValue()))); } request.AddHeader(Details::c_HeaderVersion, restoreOptions.ApiVersionParameter); if (restoreOptions.ClientRequestId.HasValue()) @@ -4180,8 +4240,8 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { // one of the x-ms-file-permission or x-ms-file-permission-key should // be specified. std::string FileAttributes; // If specified, the provided file attributes shall be set. - // Default value: ‘Archive’ for file and ‘Directory’ for - // directory. ‘None’ can also be specified as default. + // Default value: Archive for file and Directory for directory. + // None can also be specified as default. std::string FileCreationTime; // Creation time for the file/directory. Default value: Now. std::string FileLastWriteTime; // Last write time for the file/directory. Default value: Now. @@ -4195,11 +4255,13 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { { Azure::Core::Http::Request request(Azure::Core::Http::HttpMethod::Put, url); request.AddHeader(Details::c_HeaderContentLength, "0"); - request.GetUrl().AppendQuery(Details::c_QueryRestype, "directory"); + request.GetUrl().AppendQueryParameter(Details::c_QueryRestype, "directory"); if (createOptions.Timeout.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryTimeout, std::to_string(createOptions.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + Details::c_QueryTimeout, + Storage::Details::UrlEncodeQueryParameter( + std::to_string(createOptions.Timeout.GetValue()))); } std::set metadataKeys; for (const auto& pair : createOptions.Metadata) @@ -4253,16 +4315,20 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { const GetPropertiesOptions& getPropertiesOptions) { Azure::Core::Http::Request request(Azure::Core::Http::HttpMethod::Get, url); - request.GetUrl().AppendQuery(Details::c_QueryRestype, "directory"); + request.GetUrl().AppendQueryParameter(Details::c_QueryRestype, "directory"); if (getPropertiesOptions.ShareSnapshot.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryShareSnapshot, getPropertiesOptions.ShareSnapshot.GetValue()); + request.GetUrl().AppendQueryParameter( + Details::c_QueryShareSnapshot, + Storage::Details::UrlEncodeQueryParameter( + getPropertiesOptions.ShareSnapshot.GetValue())); } if (getPropertiesOptions.Timeout.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryTimeout, std::to_string(getPropertiesOptions.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + Details::c_QueryTimeout, + Storage::Details::UrlEncodeQueryParameter( + std::to_string(getPropertiesOptions.Timeout.GetValue()))); } request.AddHeader(Details::c_HeaderVersion, getPropertiesOptions.ApiVersionParameter); return GetPropertiesParseResult(context, pipeline.Send(context, request)); @@ -4286,11 +4352,13 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { const DeleteOptions& deleteOptions) { Azure::Core::Http::Request request(Azure::Core::Http::HttpMethod::Delete, url); - request.GetUrl().AppendQuery(Details::c_QueryRestype, "directory"); + request.GetUrl().AppendQueryParameter(Details::c_QueryRestype, "directory"); if (deleteOptions.Timeout.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryTimeout, std::to_string(deleteOptions.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + Details::c_QueryTimeout, + Storage::Details::UrlEncodeQueryParameter( + std::to_string(deleteOptions.Timeout.GetValue()))); } request.AddHeader(Details::c_HeaderVersion, deleteOptions.ApiVersionParameter); return DeleteParseResult(context, pipeline.Send(context, request)); @@ -4317,8 +4385,8 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { // one of the x-ms-file-permission or x-ms-file-permission-key should // be specified. std::string FileAttributes; // If specified, the provided file attributes shall be set. - // Default value: ‘Archive’ for file and ‘Directory’ for - // directory. ‘None’ can also be specified as default. + // Default value: Archive for file and Directory for directory. + // None can also be specified as default. std::string FileCreationTime; // Creation time for the file/directory. Default value: Now. std::string FileLastWriteTime; // Last write time for the file/directory. Default value: Now. @@ -4332,12 +4400,14 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { { Azure::Core::Http::Request request(Azure::Core::Http::HttpMethod::Put, url); request.AddHeader(Details::c_HeaderContentLength, "0"); - request.GetUrl().AppendQuery(Details::c_QueryRestype, "directory"); - request.GetUrl().AppendQuery(Details::c_QueryComp, "properties"); + request.GetUrl().AppendQueryParameter(Details::c_QueryRestype, "directory"); + request.GetUrl().AppendQueryParameter(Details::c_QueryComp, "properties"); if (setPropertiesOptions.Timeout.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryTimeout, std::to_string(setPropertiesOptions.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + Details::c_QueryTimeout, + Storage::Details::UrlEncodeQueryParameter( + std::to_string(setPropertiesOptions.Timeout.GetValue()))); } request.AddHeader(Details::c_HeaderVersion, setPropertiesOptions.ApiVersionParameter); if (setPropertiesOptions.FilePermission.HasValue()) @@ -4379,12 +4449,14 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { { Azure::Core::Http::Request request(Azure::Core::Http::HttpMethod::Put, url); request.AddHeader(Details::c_HeaderContentLength, "0"); - request.GetUrl().AppendQuery(Details::c_QueryRestype, "directory"); - request.GetUrl().AppendQuery(Details::c_QueryComp, "metadata"); + request.GetUrl().AppendQueryParameter(Details::c_QueryRestype, "directory"); + request.GetUrl().AppendQueryParameter(Details::c_QueryComp, "metadata"); if (setMetadataOptions.Timeout.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryTimeout, std::to_string(setMetadataOptions.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + Details::c_QueryTimeout, + Storage::Details::UrlEncodeQueryParameter( + std::to_string(setMetadataOptions.Timeout.GetValue()))); } std::set metadataKeys; for (const auto& pair : setMetadataOptions.Metadata) @@ -4438,35 +4510,42 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { const ListFilesAndDirectoriesSegmentOptions& listFilesAndDirectoriesSegmentOptions) { Azure::Core::Http::Request request(Azure::Core::Http::HttpMethod::Get, url); - request.GetUrl().AppendQuery(Details::c_QueryRestype, "directory"); - request.GetUrl().AppendQuery(Details::c_QueryComp, "list"); + request.GetUrl().AppendQueryParameter(Details::c_QueryRestype, "directory"); + request.GetUrl().AppendQueryParameter(Details::c_QueryComp, "list"); if (listFilesAndDirectoriesSegmentOptions.Prefix.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryPrefix, listFilesAndDirectoriesSegmentOptions.Prefix.GetValue()); + request.GetUrl().AppendQueryParameter( + Details::c_QueryPrefix, + Storage::Details::UrlEncodeQueryParameter( + listFilesAndDirectoriesSegmentOptions.Prefix.GetValue())); } if (listFilesAndDirectoriesSegmentOptions.ShareSnapshot.HasValue()) { - request.GetUrl().AppendQuery( + request.GetUrl().AppendQueryParameter( Details::c_QueryShareSnapshot, - listFilesAndDirectoriesSegmentOptions.ShareSnapshot.GetValue()); + Storage::Details::UrlEncodeQueryParameter( + listFilesAndDirectoriesSegmentOptions.ShareSnapshot.GetValue())); } if (listFilesAndDirectoriesSegmentOptions.Marker.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryMarker, listFilesAndDirectoriesSegmentOptions.Marker.GetValue()); + request.GetUrl().AppendQueryParameter( + Details::c_QueryMarker, + Storage::Details::UrlEncodeQueryParameter( + listFilesAndDirectoriesSegmentOptions.Marker.GetValue())); } if (listFilesAndDirectoriesSegmentOptions.MaxResults.HasValue()) { - request.GetUrl().AppendQuery( + request.GetUrl().AppendQueryParameter( Details::c_QueryMaxResults, - std::to_string(listFilesAndDirectoriesSegmentOptions.MaxResults.GetValue())); + Storage::Details::UrlEncodeQueryParameter( + std::to_string(listFilesAndDirectoriesSegmentOptions.MaxResults.GetValue()))); } if (listFilesAndDirectoriesSegmentOptions.Timeout.HasValue()) { - request.GetUrl().AppendQuery( + request.GetUrl().AppendQueryParameter( Details::c_QueryTimeout, - std::to_string(listFilesAndDirectoriesSegmentOptions.Timeout.GetValue())); + Storage::Details::UrlEncodeQueryParameter( + std::to_string(listFilesAndDirectoriesSegmentOptions.Timeout.GetValue()))); } request.AddHeader( Details::c_HeaderVersion, listFilesAndDirectoriesSegmentOptions.ApiVersionParameter); @@ -4507,26 +4586,33 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { const ListHandlesOptions& listHandlesOptions) { Azure::Core::Http::Request request(Azure::Core::Http::HttpMethod::Get, url); - request.GetUrl().AppendQuery(Details::c_QueryComp, "listhandles"); + request.GetUrl().AppendQueryParameter(Details::c_QueryComp, "listhandles"); if (listHandlesOptions.Marker.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryMarker, listHandlesOptions.Marker.GetValue()); + request.GetUrl().AppendQueryParameter( + Details::c_QueryMarker, + Storage::Details::UrlEncodeQueryParameter(listHandlesOptions.Marker.GetValue())); } if (listHandlesOptions.MaxResults.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryMaxResults, std::to_string(listHandlesOptions.MaxResults.GetValue())); + request.GetUrl().AppendQueryParameter( + Details::c_QueryMaxResults, + Storage::Details::UrlEncodeQueryParameter( + std::to_string(listHandlesOptions.MaxResults.GetValue()))); } if (listHandlesOptions.Timeout.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryTimeout, std::to_string(listHandlesOptions.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + Details::c_QueryTimeout, + Storage::Details::UrlEncodeQueryParameter( + std::to_string(listHandlesOptions.Timeout.GetValue()))); } if (listHandlesOptions.ShareSnapshot.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryShareSnapshot, listHandlesOptions.ShareSnapshot.GetValue()); + request.GetUrl().AppendQueryParameter( + Details::c_QueryShareSnapshot, + Storage::Details::UrlEncodeQueryParameter( + listHandlesOptions.ShareSnapshot.GetValue())); } if (listHandlesOptions.Recursive.HasValue()) { @@ -4554,7 +4640,7 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { ShareSnapshot; // The snapshot parameter is an opaque DateTime value that, when present, // specifies the share snapshot to query. std::string HandleId; // Specifies handle ID opened on the file or directory to be closed. - // Asterisk (‘*’) is a wildcard that specifies all handles. + // Asterisk (*) is a wildcard that specifies all handles. Azure::Core::Nullable Recursive; // Specifies operation should apply to the directory specified in the URI, // its files, its subdirectories and their files. @@ -4571,21 +4657,27 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { { Azure::Core::Http::Request request(Azure::Core::Http::HttpMethod::Put, url); request.AddHeader(Details::c_HeaderContentLength, "0"); - request.GetUrl().AppendQuery(Details::c_QueryComp, "forceclosehandles"); + request.GetUrl().AppendQueryParameter(Details::c_QueryComp, "forceclosehandles"); if (forceCloseHandlesOptions.Timeout.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryTimeout, std::to_string(forceCloseHandlesOptions.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + Details::c_QueryTimeout, + Storage::Details::UrlEncodeQueryParameter( + std::to_string(forceCloseHandlesOptions.Timeout.GetValue()))); } if (forceCloseHandlesOptions.Marker.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryMarker, forceCloseHandlesOptions.Marker.GetValue()); + request.GetUrl().AppendQueryParameter( + Details::c_QueryMarker, + Storage::Details::UrlEncodeQueryParameter( + forceCloseHandlesOptions.Marker.GetValue())); } if (forceCloseHandlesOptions.ShareSnapshot.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryShareSnapshot, forceCloseHandlesOptions.ShareSnapshot.GetValue()); + request.GetUrl().AppendQueryParameter( + Details::c_QueryShareSnapshot, + Storage::Details::UrlEncodeQueryParameter( + forceCloseHandlesOptions.ShareSnapshot.GetValue())); } request.AddHeader(Details::c_HeaderHandleId, forceCloseHandlesOptions.HandleId); if (forceCloseHandlesOptions.Recursive.HasValue()) @@ -5426,8 +5518,8 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { // one of the x-ms-file-permission or x-ms-file-permission-key should // be specified. std::string FileAttributes; // If specified, the provided file attributes shall be set. - // Default value: ‘Archive’ for file and ‘Directory’ for - // directory. ‘None’ can also be specified as default. + // Default value: Archive for file and Directory for directory. + // None can also be specified as default. std::string FileCreationTime; // Creation time for the file/directory. Default value: Now. std::string FileLastWriteTime; // Last write time for the file/directory. Default value: Now. @@ -5446,8 +5538,10 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { request.AddHeader(Details::c_HeaderContentLength, "0"); if (createOptions.Timeout.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryTimeout, std::to_string(createOptions.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + Details::c_QueryTimeout, + Storage::Details::UrlEncodeQueryParameter( + std::to_string(createOptions.Timeout.GetValue()))); } request.AddHeader(Details::c_HeaderVersion, createOptions.ApiVersionParameter); request.AddHeader( @@ -5546,8 +5640,10 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { Azure::Core::Http::Request request(Azure::Core::Http::HttpMethod::Get, url, true); if (downloadOptions.Timeout.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryTimeout, std::to_string(downloadOptions.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + Details::c_QueryTimeout, + Storage::Details::UrlEncodeQueryParameter( + std::to_string(downloadOptions.Timeout.GetValue()))); } request.AddHeader(Details::c_HeaderVersion, downloadOptions.ApiVersionParameter); if (downloadOptions.Range.HasValue()) @@ -5593,13 +5689,17 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { Azure::Core::Http::Request request(Azure::Core::Http::HttpMethod::Head, url); if (getPropertiesOptions.ShareSnapshot.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryShareSnapshot, getPropertiesOptions.ShareSnapshot.GetValue()); + request.GetUrl().AppendQueryParameter( + Details::c_QueryShareSnapshot, + Storage::Details::UrlEncodeQueryParameter( + getPropertiesOptions.ShareSnapshot.GetValue())); } if (getPropertiesOptions.Timeout.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryTimeout, std::to_string(getPropertiesOptions.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + Details::c_QueryTimeout, + Storage::Details::UrlEncodeQueryParameter( + std::to_string(getPropertiesOptions.Timeout.GetValue()))); } request.AddHeader(Details::c_HeaderVersion, getPropertiesOptions.ApiVersionParameter); if (getPropertiesOptions.LeaseIdOptional.HasValue()) @@ -5633,8 +5733,10 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { Azure::Core::Http::Request request(Azure::Core::Http::HttpMethod::Delete, url); if (deleteOptions.Timeout.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryTimeout, std::to_string(deleteOptions.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + Details::c_QueryTimeout, + Storage::Details::UrlEncodeQueryParameter( + std::to_string(deleteOptions.Timeout.GetValue()))); } request.AddHeader(Details::c_HeaderVersion, deleteOptions.ApiVersionParameter); if (deleteOptions.LeaseIdOptional.HasValue()) @@ -5682,8 +5784,8 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { // one of the x-ms-file-permission or x-ms-file-permission-key should // be specified. std::string FileAttributes; // If specified, the provided file attributes shall be set. - // Default value: ‘Archive’ for file and ‘Directory’ for - // directory. ‘None’ can also be specified as default. + // Default value: Archive for file and Directory for directory. + // None can also be specified as default. std::string FileCreationTime; // Creation time for the file/directory. Default value: Now. std::string FileLastWriteTime; // Last write time for the file/directory. Default value: Now. @@ -5700,11 +5802,13 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { { Azure::Core::Http::Request request(Azure::Core::Http::HttpMethod::Put, url); request.AddHeader(Details::c_HeaderContentLength, "0"); - request.GetUrl().AppendQuery(Details::c_QueryComp, "properties"); + request.GetUrl().AppendQueryParameter(Details::c_QueryComp, "properties"); if (setHttpHeadersOptions.Timeout.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryTimeout, std::to_string(setHttpHeadersOptions.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + Details::c_QueryTimeout, + Storage::Details::UrlEncodeQueryParameter( + std::to_string(setHttpHeadersOptions.Timeout.GetValue()))); } request.AddHeader(Details::c_HeaderVersion, setHttpHeadersOptions.ApiVersionParameter); if (setHttpHeadersOptions.XMsContentLength.HasValue()) @@ -5794,11 +5898,13 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { { Azure::Core::Http::Request request(Azure::Core::Http::HttpMethod::Put, url); request.AddHeader(Details::c_HeaderContentLength, "0"); - request.GetUrl().AppendQuery(Details::c_QueryComp, "metadata"); + request.GetUrl().AppendQueryParameter(Details::c_QueryComp, "metadata"); if (setMetadataOptions.Timeout.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryTimeout, std::to_string(setMetadataOptions.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + Details::c_QueryTimeout, + Storage::Details::UrlEncodeQueryParameter( + std::to_string(setMetadataOptions.Timeout.GetValue()))); } std::set metadataKeys; for (const auto& pair : setMetadataOptions.Metadata) @@ -5856,12 +5962,14 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { { Azure::Core::Http::Request request(Azure::Core::Http::HttpMethod::Put, url); request.AddHeader(Details::c_HeaderContentLength, "0"); - request.GetUrl().AppendQuery(Details::c_QueryComp, "lease"); + request.GetUrl().AppendQueryParameter(Details::c_QueryComp, "lease"); request.AddHeader(Details::c_HeaderAction, "acquire"); if (acquireLeaseOptions.Timeout.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryTimeout, std::to_string(acquireLeaseOptions.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + Details::c_QueryTimeout, + Storage::Details::UrlEncodeQueryParameter( + std::to_string(acquireLeaseOptions.Timeout.GetValue()))); } request.AddHeader( Details::c_HeaderDuration, std::to_string(acquireLeaseOptions.LeaseDuration)); @@ -5904,12 +6012,14 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { { Azure::Core::Http::Request request(Azure::Core::Http::HttpMethod::Put, url); request.AddHeader(Details::c_HeaderContentLength, "0"); - request.GetUrl().AppendQuery(Details::c_QueryComp, "lease"); + request.GetUrl().AppendQueryParameter(Details::c_QueryComp, "lease"); request.AddHeader(Details::c_HeaderAction, "release"); if (releaseLeaseOptions.Timeout.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryTimeout, std::to_string(releaseLeaseOptions.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + Details::c_QueryTimeout, + Storage::Details::UrlEncodeQueryParameter( + std::to_string(releaseLeaseOptions.Timeout.GetValue()))); } request.AddHeader(Details::c_HeaderLeaseId, releaseLeaseOptions.LeaseIdRequired); request.AddHeader(Details::c_HeaderVersion, releaseLeaseOptions.ApiVersionParameter); @@ -5950,12 +6060,14 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { { Azure::Core::Http::Request request(Azure::Core::Http::HttpMethod::Put, url); request.AddHeader(Details::c_HeaderContentLength, "0"); - request.GetUrl().AppendQuery(Details::c_QueryComp, "lease"); + request.GetUrl().AppendQueryParameter(Details::c_QueryComp, "lease"); request.AddHeader(Details::c_HeaderAction, "change"); if (changeLeaseOptions.Timeout.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryTimeout, std::to_string(changeLeaseOptions.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + Details::c_QueryTimeout, + Storage::Details::UrlEncodeQueryParameter( + std::to_string(changeLeaseOptions.Timeout.GetValue()))); } request.AddHeader(Details::c_HeaderLeaseId, changeLeaseOptions.LeaseIdRequired); if (changeLeaseOptions.ProposedLeaseIdOptional.HasValue()) @@ -5999,12 +6111,14 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { { Azure::Core::Http::Request request(Azure::Core::Http::HttpMethod::Put, url); request.AddHeader(Details::c_HeaderContentLength, "0"); - request.GetUrl().AppendQuery(Details::c_QueryComp, "lease"); + request.GetUrl().AppendQueryParameter(Details::c_QueryComp, "lease"); request.AddHeader(Details::c_HeaderAction, "break"); if (breakLeaseOptions.Timeout.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryTimeout, std::to_string(breakLeaseOptions.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + Details::c_QueryTimeout, + Storage::Details::UrlEncodeQueryParameter( + std::to_string(breakLeaseOptions.Timeout.GetValue()))); } if (breakLeaseOptions.LeaseIdOptional.HasValue()) { @@ -6065,11 +6179,13 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { { Azure::Core::Http::Request request( Azure::Core::Http::HttpMethod::Put, std::move(url), &bodyStream); - request.GetUrl().AppendQuery(Details::c_QueryComp, "range"); + request.GetUrl().AppendQueryParameter(Details::c_QueryComp, "range"); if (uploadRangeOptions.Timeout.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryTimeout, std::to_string(uploadRangeOptions.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + Details::c_QueryTimeout, + Storage::Details::UrlEncodeQueryParameter( + std::to_string(uploadRangeOptions.Timeout.GetValue()))); } request.AddHeader(Details::c_HeaderRange, uploadRangeOptions.XMsRange); request.AddHeader( @@ -6140,12 +6256,13 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { { Azure::Core::Http::Request request(Azure::Core::Http::HttpMethod::Put, url); request.AddHeader(Details::c_HeaderContentLength, "0"); - request.GetUrl().AppendQuery(Details::c_QueryComp, "range"); + request.GetUrl().AppendQueryParameter(Details::c_QueryComp, "range"); if (uploadRangeFromUrlOptions.Timeout.HasValue()) { - request.GetUrl().AppendQuery( + request.GetUrl().AppendQueryParameter( Details::c_QueryTimeout, - std::to_string(uploadRangeFromUrlOptions.Timeout.GetValue())); + Storage::Details::UrlEncodeQueryParameter( + std::to_string(uploadRangeFromUrlOptions.Timeout.GetValue()))); } request.AddHeader(Details::c_HeaderRange, uploadRangeFromUrlOptions.TargetRange); request.AddHeader(Details::c_HeaderCopySource, uploadRangeFromUrlOptions.CopySource); @@ -6216,21 +6333,27 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { const GetRangeListOptions& getRangeListOptions) { Azure::Core::Http::Request request(Azure::Core::Http::HttpMethod::Get, url); - request.GetUrl().AppendQuery(Details::c_QueryComp, "rangelist"); + request.GetUrl().AppendQueryParameter(Details::c_QueryComp, "rangelist"); if (getRangeListOptions.ShareSnapshot.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryShareSnapshot, getRangeListOptions.ShareSnapshot.GetValue()); + request.GetUrl().AppendQueryParameter( + Details::c_QueryShareSnapshot, + Storage::Details::UrlEncodeQueryParameter( + getRangeListOptions.ShareSnapshot.GetValue())); } if (getRangeListOptions.PrevShareSnapshot.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryPrevShareSnapshot, getRangeListOptions.PrevShareSnapshot.GetValue()); + request.GetUrl().AppendQueryParameter( + Details::c_QueryPrevShareSnapshot, + Storage::Details::UrlEncodeQueryParameter( + getRangeListOptions.PrevShareSnapshot.GetValue())); } if (getRangeListOptions.Timeout.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryTimeout, std::to_string(getRangeListOptions.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + Details::c_QueryTimeout, + Storage::Details::UrlEncodeQueryParameter( + std::to_string(getRangeListOptions.Timeout.GetValue()))); } request.AddHeader(Details::c_HeaderVersion, getRangeListOptions.ApiVersionParameter); if (getRangeListOptions.XMsRange.HasValue()) @@ -6318,8 +6441,10 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { request.AddHeader(Details::c_HeaderContentLength, "0"); if (startCopyOptions.Timeout.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryTimeout, std::to_string(startCopyOptions.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + Details::c_QueryTimeout, + Storage::Details::UrlEncodeQueryParameter( + std::to_string(startCopyOptions.Timeout.GetValue()))); } request.AddHeader(Details::c_HeaderVersion, startCopyOptions.ApiVersionParameter); std::set metadataKeys; @@ -6414,12 +6539,16 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { { Azure::Core::Http::Request request(Azure::Core::Http::HttpMethod::Put, url); request.AddHeader(Details::c_HeaderContentLength, "0"); - request.GetUrl().AppendQuery(Details::c_QueryComp, "copy"); - request.GetUrl().AppendQuery(Details::c_QueryCopyId, abortCopyOptions.CopyId); + request.GetUrl().AppendQueryParameter(Details::c_QueryComp, "copy"); + request.GetUrl().AppendQueryParameter( + Details::c_QueryCopyId, + Storage::Details::UrlEncodeQueryParameter(abortCopyOptions.CopyId)); if (abortCopyOptions.Timeout.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryTimeout, std::to_string(abortCopyOptions.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + Details::c_QueryTimeout, + Storage::Details::UrlEncodeQueryParameter( + std::to_string(abortCopyOptions.Timeout.GetValue()))); } request.AddHeader(Details::c_HeaderCopyActionAbortConstant, "abort"); request.AddHeader(Details::c_HeaderVersion, abortCopyOptions.ApiVersionParameter); @@ -6461,26 +6590,33 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { const ListHandlesOptions& listHandlesOptions) { Azure::Core::Http::Request request(Azure::Core::Http::HttpMethod::Get, url); - request.GetUrl().AppendQuery(Details::c_QueryComp, "listhandles"); + request.GetUrl().AppendQueryParameter(Details::c_QueryComp, "listhandles"); if (listHandlesOptions.Marker.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryMarker, listHandlesOptions.Marker.GetValue()); + request.GetUrl().AppendQueryParameter( + Details::c_QueryMarker, + Storage::Details::UrlEncodeQueryParameter(listHandlesOptions.Marker.GetValue())); } if (listHandlesOptions.MaxResults.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryMaxResults, std::to_string(listHandlesOptions.MaxResults.GetValue())); + request.GetUrl().AppendQueryParameter( + Details::c_QueryMaxResults, + Storage::Details::UrlEncodeQueryParameter( + std::to_string(listHandlesOptions.MaxResults.GetValue()))); } if (listHandlesOptions.Timeout.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryTimeout, std::to_string(listHandlesOptions.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + Details::c_QueryTimeout, + Storage::Details::UrlEncodeQueryParameter( + std::to_string(listHandlesOptions.Timeout.GetValue()))); } if (listHandlesOptions.ShareSnapshot.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryShareSnapshot, listHandlesOptions.ShareSnapshot.GetValue()); + request.GetUrl().AppendQueryParameter( + Details::c_QueryShareSnapshot, + Storage::Details::UrlEncodeQueryParameter( + listHandlesOptions.ShareSnapshot.GetValue())); } request.AddHeader(Details::c_HeaderVersion, listHandlesOptions.ApiVersionParameter); return ListHandlesParseResult(context, pipeline.Send(context, request)); @@ -6502,7 +6638,7 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { ShareSnapshot; // The snapshot parameter is an opaque DateTime value that, when present, // specifies the share snapshot to query. std::string HandleId; // Specifies handle ID opened on the file or directory to be closed. - // Asterisk (‘*’) is a wildcard that specifies all handles. + // Asterisk (*) is a wildcard that specifies all handles. std::string ApiVersionParameter = Details::c_DefaultServiceApiVersion; // Specifies the version of the operation to use // for this request. @@ -6516,21 +6652,27 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { { Azure::Core::Http::Request request(Azure::Core::Http::HttpMethod::Put, url); request.AddHeader(Details::c_HeaderContentLength, "0"); - request.GetUrl().AppendQuery(Details::c_QueryComp, "forceclosehandles"); + request.GetUrl().AppendQueryParameter(Details::c_QueryComp, "forceclosehandles"); if (forceCloseHandlesOptions.Timeout.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryTimeout, std::to_string(forceCloseHandlesOptions.Timeout.GetValue())); + request.GetUrl().AppendQueryParameter( + Details::c_QueryTimeout, + Storage::Details::UrlEncodeQueryParameter( + std::to_string(forceCloseHandlesOptions.Timeout.GetValue()))); } if (forceCloseHandlesOptions.Marker.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryMarker, forceCloseHandlesOptions.Marker.GetValue()); + request.GetUrl().AppendQueryParameter( + Details::c_QueryMarker, + Storage::Details::UrlEncodeQueryParameter( + forceCloseHandlesOptions.Marker.GetValue())); } if (forceCloseHandlesOptions.ShareSnapshot.HasValue()) { - request.GetUrl().AppendQuery( - Details::c_QueryShareSnapshot, forceCloseHandlesOptions.ShareSnapshot.GetValue()); + request.GetUrl().AppendQueryParameter( + Details::c_QueryShareSnapshot, + Storage::Details::UrlEncodeQueryParameter( + forceCloseHandlesOptions.ShareSnapshot.GetValue())); } request.AddHeader(Details::c_HeaderHandleId, forceCloseHandlesOptions.HandleId); request.AddHeader(Details::c_HeaderVersion, forceCloseHandlesOptions.ApiVersionParameter); diff --git a/sdk/storage/azure-storage-files-shares/src/share_client.cpp b/sdk/storage/azure-storage-files-shares/src/share_client.cpp index e4ac472c0..32eb5cd55 100644 --- a/sdk/storage/azure-storage-files-shares/src/share_client.cpp +++ b/sdk/storage/azure-storage-files-shares/src/share_client.cpp @@ -132,11 +132,13 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { ShareClient newClient(*this); if (snapshot.empty()) { - newClient.m_shareUri.RemoveQuery(Details::c_ShareSnapshotQueryParameter); + newClient.m_shareUri.RemoveQueryParameter(Details::c_ShareSnapshotQueryParameter); } else { - newClient.m_shareUri.AppendQuery(Details::c_ShareSnapshotQueryParameter, snapshot); + newClient.m_shareUri.AppendQueryParameter( + Details::c_ShareSnapshotQueryParameter, + Storage::Details::UrlEncodeQueryParameter(snapshot)); } return newClient; } diff --git a/sdk/storage/azure-storage-files-shares/src/share_directory_client.cpp b/sdk/storage/azure-storage-files-shares/src/share_directory_client.cpp index 193cdb946..99d3a7339 100644 --- a/sdk/storage/azure-storage-files-shares/src/share_directory_client.cpp +++ b/sdk/storage/azure-storage-files-shares/src/share_directory_client.cpp @@ -135,12 +135,13 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { DirectoryClient newClient(*this); if (shareSnapshot.empty()) { - newClient.m_shareDirectoryUri.RemoveQuery(Details::c_ShareSnapshotQueryParameter); + newClient.m_shareDirectoryUri.RemoveQueryParameter(Details::c_ShareSnapshotQueryParameter); } else { - newClient.m_shareDirectoryUri.AppendQuery( - Details::c_ShareSnapshotQueryParameter, shareSnapshot); + newClient.m_shareDirectoryUri.AppendQueryParameter( + Details::c_ShareSnapshotQueryParameter, + Storage::Details::UrlEncodeQueryParameter(shareSnapshot)); } return newClient; } diff --git a/sdk/storage/azure-storage-files-shares/src/share_file_client.cpp b/sdk/storage/azure-storage-files-shares/src/share_file_client.cpp index 7abf788d3..3cfa4a328 100644 --- a/sdk/storage/azure-storage-files-shares/src/share_file_client.cpp +++ b/sdk/storage/azure-storage-files-shares/src/share_file_client.cpp @@ -122,11 +122,13 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { FileClient newClient(*this); if (shareSnapshot.empty()) { - newClient.m_shareFileUri.RemoveQuery(Details::c_ShareSnapshotQueryParameter); + newClient.m_shareFileUri.RemoveQueryParameter(Details::c_ShareSnapshotQueryParameter); } else { - newClient.m_shareFileUri.AppendQuery(Details::c_ShareSnapshotQueryParameter, shareSnapshot); + newClient.m_shareFileUri.AppendQueryParameter( + Details::c_ShareSnapshotQueryParameter, + Storage::Details::UrlEncodeQueryParameter(shareSnapshot)); } return newClient; } diff --git a/sdk/storage/azure-storage-files-shares/src/share_sas_builder.cpp b/sdk/storage/azure-storage-files-shares/src/share_sas_builder.cpp index c71bbd5e5..071fdd63b 100644 --- a/sdk/storage/azure-storage-files-shares/src/share_sas_builder.cpp +++ b/sdk/storage/azure-storage-files-shares/src/share_sas_builder.cpp @@ -94,49 +94,49 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { = Base64Encode(Details::HmacSha256(stringToSign, Base64Decode(credential.GetAccountKey()))); Azure::Core::Http::Url builder; - builder.AppendQuery("sv", Version); - builder.AppendQuery("spr", protocol); + builder.AppendQueryParameter("sv", Details::UrlEncodeQueryParameter(Version)); + builder.AppendQueryParameter("spr", Details::UrlEncodeQueryParameter(protocol)); if (StartsOn.HasValue()) { - builder.AppendQuery("st", StartsOn.GetValue()); + builder.AppendQueryParameter("st", Details::UrlEncodeQueryParameter(StartsOn.GetValue())); } if (!ExpiresOn.empty()) { - builder.AppendQuery("se", ExpiresOn); + builder.AppendQueryParameter("se", Details::UrlEncodeQueryParameter(ExpiresOn)); } if (IPRange.HasValue()) { - builder.AppendQuery("sip", IPRange.GetValue()); + builder.AppendQueryParameter("sip", Details::UrlEncodeQueryParameter(IPRange.GetValue())); } if (!Identifier.empty()) { - builder.AppendQuery("si", Identifier); + builder.AppendQueryParameter("si", Details::UrlEncodeQueryParameter(Identifier)); } - builder.AppendQuery("sr", resource); + builder.AppendQueryParameter("sr", Details::UrlEncodeQueryParameter(resource)); if (!Permissions.empty()) { - builder.AppendQuery("sp", Permissions); + builder.AppendQueryParameter("sp", Details::UrlEncodeQueryParameter(Permissions)); } - builder.AppendQuery("sig", signature); + builder.AppendQueryParameter("sig", Details::UrlEncodeQueryParameter(signature)); if (!CacheControl.empty()) { - builder.AppendQuery("rscc", CacheControl); + builder.AppendQueryParameter("rscc", Details::UrlEncodeQueryParameter(CacheControl)); } if (!ContentDisposition.empty()) { - builder.AppendQuery("rscd", ContentDisposition); + builder.AppendQueryParameter("rscd", Details::UrlEncodeQueryParameter(ContentDisposition)); } if (!ContentEncoding.empty()) { - builder.AppendQuery("rsce", ContentEncoding); + builder.AppendQueryParameter("rsce", Details::UrlEncodeQueryParameter(ContentEncoding)); } if (!ContentLanguage.empty()) { - builder.AppendQuery("rscl", ContentLanguage); + builder.AppendQueryParameter("rscl", Details::UrlEncodeQueryParameter(ContentLanguage)); } if (!ContentType.empty()) { - builder.AppendQuery("rsct", ContentType); + builder.AppendQueryParameter("rsct", Details::UrlEncodeQueryParameter(ContentType)); } return builder.GetAbsoluteUrl();