-
Notifications
You must be signed in to change notification settings - Fork 300
Enabling baggage cache to support limits and non-ascii characters #8713
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
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -45,7 +45,7 @@ public BaggagePropagator(boolean injectBaggage, boolean extractBaggage) { | |
public <C> void inject(Context context, C carrier, CarrierSetter<C> setter) { | ||
int maxItems = this.config.getTraceBaggageMaxItems(); | ||
int maxBytes = this.config.getTraceBaggageMaxBytes(); | ||
//noinspection ConstantValue | ||
// noinspection ConstantValue | ||
if (!this.injectBaggage | ||
|| maxItems == 0 | ||
|| maxBytes == 0 | ||
|
@@ -108,7 +108,8 @@ public <C> Context extract(Context context, C carrier, CarrierVisitor<C> visitor | |
if (!this.extractBaggage || context == null || carrier == null || visitor == null) { | ||
return context; | ||
} | ||
BaggageExtractor baggageExtractor = new BaggageExtractor(); | ||
BaggageExtractor baggageExtractor = | ||
new BaggageExtractor(config.getTraceBaggageMaxItems(), config.getTraceBaggageMaxBytes()); | ||
visitor.forEachKeyValue(carrier, baggageExtractor); | ||
return baggageExtractor.extracted == null ? context : context.with(baggageExtractor.extracted); | ||
} | ||
|
@@ -117,8 +118,15 @@ private static class BaggageExtractor implements BiConsumer<String, String> { | |
private static final char KEY_VALUE_SEPARATOR = '='; | ||
private static final char PAIR_SEPARATOR = ','; | ||
private Baggage extracted; | ||
|
||
private BaggageExtractor() {} | ||
private final int maxItems; | ||
private final int maxBytes; | ||
private String w3cHeader; | ||
|
||
private BaggageExtractor(int maxItems, int maxBytes) { | ||
this.maxItems = maxItems; | ||
this.maxBytes = maxBytes; | ||
this.w3cHeader = null; | ||
} | ||
|
||
/** URL decode value */ | ||
private String decode(final String value) { | ||
|
@@ -134,6 +142,7 @@ private String decode(final String value) { | |
private Map<String, String> parseBaggageHeaders(String input) { | ||
Map<String, String> baggage = new HashMap<>(); | ||
int start = 0; | ||
boolean truncatedCache = false; | ||
int pairSeparatorInd = input.indexOf(PAIR_SEPARATOR); | ||
pairSeparatorInd = pairSeparatorInd == -1 ? input.length() : pairSeparatorInd; | ||
int kvSeparatorInd = input.indexOf(KEY_VALUE_SEPARATOR); | ||
|
@@ -152,11 +161,29 @@ private Map<String, String> parseBaggageHeaders(String input) { | |
} | ||
baggage.put(key, value); | ||
|
||
// need to percent-encode non-ascii headers we pass down | ||
if (UTF_ESCAPER.keyNeedsEncoding(key) || UTF_ESCAPER.valNeedsEncoding(value)) { | ||
truncatedCache = true; | ||
this.w3cHeader = null; | ||
} else if (!truncatedCache && (end > this.maxBytes || baggage.size() > this.maxItems)) { | ||
if(start == 0) { // if we go out of range after first k/v pair, there is no cache | ||
this.w3cHeader = null; | ||
} else{ | ||
this.w3cHeader = input.substring(0, start - 1); // -1 to ignore the k/v separator | ||
} | ||
truncatedCache = true; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You should |
||
} | ||
|
||
kvSeparatorInd = input.indexOf(KEY_VALUE_SEPARATOR, pairSeparatorInd + 1); | ||
pairSeparatorInd = input.indexOf(PAIR_SEPARATOR, pairSeparatorInd + 1); | ||
pairSeparatorInd = pairSeparatorInd == -1 ? input.length() : pairSeparatorInd; | ||
start = end + 1; | ||
} | ||
|
||
if (!truncatedCache) { | ||
this.w3cHeader = input; | ||
} | ||
|
||
return baggage; | ||
} | ||
|
||
|
@@ -166,7 +193,7 @@ public void accept(String key, String value) { | |
if (BAGGAGE_KEY.equalsIgnoreCase(key)) { | ||
Map<String, String> baggage = parseBaggageHeaders(value); | ||
if (!baggage.isEmpty()) { | ||
this.extracted = Baggage.create(baggage, value); | ||
this.extracted = Baggage.create(baggage, this.w3cHeader); | ||
} | ||
} | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -115,12 +115,41 @@ public Escaped escapeValue(String s) { | |
return escape(s, unsafeValOctets); | ||
} | ||
|
||
public boolean needsEncoding(char c, boolean[] unsafeOctets) { | ||
if (c > '~' || c <= ' ' || c < unsafeOctets.length && unsafeOctets[c]) { | ||
return true; | ||
} | ||
return false; | ||
} | ||
|
||
public boolean keyNeedsEncoding(String key) { | ||
int slen = key.length(); | ||
for (int index = 0; index < slen; index++) { | ||
char c = key.charAt(index); | ||
if (needsEncoding(c, unsafeKeyOctets)) { | ||
return true; | ||
} | ||
} | ||
return false; | ||
} | ||
|
||
public boolean valNeedsEncoding(String val) { | ||
Comment on lines
+125
to
+136
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I included both of these to avoid checking which unsafe characters to use for each string we decode. Let me know if that is preferred for code-conciseness There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No that’s good 👍 |
||
int slen = val.length(); | ||
for (int index = 0; index < slen; index++) { | ||
char c = val.charAt(index); | ||
if (needsEncoding(c, unsafeValOctets)) { | ||
return true; | ||
} | ||
} | ||
return false; | ||
} | ||
|
||
/** Escape the provided String, using percent-style URL Encoding. */ | ||
public Escaped escape(String s, boolean[] unsafeOctets) { | ||
int slen = s.length(); | ||
for (int index = 0; index < slen; index++) { | ||
char c = s.charAt(index); | ||
if (c > '~' || c <= ' ' || c <= unsafeOctets.length && unsafeOctets[c]) { | ||
if (needsEncoding(c, unsafeOctets)) { | ||
return escapeSlow(s, index, unsafeOctets); | ||
} | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It’s not strictly truncated, it’s invalid in this case as non ascii characters are not allowed in HTTP headers. I though the RFC asked to drop the header and not parse it if it was invalid.
From RFC encoding:
From RFC error handling: