private int appendLastBoundaryDeliminator(byte[] output, int destPos) { byte[] slice = (NEW_LINE + rangePartHeaderSerializer.serializeLastBoundaryDeliminator(BOUNDARY)) .getBytes(StandardCharsets.UTF_8); System.arraycopy(slice, 0, output, destPos, slice.length); return slice.length; } }
private void doServeRangePartHeader(final OutputStream outputStream, final String boundary, final String contentType, final long totalLength, final Range range) throws IOException { RangePartHeader rangePartHeader = new RangePartHeader(range, boundary, contentType, totalLength); byte[] rangePartHeaderBytes = rangePartHeaderSerializer.serialize(rangePartHeader).getBytes(StandardCharsets.UTF_8); serveMultiRangeStream(new ByteArrayInputStream(rangePartHeaderBytes), outputStream); }
String partHeader = serialize(new RangePartHeader(new Range(0L, 0L), boundary, contentType, 0L)); int partHeaderWithoutDigits = partHeader.length() - RANGE_DIGITS_LENGTH; partHeadersLength += serializeLastBoundaryDeliminator(boundary).length();
public ServiceContainer(final ServerConfig serverConfig) { HeadersParser headersParser = new HeadersParser(); requestWrapperFactory = new HttpServletRequestImplFactory(headersParser, new QueryStringParser(), new RequestStatusParser(), new CookieParser(), new MultipartHeadersPartParser(headersParser), serverConfig.getTempPath() ); responseFactory = new HttpServletResponseImplFactory( new HeadersSerializer(), new CookieHeaderSerializer(new DateProvider()), new StreamHelper( new RangeHelper(), new RangePartHeaderSerializer() ) ); threadPoolExecutor = new ThreadPoolExecutor(1, serverConfig.getMaxServerThreads(), DEFAULT_TIME_UNITS, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(serverConfig.getMaxServerThreads() * MAX_THREADS_MULTIPLIER), Executors.defaultThreadFactory(), new ServiceUnavailableHandler(responseFactory) ); httpErrorHandlerResolver = new HttpErrorHandlerResolverImpl(serverConfig); pathHelper = new PathHelper(); }
private ResourceProvider getAssetsResourceProvider(final MimeTypeMapping mimeTypeMapping) { String assetBasePath = "public"; if (context != null) { AssetManager assetManager = ((Context) context).getResources().getAssets(); return new AssetResourceProvider(assetManager, assetBasePath); } else { return new FileResourceProvider(new RangeParser(), new RangeHelper(), new RangePartHeaderSerializer(), mimeTypeMapping, "./app/src/main/assets/" + assetBasePath); } } }
@Test public void shouldReturnLengthForMultipleRanges() { Range range = new Range(333L, 1234L); String boundary = "BBBOOUUNNNDDAARRYY"; String contentType = "application/pdf"; long totalLength = 12345L; RangePartHeader rangePartHeader = new RangePartHeader(range, boundary, contentType, totalLength); String serialized = rangePartHeaderSerializer.serialize(rangePartHeader); long serializedLength = serialized.length(); long computedLength = rangePartHeaderSerializer.getPartHeadersLength(Arrays.asList(range, range), boundary, contentType, totalLength); long firstLineLength = "\r\n".length(); long lastLineLength = ("\r\n--" + boundary + "--\r\n\r\n").length(); assertThat(computedLength, is(firstLineLength + 2 * serializedLength + lastLineLength)); } }
@Test public void shouldReturnLengthForASingeRange() { Range range = new Range(333L, 1234L); String boundary = "BBBOOUUNNNDDAARRYY"; String contentType = "application/pdf"; long totalLength = 12345L; long computedLength = rangePartHeaderSerializer.getPartHeadersLength(Collections.singletonList(range), boundary, contentType, totalLength); assertThat(computedLength, is(0L)); }
@Test public void shouldSerializeCookieWithAllAttributes() { Cookie cookie = new Cookie("name", "value"); cookie.setDomain("example.com"); cookie.setMaxAge(20); cookie.setSecure(true); cookie.setHttpOnly(true); cookie.setPath("/somepath"); cookie.setComment("Some Comment"); String serializedCookie = cookieHeaderSerializer.serialize(cookie); String[] serializedCookieParts = getCookieParts(serializedCookie); assertThat(serializedCookie, startsWith("name=value")); assertThat(serializedCookie, containsString("Expires")); assertThat(getExpiresValue(serializedCookie), endsWith("GMT")); // Pseudo date validation assertThat(serializedCookieParts, hasItemInArray("Domain=example.com")); assertThat(serializedCookieParts, hasItemInArray("Path=/somepath")); assertThat(serializedCookieParts, hasItemInArray("HttpOnly")); assertThat(serializedCookieParts, hasItemInArray("Secure")); assertThat(serializedCookieParts, hasItemInArray("Comment=Some Comment")); }
@Test public void shouldSerializeExpiresBasedOnMaxAge() { int maxAgeSeconds = 35; Cookie cookie = new Cookie("name", "value"); cookie.setMaxAge(maxAgeSeconds); String serializedCookie = cookieHeaderSerializer.serialize(cookie); Date date = new Date(System.currentTimeMillis() + Long.valueOf(maxAgeSeconds) * 1000l); String expiresValue = DateUtilities.dateFormat(date); assertThat(getExpiresValue(serializedCookie), is(expiresValue)); }
@Before public void setUp() { Date now = new Date(); dateProvider = mock(DateProvider.class); when(dateProvider.now()).thenReturn(now); cookieHeaderSerializer = new CookieHeaderSerializer(dateProvider); }
@Test public void shouldSerializeCookieWithNoAttributes() { Cookie cookie = new Cookie("name", "value"); String serializedCookie = cookieHeaderSerializer.serialize(cookie); assertThat(serializedCookie, is("name=value")); }
.append("Expires") .append(EQUALS) .append(getExpires(cookie.getMaxAge()));
private FileResourceProvider getFileResourceProvider(final ServerConfig serverConfig) { return new FileResourceProvider(new RangeParser(), new RangeHelper(), new RangePartHeaderSerializer(), serverConfig.getMimeTypeMapping(), serverConfig.getDocumentRootPath()); }
private int appendRangePartHeader(byte[] output, int destPos, Range range) { RangePartHeader rangePartHeader = new RangePartHeader(range, BOUNDARY, CONTENT_TYPE, TOTAL_LENGTH); byte[] slice = (NEW_LINE + rangePartHeaderSerializer.serialize(rangePartHeader)) .getBytes(StandardCharsets.UTF_8); System.arraycopy(slice, 0, output, destPos, slice.length); return slice.length; }
public byte[] getSliceForRanges(byte[] input, List<Range> ranges) { long totalLength = rangeHelper.getTotalLength(ranges); long headersPartLength = rangePartHeaderSerializer.getPartHeadersLength(ranges, BOUNDARY, CONTENT_TYPE, TOTAL_LENGTH); byte[] output = new byte[(int) (totalLength + headersPartLength)]; random.nextBytes(output); int destPos = 0; for (Range range : ranges) { if (ranges.size() > 1) { destPos += appendRangePartHeader(output, destPos, range); } destPos += appendRangeSlice(input, output, destPos, range); } if (ranges.size() > 1) { appendLastBoundaryDeliminator(output, destPos); } return output; }
/** * Serves multiple ranges of the input stream to the output stream. * * @param inputStream * @param outputStream * @param rangeList * @param boundary * @param contentType * @param totalLength * @throws IOException */ public void serveMultiRangeStream(final InputStream inputStream, final OutputStream outputStream, final List<Range> rangeList, final String boundary, final String contentType, final long totalLength) throws IOException { inputStream.mark(0); serveMultiRangeStream(new ByteArrayInputStream(NEW_LINE.getBytes(StandardCharsets.UTF_8)), outputStream); for (Range range : rangeList) { doServeRangePartHeader(outputStream, boundary, contentType, totalLength, range); doServeRangeStream(inputStream, outputStream, range); serveMultiRangeStream(new ByteArrayInputStream(NEW_LINE.getBytes(StandardCharsets.UTF_8)), outputStream); } serveMultiRangeStream(new ByteArrayInputStream(rangePartHeaderSerializer .serializeLastBoundaryDeliminator(boundary).getBytes(StandardCharsets.UTF_8)), outputStream); }
@Test public void shouldSerializeCookieWithUrlEncode() { String value = "= &"; Cookie cookie = new Cookie("name", value); String serializedCookie = cookieHeaderSerializer.serialize(cookie); assertThat(serializedCookie, is("name=" + StringUtilities.urlEncode(value))); }
@Before public void setUp() { outputStream = new ByteArrayOutputStream(); response = new HttpServletResponseImpl( mock(Serializer.class), mock(Serializer.class), new StreamHelper(new RangeHelper(), new RangePartHeaderSerializer()), outputStream); }
@Test public void shouldSerializeRangeProperly() { Range range = new Range(333L, 1234L); String boundary = "BBBOOUUNNNDDAARRYY"; String contentType = "application/pdf"; long totalLength = 12345L; RangePartHeader rangePartHeader = new RangePartHeader(range, boundary, contentType, totalLength); String serialized = rangePartHeaderSerializer.serialize(rangePartHeader); assertThat(serialized, startsWith("--" + boundary + "\r\n")); assertThat(serialized, endsWith("\r\n\r\n")); assertThat(serialized, containsString("\r\nContent-Type: " + contentType + "\r\n")); assertThat(serialized, containsString("\r\nContent-Range: bytes 333-1234/12345\r\n")); }
} else { boundary = StringUtilities.generateRandom(); response.setContentLength(rangePartHeaderSerializer.getPartHeadersLength(ranges, boundary, contentType, file.length()) + rangeLength);