Repository: jenkinsci/jenkins
File: test/src/test/java/hudson/console/ConsoleAnnotatorTest.java (Java)

Code before:

        String consoleAnnotator;
        String start;
        private Page p;

        ProgressiveLogClient(JenkinsRule.WebClient wc, Run r, boolean streaming) {
            this.wc = wc;
            this.run = r;
            this.streaming = streaming;
        }

        String next() throws IOException {
            WebRequest req = new WebRequest(new URL(r.getURL() + run.getUrl() + "/logText/progressiveHtml" + (start != null ? "?start=" + start : "")));
            req.setEncodingType(null);
            Map<String, String> headers = new HashMap<>();
            if (consoleAnnotator != null)
                headers.put("X-ConsoleAnnotator", consoleAnnotator);
            if (streaming) headers.put("Accept", "multipart/form-data");
            req.setAdditionalHeaders(headers);

            p = wc.getPage(req);
            String content;
            if (streaming) {
                var ct = p.getWebResponse().getResponseHeaderValue("Content-Type");
                assertTrue(ct.matches("^multipart/form-data;boundary=[a-f0-9-]{36};charset=utf-8$"));
                var boundary = ct.substring(29, 29+36).getBytes();
                var mp = new MultipartInput.Builder()
                        .setBoundary(boundary)
                        .setInputStream(p.getWebResponse().getContentAsStream())
                        .get();
                var text = new ByteArrayOutputStream();
                mp.skipPreamble();
                assertEquals("Content-Disposition: form-data;name=text\r\nContent-Type: text/html;charset=utf-8\r\n\r\n", mp.readHeaders());
                mp.readBodyData(text);

                var metaBAOS = new ByteArrayOutputStream();
                mp.readBoundary();
                assertEquals("Content-Disposition: form-data;name=meta\r\nContent-Type: application/json;charset=utf-8\r\n\r\n", mp.readHeaders());
                mp.readBodyData(metaBAOS);

                content = text.toString();
                var meta = JSONObject.fromObject(metaBAOS.toString());
                consoleAnnotator = meta.getString("consoleAnnotator");
                start = meta.getString("end");
            } else {
                content = p.getWebResponse().getContentAsString();
                consoleAnnotator = p.getWebResponse().getResponseHeaderValue("X-ConsoleAnnotator");
                start = p.getWebResponse().getResponseHeaderValue("X-Text-Size");
            }
            return content;
        }

Review comment (suggestion):
```suggestion
                var boundary = ct.substring(29, 29 + 36).getBytes();
```

Code after:

        String consoleAnnotator;
        String start;
        private Page p;

        ProgressiveLogClient(JenkinsRule.WebClient wc, Run r, boolean streaming) {
            this.wc = wc;
            this.run = r;
            this.streaming = streaming;
        }

        String next() throws IOException {
            WebRequest req = new WebRequest(new URL(r.getURL() + run.getUrl() + "/logText/progressiveHtml" + (start != null ? "?start=" + start : "")));
            req.setEncodingType(null);
            Map<String, String> headers = new HashMap<>();
            if (consoleAnnotator != null)
                headers.put("X-ConsoleAnnotator", consoleAnnotator);
            if (streaming) headers.put("Accept", "multipart/form-data");
            req.setAdditionalHeaders(headers);

            p = wc.getPage(req);
            String content;
            if (streaming) {
                var ct = p.getWebResponse().getResponseHeaderValue("Content-Type");
                assertTrue(ct.matches("^multipart/form-data;boundary=[a-f0-9-]{36};charset=utf-8$"));
                var boundary = ct.substring(29, 29 + 36).getBytes();
                var mp = new MultipartInput.Builder()
                        .setBoundary(boundary)
                        .setInputStream(p.getWebResponse().getContentAsStream())
                        .get();
                var text = new ByteArrayOutputStream();
                mp.skipPreamble();
                assertEquals("Content-Disposition: form-data;name=text\r\nContent-Type: text/html;charset=utf-8\r\n\r\n", mp.readHeaders());
                mp.readBodyData(text);

                var metaBAOS = new ByteArrayOutputStream();
                mp.readBoundary();
                assertEquals("Content-Disposition: form-data;name=meta\r\nContent-Type: application/json;charset=utf-8\r\n\r\n", mp.readHeaders());
                mp.readBodyData(metaBAOS);

                content = text.toString();
                var meta = JSONObject.fromObject(metaBAOS.toString());
                consoleAnnotator = meta.getString("consoleAnnotator");
                start = meta.getString("end");
            } else {
                content = p.getWebResponse().getContentAsString();
                consoleAnnotator = p.getWebResponse().getResponseHeaderValue("X-ConsoleAnnotator");
                start = p.getWebResponse().getResponseHeaderValue("X-Text-Size");
            }
            return content;
        }