Preserve client order of activity baggage items (#26302) (#26395)

Co-authored-by: Andrey Tretyak <andreyt@microsoft.com>
This commit is contained in:
Sourabh Shirhatti 2020-10-05 14:29:39 -07:00 committed by GitHub
parent a3767eedb0
commit fda7d1d660
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 43 additions and 6 deletions

View File

@ -267,14 +267,14 @@ namespace Microsoft.AspNetCore.Hosting
// We expect baggage to be empty by default
// Only very advanced users will be using it in near future, we encourage them to keep baggage small (few items)
string[] baggage = headers.GetCommaSeparatedValues(HeaderNames.CorrelationContext);
if (baggage.Length > 0)
// AddBaggage adds items at the beginning of the list, so we need to add them in reverse to keep the same order as the client
// An order could be important if baggage has two items with the same key (that is allowed by the contract)
for (var i = baggage.Length - 1; i >= 0; i--)
{
foreach (var item in baggage)
if (NameValueHeaderValue.TryParse(baggage[i], out var baggageItem))
{
if (NameValueHeaderValue.TryParse(item, out var baggageItem))
{
activity.AddBaggage(baggageItem.Name.ToString(), HttpUtility.UrlDecode(baggageItem.Value.ToString()));
}
activity.AddBaggage(baggageItem.Name.ToString(), HttpUtility.UrlDecode(baggageItem.Value.ToString()));
}
}
}

View File

@ -301,6 +301,43 @@ namespace Microsoft.AspNetCore.Hosting.Tests
Assert.Contains(Activity.Current.Baggage, pair => pair.Key == "Key2" && pair.Value == "value2");
}
[Fact]
public void ActivityBaggagePreservesItemsOrder()
{
var diagnosticListener = new DiagnosticListener("DummySource");
var hostingApplication = CreateApplication(out var features, diagnosticListener: diagnosticListener);
diagnosticListener.Subscribe(new CallbackDiagnosticListener(pair => { }),
s =>
{
if (s.StartsWith("Microsoft.AspNetCore.Hosting.HttpRequestIn"))
{
return true;
}
return false;
});
features.Set<IHttpRequestFeature>(new HttpRequestFeature()
{
Headers = new HeaderDictionary()
{
{"Request-Id", "ParentId1"},
{"Correlation-Context", "Key1=value1, Key2=value2, Key1=value3"} // duplicated keys allowed by the contract
}
});
hostingApplication.CreateContext(features);
Assert.Equal("Microsoft.AspNetCore.Hosting.HttpRequestIn", Activity.Current.OperationName);
var expectedBaggage = new []
{
KeyValuePair.Create("Key1","value1"),
KeyValuePair.Create("Key2","value2"),
KeyValuePair.Create("Key1","value3")
};
Assert.Equal(expectedBaggage, Activity.Current.Baggage);
}
[Fact]
public void ActivityBaggageValuesAreUrlDecodedFromHeaders()
{