|
22 | 22 | import co.elastic.clients.elasticsearch._types.ErrorResponse;
|
23 | 23 | import co.elastic.clients.json.JsonpDeserializer;
|
24 | 24 | import co.elastic.clients.transport.Endpoint;
|
25 |
| -import org.apache.http.client.utils.URLEncodedUtils; |
26 | 25 |
|
27 | 26 | import javax.annotation.Nullable;
|
| 27 | +import java.nio.ByteBuffer; |
| 28 | +import java.nio.charset.StandardCharsets; |
| 29 | +import java.util.BitSet; |
28 | 30 | import java.util.Collections;
|
29 | 31 | import java.util.Map;
|
30 | 32 | import java.util.function.Function;
|
@@ -145,8 +147,54 @@ public static RuntimeException noPathTemplateFound(String what) {
|
145 | 147 | "Please check the API documentation, or raise an issue if this should be a valid request.");
|
146 | 148 | }
|
147 | 149 |
|
148 |
| - public static void pathEncode(String src, StringBuilder dest) { |
149 |
| - // TODO: avoid dependency on HttpClient here (and use something more efficient) |
150 |
| - dest.append(URLEncodedUtils.formatSegments(src).substring(1)); |
| 150 | + private static final BitSet PATH_SAFE; |
| 151 | + private static final char[] HEX_CHARS; |
| 152 | + |
| 153 | + static { |
| 154 | + PATH_SAFE = new BitSet(256); |
| 155 | + // From RFC 3986 |
| 156 | + // unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" |
| 157 | + PATH_SAFE.set('a', 'z'+1); |
| 158 | + PATH_SAFE.set('A', 'Z'+1); |
| 159 | + PATH_SAFE.set('0', '9'+1); |
| 160 | + PATH_SAFE.set('-'); |
| 161 | + PATH_SAFE.set('.'); |
| 162 | + PATH_SAFE.set('_'); |
| 163 | + PATH_SAFE.set('~'); |
| 164 | + |
| 165 | + // sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "=" |
| 166 | + PATH_SAFE.set('!'); |
| 167 | + PATH_SAFE.set('$'); |
| 168 | + PATH_SAFE.set('&'); |
| 169 | + PATH_SAFE.set('\''); |
| 170 | + PATH_SAFE.set('('); |
| 171 | + PATH_SAFE.set(')'); |
| 172 | + PATH_SAFE.set('*'); |
| 173 | + PATH_SAFE.set('+'); |
| 174 | + PATH_SAFE.set(','); |
| 175 | + PATH_SAFE.set(';'); |
| 176 | + PATH_SAFE.set('='); |
| 177 | + |
| 178 | + // pchar = unreserved / pct-encoded / sub-delims / ":" / "@" |
| 179 | + PATH_SAFE.set(':'); |
| 180 | + PATH_SAFE.set('@'); |
| 181 | + |
| 182 | + HEX_CHARS = "0123456789ABCDEF".toCharArray(); |
| 183 | + } |
| 184 | + |
| 185 | + public static void pathEncode(final String src, StringBuilder dest) { |
| 186 | + final ByteBuffer buf = StandardCharsets.UTF_8.encode(src); |
| 187 | + // In UTF-8 multibyte encoding, all bytes have the high bit set. This means we can iterate |
| 188 | + // on all bytes and percent-encode without having to care about code point context. |
| 189 | + while (buf.hasRemaining()) { |
| 190 | + int b = buf.get() & 0xff; |
| 191 | + if (PATH_SAFE.get(b)) { |
| 192 | + dest.append((char) b); |
| 193 | + } else { |
| 194 | + dest.append("%"); |
| 195 | + dest.append(HEX_CHARS[b >> 4 & 0xF]); |
| 196 | + dest.append(HEX_CHARS[b & 0xF]); |
| 197 | + } |
| 198 | + } |
151 | 199 | }
|
152 | 200 | }
|
0 commit comments