|
50 | 50 | import java.io.InputStreamReader;
|
51 | 51 | import java.io.OutputStream;
|
52 | 52 | import java.io.Reader;
|
53 |
| -import java.io.UnsupportedEncodingException; |
| 53 | +import java.io.SequenceInputStream; |
| 54 | +import java.io.StringReader; |
54 | 55 | import java.net.URLDecoder;
|
55 | 56 | import java.nio.charset.StandardCharsets;
|
56 | 57 | import java.util.Collection;
|
@@ -143,11 +144,7 @@ private static boolean includeRequestHeader(String headerName) {
|
143 | 144 | }
|
144 | 145 |
|
145 | 146 | private static String urlDecode(String input) {
|
146 |
| - try { |
147 |
| - return URLDecoder.decode(input, "UTF-8"); |
148 |
| - } catch (UnsupportedEncodingException e) { |
149 |
| - throw new SafeUncheckedIoException("Failed to decode path segment", e, UnsafeArg.of("encoded", input)); |
150 |
| - } |
| 147 | + return URLDecoder.decode(input, StandardCharsets.UTF_8); |
151 | 148 | }
|
152 | 149 |
|
153 | 150 | private static Optional<RequestBody> requestBody(Request request) {
|
@@ -239,7 +236,32 @@ public InputStream asInputStream() {
|
239 | 236 |
|
240 | 237 | @Override
|
241 | 238 | public Reader asReader() {
|
242 |
| - return new InputStreamReader(asInputStream(), StandardCharsets.UTF_8); |
| 239 | + InputStream inputStream = asInputStream(); |
| 240 | + Integer maybeLength = length(); |
| 241 | + if (maybeLength != null) { |
| 242 | + int length = maybeLength; |
| 243 | + if (length < 8192) { |
| 244 | + // Avoid InputStreamReader / HeapByteBuffer overhead for small (less than 8KiB) inputs, |
| 245 | + // see https://github.com/FasterXML/jackson-core/pull/1081 |
| 246 | + // try to read an extra byte to determine if more bytes were provided than actual content-length |
| 247 | + int toRead = length + 1; |
| 248 | + byte[] bytes = new byte[toRead]; |
| 249 | + try { |
| 250 | + int read = inputStream.readNBytes(bytes, 0, toRead); |
| 251 | + if (read <= length) { |
| 252 | + // fully read input |
| 253 | + inputStream.close(); |
| 254 | + return new StringReader(new String(bytes, 0, read, StandardCharsets.UTF_8)); |
| 255 | + } |
| 256 | + // input was larger than provided content length, fallback to stream path |
| 257 | + inputStream = new SequenceInputStream(new ByteArrayInputStream(bytes), inputStream); |
| 258 | + } catch (IOException e) { |
| 259 | + throw new SafeUncheckedIoException( |
| 260 | + "Failed to read response body", e, SafeArg.of("length", maybeLength)); |
| 261 | + } |
| 262 | + } |
| 263 | + } |
| 264 | + return new InputStreamReader(inputStream, StandardCharsets.UTF_8); |
243 | 265 | }
|
244 | 266 |
|
245 | 267 | @Override
|
|
0 commit comments