Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Trim extra spaces in metadata for canonicalized request #278

Merged
merged 1 commit into from
Jan 24, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions Minio.Examples/Cases/PutObject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/

using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using Minio.DataModel;
Expand Down Expand Up @@ -47,11 +48,16 @@ public async static Task Run(Minio.MinioClient minio,
{
Console.Out.WriteLine("Running example for API: PutObjectAsync with Stream and MultiPartUpload");
}
var metaData = new Dictionary<string, string>()
{
{"X-Amz-Meta-Test", "Test Test"}
};
await minio.PutObjectAsync(bucketName,
objectName,
filestream,
filestream.Length,
"application/octet-stream",
metaData: metaData,
sse:sse);
}

Expand Down
6 changes: 3 additions & 3 deletions Minio.Functional.Tests/FunctionalTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -565,7 +565,7 @@ private async static Task PutObject_Test4(MinioClient minio)
string fileName = CreateFile(1 * MB, dataFile1MB);
string contentType = "custom/contenttype";
Dictionary<string, string> metaData = new Dictionary<string, string>(){
{ "x-amz-meta-customheader", "minio-dotnet"}
{ "x-amz-meta-customheader", "minio dotnet"}
};
Dictionary<string,string> args = new Dictionary<string,string>
{
Expand Down Expand Up @@ -1408,7 +1408,7 @@ private async static Task CopyObject_Test8(MinioClient minio)
{
await minio.PutObjectAsync(bucketName,
objectName,
filestream, filestream.Length, metaData:new Dictionary<string,string>{{"X-Amz-Meta-Orig", "orig-val"}});
filestream, filestream.Length, metaData:new Dictionary<string,string>{{"X-Amz-Meta-Orig", "orig-val with spaces"}});
}
ObjectStat stats = await minio.StatObjectAsync(bucketName, objectName);
Assert.IsTrue(stats.metaData["X-Amz-Meta-Orig"] != null);
Expand All @@ -1420,7 +1420,7 @@ await minio.PutObjectAsync(bucketName,
Dictionary<string,string> metadata = new Dictionary<string,string>()
{
{ "Content-Type", "application/css"},
{"X-Amz-Meta-Mynewkey","my-new-value"}
{"X-Amz-Meta-Mynewkey","test test"}
};
await minio.CopyObjectAsync(bucketName, objectName, destBucketName, destObjectName,copyConditions:copyCond,metadata: metadata);

Expand Down
11 changes: 11 additions & 0 deletions Minio/Helper/s3utils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,15 @@
using System;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
namespace Minio.Helper
{
internal class s3utils
{

internal static readonly Regex TrimWhitespaceRegex = new Regex("\\s+");

internal static bool IsAmazonEndPoint(string endpoint)
{
if (IsAmazonChinaEndPoint(endpoint))
Expand Down Expand Up @@ -93,5 +97,12 @@ internal static bool IsValidIP(string ip)

return splitValues.All(r => byte.TryParse(r, out tempForParsing));
}

// TrimAll trims leading and trailing spaces and replace sequential spaces with one space, following Trimall()
// in http://docs.aws.amazon.com/general/latest/gr/sigv4-create-canonical-request.html
internal static string TrimAll(string s)
{
return TrimWhitespaceRegex.Replace(s, " ").Trim();
}
}
}
4 changes: 2 additions & 2 deletions Minio/V4Authenticator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,7 @@ private string GetPresignCanonicalRequest(IRestClient client, IRestRequest reque
path = "/" + path;
}
canonicalStringList.AddLast(path);
String query = headersToSign.Aggregate(requestQuery, (pv, cv) => $"{pv}&{utils.UrlEncode(cv.Key)}={utils.UrlEncode(cv.Value)}");
String query = headersToSign.Aggregate(requestQuery, (pv, cv) => $"{pv}&{utils.UrlEncode(cv.Key)}={utils.UrlEncode(s3utils.TrimAll(cv.Value))}");
canonicalStringList.AddLast(query);
if (client.BaseUrl.Port > 0 && (client.BaseUrl.Port != 80 && client.BaseUrl.Port != 443))
{
Expand Down Expand Up @@ -409,7 +409,7 @@ private string GetCanonicalRequest(IRestRequest request,

foreach (string header in headersToSign.Keys)
{
canonicalStringList.AddLast(header + ":" + headersToSign[header]);
canonicalStringList.AddLast(header + ":" + s3utils.TrimAll(headersToSign[header]));
}
canonicalStringList.AddLast("");
canonicalStringList.AddLast(string.Join(";", headersToSign.Keys));
Expand Down