13
13
import java .util .Collections ;
14
14
import java .util .HashMap ;
15
15
import java .util .HashSet ;
16
- import java .util .List ;
17
16
import java .util .Map ;
18
17
import java .util .Set ;
19
18
import java .util .function .Supplier ;
@@ -26,10 +25,14 @@ class BaggageHttpCodec {
26
25
27
26
static final String BAGGAGE_KEY = "baggage" ;
28
27
private static final int MAX_CHARACTER_SIZE = 4 ;
29
- private static final List <Character > UNSAFE_CHARACTERS =
30
- Arrays .asList (
31
- '\"' , ',' , ';' , '\\' , '(' , ')' , '/' , ':' , '<' , '=' , '>' , '?' , '@' , '[' , ']' , '{' , '}' );
32
- private static final Set <Character > UNSAFE_CHARACTERS_SET = new HashSet <>(UNSAFE_CHARACTERS );
28
+
29
+ private static final Set <Character > UNSAFE_CHARACTERS_KEY =
30
+ new HashSet <>(
31
+ Arrays .asList (
32
+ '\"' , ',' , ';' , '\\' , '(' , ')' , '/' , ':' , '<' , '=' , '>' , '?' , '@' , '[' , ']' , '{' ,
33
+ '}' ));
34
+ private static final Set <Character > UNSAFE_CHARACTERS_VALUE =
35
+ new HashSet <>(Arrays .asList ('\"' , ',' , ';' , '\\' ));
33
36
34
37
private BaggageHttpCodec () {
35
38
// This class should not be created. This also makes code coverage checks happy.
@@ -48,20 +51,32 @@ public Injector(Map<String, String> invertedBaggageMapping) {
48
51
this .invertedBaggageMapping = invertedBaggageMapping ;
49
52
}
50
53
51
- private void encodeKey (String key , StringBuilder buffer ) {
52
- for (int i = 0 ; i < key .length (); i ++) {
53
- char c = key .charAt (i );
54
- if (UNSAFE_CHARACTERS_SET .contains (c ) || c > 126 || c <= 20 ) { // encode character
54
+ private int encodeKey (String key , StringBuilder builder ) {
55
+ return encode (key , builder , UNSAFE_CHARACTERS_KEY );
56
+ }
57
+
58
+ private int encodeValue (String key , StringBuilder builder ) {
59
+ return encode (key , builder , UNSAFE_CHARACTERS_VALUE );
60
+ }
61
+
62
+ private int encode (String input , StringBuilder builder , Set <Character > UNSAFE_CHARACTERS ) {
63
+ int size = 0 ;
64
+ for (int i = 0 ; i < input .length (); i ++) {
65
+ char c = input .charAt (i );
66
+ if (UNSAFE_CHARACTERS .contains (c ) || c > 126 || c <= 32 ) { // encode character
55
67
byte [] bytes =
56
68
Character .toString (c )
57
69
.getBytes (StandardCharsets .UTF_8 ); // not most efficient but what URLEncoder does
58
70
for (byte b : bytes ) {
59
- buffer .append (String .format ("%%%02X" , b & 0xFF ));
71
+ builder .append (String .format ("%%%02X" , b & 0xFF ));
72
+ size += 1 ;
60
73
}
61
74
} else {
62
- buffer .append (c );
75
+ builder .append (c );
76
+ size += 1 ;
63
77
}
64
78
}
79
+ return size ;
65
80
}
66
81
67
82
@ Override
@@ -84,36 +99,22 @@ public <C> void inject(
84
99
if (processedBaggage != 0 ) {
85
100
additionalCharacters = 2 ; // allocating space for comma
86
101
}
87
- int currentPairSize =
88
- entry .getKey ().length () + entry .getValue ().length () + additionalCharacters ;
89
-
90
- // worst case check
91
- if (currentCharacters + currentPairSize <= maxSafeCharacters ) {
92
- currentCharacters += currentPairSize ;
93
- } else {
94
- if (currentBytes
95
- == 0 ) { // special case to calculate byte size after surpassing worst-case number of
96
- // characters
97
- currentBytes = baggageText .toString ().getBytes (StandardCharsets .UTF_8 ).length ;
98
- }
99
- int byteSize =
100
- entry .getKey ().getBytes (StandardCharsets .UTF_8 ).length
101
- + entry .getValue ().getBytes (StandardCharsets .UTF_8 ).length
102
- + additionalCharacters ; // find largest possible byte size for UTF encoded
103
- // characters and only do
104
- // size checking after we hit this worst case scenario
105
- if (byteSize + currentBytes > maxBytes ) {
106
- break ;
107
- }
108
- currentBytes += byteSize ;
109
- }
110
102
103
+ int byteSize = 1 ; // default include size of '='
111
104
if (additionalCharacters == 2 ) {
112
105
baggageText .append (',' );
106
+ byteSize += 1 ;
113
107
}
114
108
115
- encodeKey (entry .getKey (), baggageText );
116
- baggageText .append ('=' ).append (HttpCodec .encodeBaggage (entry .getValue ()));
109
+ byteSize += encodeKey (entry .getKey (), baggageText );
110
+ baggageText .append ('=' );
111
+ byteSize += encodeValue (entry .getValue (), baggageText );
112
+
113
+ if (currentBytes + byteSize > maxBytes ) {
114
+ baggageText .setLength (currentBytes );
115
+ break ;
116
+ }
117
+ currentBytes += byteSize ;
117
118
processedBaggage ++;
118
119
}
119
120
0 commit comments