@@ -17,6 +17,16 @@ void AWSSigV4Signer::sign(HttpRequestBase<T>& request) {
1717 // Autorization
1818 const std::string hash_algo = " AWS4-HMAC-SHA256" ;
1919
20+ // Compute payload hash and set header ONLY for body requests
21+ std::string payload_hash;
22+ if constexpr (std::is_same_v<T, HttpBodyRequest>) {
23+ const std::string& body = static_cast <HttpBodyRequest&>(request).getBody ();
24+ payload_hash = hex (sha256 (body));
25+ request.header (" x-amz-content-sha256" , payload_hash);
26+ } else {
27+ payload_hash = " e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" ;
28+ }
29+
2030 // Compute date and add it as a header
2131 const std::string timestamp = this ->getTimestamp ();
2232 request.header (" X-Amz-Date" , timestamp);
@@ -39,7 +49,7 @@ void AWSSigV4Signer::sign(HttpRequestBase<T>& request) {
3949 }
4050
4151 // Cannonical request
42- std::string hex_cannonical_request = hex (sha256 (createCannonicalRequest (request)));
52+ std::string hex_cannonical_request = hex (sha256 (createCannonicalRequest (request, payload_hash )));
4353
4454 // To sign
4555 std::string string_to_sign = std::format (" {}\n {}\n {}\n {}" , hash_algo, timestamp, credential_scope, hex_cannonical_request);
@@ -50,7 +60,7 @@ void AWSSigV4Signer::sign(HttpRequestBase<T>& request) {
5060}
5161
5262template <typename T>
53- std::string AWSSigV4Signer::createCannonicalRequest (HttpRequestBase<T>& request) {
63+ std::string AWSSigV4Signer::createCannonicalRequest (HttpRequestBase<T>& request, const std::string& payload_hash ) {
5464 const std::string http_verb = request.getHttpMethodStr (request.getHttpMethod ());
5565 std::string url = request.getURL ();
5666
@@ -93,34 +103,29 @@ std::string AWSSigV4Signer::createCannonicalRequest(HttpRequestBase<T>& request)
93103 }
94104
95105 // Canonical Headers + SignedHeaders
96- const std::map<std::string, std::string> headers = request.getHeaders ();
106+ const std::map<std::string, std::string, LowerCaseCompare > headers = request.getHeaders ();
97107 std::string cheaders = " " ;
98108 std::string signed_headers = " " ;
99109 uint_fast16_t i = 0 ;
100110 for (const auto & header : headers) {
101111 std::string kHeader = header.first ;
102- std::transform (kHeader .begin (), kHeader .end (), kHeader .begin (),
103- ::tolower);
112+ std::transform (kHeader .begin (), kHeader .end (), kHeader .begin (), ::tolower);
104113 if (i > 0 )
105114 signed_headers += " ;" ;
106115 signed_headers += kHeader ;
107116 cheaders += kHeader + " :" + header.second + " \n " ;
108117 i++;
109118 }
110119
111- std::string payload_hash;
112- if constexpr (std::is_same_v<T, HttpBodyRequest>) {
113- const std::string& body = static_cast <HttpBodyRequest&>(request).getBody ();
114- payload_hash = hex (sha256 (body));
115- } else {
116- payload_hash = " e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" ;
117- }
118-
119- // The x-amz-content-sha256 header is required for Amazon S3 AWS requests. It provides a hash of the request payload. If there is no payload, you must provide the hash of an empty string.
120- request.header (" x-amz-content-sha256" , payload_hash);
120+ std::string canonical_request = std::format (" {}\n {}\n {}\n {}\n {}\n {}" ,
121+ http_verb,
122+ cannonical_uri,
123+ query_str,
124+ cheaders,
125+ signed_headers,
126+ payload_hash);
121127
122- return std::format (" {}\n {}\n {}\n {}\n {}\n {}" , http_verb, cannonical_uri, query_str,
123- cheaders, signed_headers, payload_hash);
128+ return canonical_request;
124129}
125130
126131const unsigned char * AWSSigV4Signer::sha256 (const std::string& str) {
@@ -194,5 +199,5 @@ const unsigned char* AWSSigV4Signer::deriveSigningKey(const std::string request_
194199// Why are we still here? Just to suffer?
195200template void AWSSigV4Signer::sign<HttpRequest>(HttpRequestBase<HttpRequest>&);
196201template void AWSSigV4Signer::sign<HttpBodyRequest>(HttpRequestBase<HttpBodyRequest>&);
197- template std::string AWSSigV4Signer::createCannonicalRequest<HttpRequest>(HttpRequestBase<HttpRequest>&);
198- template std::string AWSSigV4Signer::createCannonicalRequest<HttpBodyRequest>(HttpRequestBase<HttpBodyRequest>&);
202+ template std::string AWSSigV4Signer::createCannonicalRequest<HttpRequest>(HttpRequestBase<HttpRequest>&, const std::string& );
203+ template std::string AWSSigV4Signer::createCannonicalRequest<HttpBodyRequest>(HttpRequestBase<HttpBodyRequest>&, const std::string& );
0 commit comments