@@ -161,7 +161,7 @@ public void handle(final HttpExchange exchange) throws IOException {
161161 // Batch https://cloud.google.com/storage/docs/json_api/v1/how-tos/batch
162162 final String uri = "/storage/v1/b/" + bucket + "/o/" ;
163163 final StringBuilder batch = new StringBuilder ();
164- for (String line : Streams .readAllLines (new BufferedInputStream ( wrappedRequest ) )) {
164+ for (String line : Streams .readAllLines (wrappedRequest )) {
165165 if (line .length () == 0 || line .startsWith ("--" ) || line .toLowerCase (Locale .ROOT ).startsWith ("content" )) {
166166 batch .append (line ).append ('\n' );
167167 } else if (line .startsWith ("DELETE" )) {
@@ -226,8 +226,13 @@ public void handle(final HttpExchange exchange) throws IOException {
226226 final int start = getContentRangeStart (range );
227227 final int end = getContentRangeEnd (range );
228228
229- final ByteArrayOutputStream out = new ByteArrayOutputStream ();
230- long bytesRead = Streams .copy (wrappedRequest , out );
229+ final ByteArrayOutputStream out = new ByteArrayOutputStream () {
230+ @ Override
231+ public byte [] toByteArray () {
232+ return buf ;
233+ }
234+ };
235+ long bytesRead = Streams .copy (wrappedRequest , out , new byte [128 ]);
231236 int length = Math .max (end + 1 , limit != null ? limit : 0 );
232237 if ((int ) bytesRead > length ) {
233238 throw new AssertionError ("Requesting more bytes than available for blob" );
@@ -267,56 +272,62 @@ private String httpServerUrl(final HttpExchange exchange) {
267272 return "http://" + InetAddresses .toUriString (address .getAddress ()) + ":" + address .getPort ();
268273 }
269274
275+ private static final Pattern NAME_PATTERN = Pattern .compile ("\" name\" :\" ([^\" ]*)\" " );
276+
270277 public static Optional <Tuple <String , BytesArray >> parseMultipartRequestBody (final InputStream requestBody ) throws IOException {
271278 Tuple <String , BytesArray > content = null ;
272279 try (BufferedInputStream in = new BufferedInputStream (new GZIPInputStream (requestBody ))) {
273280 String name = null ;
274281 int read ;
282+ ByteArrayOutputStream out = new ByteArrayOutputStream () {
283+ @ Override
284+ public byte [] toByteArray () {
285+ return buf ;
286+ }
287+ };
275288 while ((read = in .read ()) != -1 ) {
289+ out .reset ();
276290 boolean markAndContinue = false ;
277- try (ByteArrayOutputStream out = new ByteArrayOutputStream ()) {
278- do { // search next consecutive {carriage return, new line} chars and stop
279- if ((char ) read == '\r' ) {
280- int next = in .read ();
281- if (next != -1 ) {
282- if (next == '\n' ) {
283- break ;
284- }
285- out .write (read );
286- out .write (next );
287- continue ;
291+ do { // search next consecutive {carriage return, new line} chars and stop
292+ if ((char ) read == '\r' ) {
293+ int next = in .read ();
294+ if (next != -1 ) {
295+ if (next == '\n' ) {
296+ break ;
288297 }
289- }
290- out .write (read );
291- } while ((read = in .read ()) != -1 );
292-
293- final String line = new String (out .toByteArray (), UTF_8 );
294- if (line .length () == 0 || line .equals ("\r \n " ) || line .startsWith ("--" )
295- || line .toLowerCase (Locale .ROOT ).startsWith ("content" )) {
296- markAndContinue = true ;
297- } else if (line .startsWith ("{\" bucket\" :" )) {
298- markAndContinue = true ;
299- Matcher matcher = Pattern .compile ("\" name\" :\" ([^\" ]*)\" " ).matcher (line );
300- if (matcher .find ()) {
301- name = matcher .group (1 );
298+ out .write (read );
299+ out .write (next );
300+ continue ;
302301 }
303302 }
304- if (markAndContinue ) {
305- in .mark (Integer .MAX_VALUE );
306- continue ;
303+ out .write (read );
304+ } while ((read = in .read ()) != -1 );
305+ final String bucketPrefix = "{\" bucket\" :" ;
306+ final String start = new String (out .toByteArray (), 0 , Math .min (out .size (), bucketPrefix .length ()), UTF_8 );
307+ if (start .length () == 0 || start .equals ("\r \n " ) || start .startsWith ("--" )
308+ || start .toLowerCase (Locale .ROOT ).startsWith ("content" )) {
309+ markAndContinue = true ;
310+ } else if (start .startsWith (bucketPrefix )) {
311+ markAndContinue = true ;
312+ final String line = new String (out .toByteArray (), bucketPrefix .length (), out .size () - bucketPrefix .length (), UTF_8 );
313+ Matcher matcher = NAME_PATTERN .matcher (line );
314+ if (matcher .find ()) {
315+ name = matcher .group (1 );
307316 }
308317 }
318+ if (markAndContinue ) {
319+ in .mark (Integer .MAX_VALUE );
320+ continue ;
321+ }
309322 if (name != null ) {
310323 in .reset ();
311- try (ByteArrayOutputStream binary = new ByteArrayOutputStream ()) {
312- while ((read = in .read ()) != -1 ) {
313- binary .write (read );
314- }
315- binary .flush ();
316- byte [] tmp = binary .toByteArray ();
317- // removes the trailing end "\r\n--__END_OF_PART__--\r\n" which is 23 bytes long
318- content = Tuple .tuple (name , new BytesArray (Arrays .copyOf (tmp , tmp .length - 23 )));
324+ out .reset ();
325+ while ((read = in .read ()) != -1 ) {
326+ out .write (read );
319327 }
328+ // removes the trailing end "\r\n--__END_OF_PART__--\r\n" which is 23 bytes long
329+ content = Tuple .tuple (name , new BytesArray (Arrays .copyOf (out .toByteArray (), out .size () - 23 )));
330+ break ;
320331 }
321332 }
322333 }
0 commit comments