From 63a6daa2af7588f25cede43fd64e27171ae31a6a Mon Sep 17 00:00:00 2001 From: Mikko Karjalainen Date: Fri, 7 Dec 2018 11:50:48 +0000 Subject: [PATCH 1/5] Use Long for a Content-Length header size. --- .../api/src/main/java/com/hotels/styx/api/HttpRequest.java | 4 ++-- .../api/src/main/java/com/hotels/styx/api/HttpResponse.java | 4 ++-- .../src/main/java/com/hotels/styx/api/LiveHttpMessage.java | 4 ++-- .../src/main/java/com/hotels/styx/api/LiveHttpRequest.java | 4 ++-- .../src/main/java/com/hotels/styx/api/LiveHttpResponse.java | 4 ++-- .../interceptors/UnexpectedRequestContentLengthRemover.java | 6 +++--- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/components/api/src/main/java/com/hotels/styx/api/HttpRequest.java b/components/api/src/main/java/com/hotels/styx/api/HttpRequest.java index fee218ec22..1913ad9801 100644 --- a/components/api/src/main/java/com/hotels/styx/api/HttpRequest.java +++ b/components/api/src/main/java/com/hotels/styx/api/HttpRequest.java @@ -45,7 +45,7 @@ import static com.hotels.styx.api.RequestCookie.decode; import static com.hotels.styx.api.RequestCookie.encode; import static io.netty.buffer.Unpooled.copiedBuffer; -import static java.lang.Integer.parseInt; +import static java.lang.Long.parseLong; import static java.util.Arrays.asList; import static java.util.Objects.requireNonNull; import static java.util.UUID.randomUUID; @@ -730,7 +730,7 @@ private Optional requireNotDuplicatedHeader(CharSequence headerName) { private static boolean isInteger(String contentLength) { try { - parseInt(contentLength); + parseLong(contentLength); return true; } catch (NumberFormatException e) { return false; diff --git a/components/api/src/main/java/com/hotels/styx/api/HttpResponse.java b/components/api/src/main/java/com/hotels/styx/api/HttpResponse.java index a5863e795a..fc82b96e9e 100644 --- a/components/api/src/main/java/com/hotels/styx/api/HttpResponse.java +++ b/components/api/src/main/java/com/hotels/styx/api/HttpResponse.java @@ -37,7 +37,7 @@ import static com.hotels.styx.api.ResponseCookie.decode; import static com.hotels.styx.api.ResponseCookie.encode; import static io.netty.buffer.Unpooled.copiedBuffer; -import static java.lang.Integer.parseInt; +import static java.lang.Long.parseLong; import static java.util.Arrays.asList; import static java.util.Objects.requireNonNull; import static java.util.stream.Collectors.toList; @@ -571,7 +571,7 @@ Builder ensureContentLengthIsValid() { private static boolean isInteger(String contentLength) { try { - parseInt(contentLength); + parseLong(contentLength); return true; } catch (NumberFormatException e) { return false; diff --git a/components/api/src/main/java/com/hotels/styx/api/LiveHttpMessage.java b/components/api/src/main/java/com/hotels/styx/api/LiveHttpMessage.java index 6cba013d73..13dd23571e 100644 --- a/components/api/src/main/java/com/hotels/styx/api/LiveHttpMessage.java +++ b/components/api/src/main/java/com/hotels/styx/api/LiveHttpMessage.java @@ -71,8 +71,8 @@ default List headers(CharSequence name) { * * @return the content-length if present */ - default Optional contentLength() { - return header(CONTENT_LENGTH).map(Integer::valueOf); + default Optional contentLength() { + return header(CONTENT_LENGTH).map(Long::valueOf); } /** diff --git a/components/api/src/main/java/com/hotels/styx/api/LiveHttpRequest.java b/components/api/src/main/java/com/hotels/styx/api/LiveHttpRequest.java index 331fb50cf1..3636871b47 100644 --- a/components/api/src/main/java/com/hotels/styx/api/LiveHttpRequest.java +++ b/components/api/src/main/java/com/hotels/styx/api/LiveHttpRequest.java @@ -48,7 +48,7 @@ import static com.hotels.styx.api.RequestCookie.encode; import static io.netty.buffer.ByteBufUtil.getBytes; import static io.netty.buffer.Unpooled.copiedBuffer; -import static java.lang.Integer.parseInt; +import static java.lang.Long.parseLong; import static java.util.Arrays.asList; import static java.util.Objects.requireNonNull; import static java.util.UUID.randomUUID; @@ -1017,7 +1017,7 @@ private Optional requireNotDuplicatedHeader(CharSequence headerName) { private static boolean isInteger(String contentLength) { try { - parseInt(contentLength); + parseLong(contentLength); return true; } catch (NumberFormatException e) { return false; diff --git a/components/api/src/main/java/com/hotels/styx/api/LiveHttpResponse.java b/components/api/src/main/java/com/hotels/styx/api/LiveHttpResponse.java index 6f3abaf609..4da2868a98 100644 --- a/components/api/src/main/java/com/hotels/styx/api/LiveHttpResponse.java +++ b/components/api/src/main/java/com/hotels/styx/api/LiveHttpResponse.java @@ -39,7 +39,7 @@ import static com.hotels.styx.api.ResponseCookie.decode; import static com.hotels.styx.api.ResponseCookie.encode; import static io.netty.buffer.ByteBufUtil.getBytes; -import static java.lang.Integer.parseInt; +import static java.lang.Long.parseLong; import static java.util.Arrays.asList; import static java.util.Objects.requireNonNull; import static java.util.stream.Collectors.toList; @@ -871,7 +871,7 @@ Builder ensureContentLengthIsValid() { private static boolean isInteger(String contentLength) { try { - parseInt(contentLength); + parseLong(contentLength); return true; } catch (NumberFormatException e) { return false; diff --git a/components/proxy/src/main/java/com/hotels/styx/proxy/interceptors/UnexpectedRequestContentLengthRemover.java b/components/proxy/src/main/java/com/hotels/styx/proxy/interceptors/UnexpectedRequestContentLengthRemover.java index a35fe8478d..b4f451d8e0 100644 --- a/components/proxy/src/main/java/com/hotels/styx/proxy/interceptors/UnexpectedRequestContentLengthRemover.java +++ b/components/proxy/src/main/java/com/hotels/styx/proxy/interceptors/UnexpectedRequestContentLengthRemover.java @@ -15,14 +15,14 @@ */ package com.hotels.styx.proxy.interceptors; +import com.hotels.styx.api.Eventual; import com.hotels.styx.api.HttpInterceptor; +import com.hotels.styx.api.LiveHttpRequest; import com.hotels.styx.api.LiveHttpResponse; -import com.hotels.styx.api.Eventual; import java.util.Optional; import static com.hotels.styx.api.HttpHeaderNames.CONTENT_LENGTH; -import com.hotels.styx.api.LiveHttpRequest; /** * Fixes bad content length headers. @@ -34,7 +34,7 @@ public Eventual intercept(LiveHttpRequest request, Chain chain } private static LiveHttpRequest removeBadContentLength(LiveHttpRequest request) { - Optional contentLength = request.contentLength(); + Optional contentLength = request.contentLength(); if (contentLength.isPresent() && request.chunked()) { return request.newBuilder() .removeHeader(CONTENT_LENGTH) From 64f8c743882714ebca840977aa26ef6c39d220fa Mon Sep 17 00:00:00 2001 From: Mikko Karjalainen Date: Mon, 10 Dec 2018 10:00:51 +0000 Subject: [PATCH 2/5] Ensure content length is non-negative number. --- .../src/main/java/com/hotels/styx/api/HttpRequest.java | 8 ++++---- .../src/main/java/com/hotels/styx/api/HttpResponse.java | 8 ++++---- .../test/java/com/hotels/styx/api/HttpRequestTest.java | 7 +++++++ .../test/java/com/hotels/styx/api/HttpResponseTest.java | 7 +++++++ 4 files changed, 22 insertions(+), 8 deletions(-) diff --git a/components/api/src/main/java/com/hotels/styx/api/HttpRequest.java b/components/api/src/main/java/com/hotels/styx/api/HttpRequest.java index 1913ad9801..1d7feacdec 100644 --- a/components/api/src/main/java/com/hotels/styx/api/HttpRequest.java +++ b/components/api/src/main/java/com/hotels/styx/api/HttpRequest.java @@ -716,7 +716,7 @@ private boolean isMethodValid() { private void ensureContentLengthIsValid() { requireNotDuplicatedHeader(CONTENT_LENGTH).ifPresent(contentLength -> - checkArgument(isInteger(contentLength), "Invalid Content-Length found. %s", contentLength) + checkArgument(isPositiveInteger(contentLength), "Invalid Content-Length found. %s", contentLength) ); } @@ -728,10 +728,10 @@ private Optional requireNotDuplicatedHeader(CharSequence headerName) { return headerValues.isEmpty() ? Optional.empty() : Optional.of(headerValues.get(0)); } - private static boolean isInteger(String contentLength) { + private static boolean isPositiveInteger(String contentLength) { try { - parseLong(contentLength); - return true; + long value = parseLong(contentLength); + return value >= 0; } catch (NumberFormatException e) { return false; } diff --git a/components/api/src/main/java/com/hotels/styx/api/HttpResponse.java b/components/api/src/main/java/com/hotels/styx/api/HttpResponse.java index fc82b96e9e..b254d095a9 100644 --- a/components/api/src/main/java/com/hotels/styx/api/HttpResponse.java +++ b/components/api/src/main/java/com/hotels/styx/api/HttpResponse.java @@ -564,15 +564,15 @@ Builder ensureContentLengthIsValid() { checkArgument(contentLengths.size() <= 1, "Duplicate Content-Length found. %s", contentLengths); if (contentLengths.size() == 1) { - checkArgument(isInteger(contentLengths.get(0)), "Invalid Content-Length found. %s", contentLengths.get(0)); + checkArgument(isPositiveInteger(contentLengths.get(0)), "Invalid Content-Length found. %s", contentLengths.get(0)); } return this; } - private static boolean isInteger(String contentLength) { + private static boolean isPositiveInteger(String contentLength) { try { - parseLong(contentLength); - return true; + long value = parseLong(contentLength); + return value >= 0; } catch (NumberFormatException e) { return false; } diff --git a/components/api/src/test/java/com/hotels/styx/api/HttpRequestTest.java b/components/api/src/test/java/com/hotels/styx/api/HttpRequestTest.java index 44b98255be..e506134951 100644 --- a/components/api/src/test/java/com/hotels/styx/api/HttpRequestTest.java +++ b/components/api/src/test/java/com/hotels/styx/api/HttpRequestTest.java @@ -523,4 +523,11 @@ public void removesCookiesInSameBuilder() { assertThat(r1.cookie("x"), isAbsent()); } + + @Test(expectedExceptions = IllegalArgumentException.class, expectedExceptionsMessageRegExp = "Invalid Content-Length found. -3") + public void ensuresContentLengthIsPositive() { + HttpRequest r1 = HttpRequest.post("/y") + .header("Content-Length", -3) + .build(); + } } diff --git a/components/api/src/test/java/com/hotels/styx/api/HttpResponseTest.java b/components/api/src/test/java/com/hotels/styx/api/HttpResponseTest.java index 088faa031d..1f42fac447 100644 --- a/components/api/src/test/java/com/hotels/styx/api/HttpResponseTest.java +++ b/components/api/src/test/java/com/hotels/styx/api/HttpResponseTest.java @@ -521,4 +521,11 @@ public void removesCookiesInSameBuilder() { assertThat(r1.cookie("x"), isAbsent()); } + + @Test(expectedExceptions = IllegalArgumentException.class, expectedExceptionsMessageRegExp = "Invalid Content-Length found. -3") + public void ensuresContentLengthIsPositive() { + HttpResponse r1 = HttpResponse.response() + .header("Content-Length", -3) + .build(); + } } \ No newline at end of file From f74588b0b001f54525dc9b156cece4e8f1b462c2 Mon Sep 17 00:00:00 2001 From: Mikko Karjalainen Date: Tue, 11 Dec 2018 12:35:04 +0000 Subject: [PATCH 3/5] Ensure content length is non-negative number: LiveHttpRequest/Response. --- .../main/java/com/hotels/styx/api/LiveHttpRequest.java | 8 ++++---- .../main/java/com/hotels/styx/api/LiveHttpResponse.java | 4 ++-- .../test/java/com/hotels/styx/api/HttpRequestTest.java | 2 +- .../test/java/com/hotels/styx/api/HttpResponseTest.java | 2 +- .../java/com/hotels/styx/api/LiveHttpRequestTest.java | 7 +++++++ .../java/com/hotels/styx/api/LiveHttpResponseTest.java | 7 +++++++ 6 files changed, 22 insertions(+), 8 deletions(-) diff --git a/components/api/src/main/java/com/hotels/styx/api/LiveHttpRequest.java b/components/api/src/main/java/com/hotels/styx/api/LiveHttpRequest.java index 3636871b47..eaab62ee38 100644 --- a/components/api/src/main/java/com/hotels/styx/api/LiveHttpRequest.java +++ b/components/api/src/main/java/com/hotels/styx/api/LiveHttpRequest.java @@ -1003,7 +1003,7 @@ private boolean isMethodValid() { private void ensureContentLengthIsValid() { requireNotDuplicatedHeader(CONTENT_LENGTH).ifPresent(contentLength -> - checkArgument(isInteger(contentLength), "Invalid Content-Length found. %s", contentLength) + checkArgument(isPositiveInteger(contentLength), "Invalid Content-Length found. %s", contentLength) ); } @@ -1015,10 +1015,10 @@ private Optional requireNotDuplicatedHeader(CharSequence headerName) { return headerValues.isEmpty() ? Optional.empty() : Optional.of(headerValues.get(0)); } - private static boolean isInteger(String contentLength) { + private static boolean isPositiveInteger(String contentLength) { try { - parseLong(contentLength); - return true; + long value = parseLong(contentLength); + return value >= 0; } catch (NumberFormatException e) { return false; } diff --git a/components/api/src/main/java/com/hotels/styx/api/LiveHttpResponse.java b/components/api/src/main/java/com/hotels/styx/api/LiveHttpResponse.java index 4da2868a98..35f49c7d82 100644 --- a/components/api/src/main/java/com/hotels/styx/api/LiveHttpResponse.java +++ b/components/api/src/main/java/com/hotels/styx/api/LiveHttpResponse.java @@ -871,8 +871,8 @@ Builder ensureContentLengthIsValid() { private static boolean isInteger(String contentLength) { try { - parseLong(contentLength); - return true; + long value = parseLong(contentLength); + return value >= 0; } catch (NumberFormatException e) { return false; } diff --git a/components/api/src/test/java/com/hotels/styx/api/HttpRequestTest.java b/components/api/src/test/java/com/hotels/styx/api/HttpRequestTest.java index e506134951..f8a4a1ae28 100644 --- a/components/api/src/test/java/com/hotels/styx/api/HttpRequestTest.java +++ b/components/api/src/test/java/com/hotels/styx/api/HttpRequestTest.java @@ -526,7 +526,7 @@ public void removesCookiesInSameBuilder() { @Test(expectedExceptions = IllegalArgumentException.class, expectedExceptionsMessageRegExp = "Invalid Content-Length found. -3") public void ensuresContentLengthIsPositive() { - HttpRequest r1 = HttpRequest.post("/y") + HttpRequest.post("/y") .header("Content-Length", -3) .build(); } diff --git a/components/api/src/test/java/com/hotels/styx/api/HttpResponseTest.java b/components/api/src/test/java/com/hotels/styx/api/HttpResponseTest.java index 1f42fac447..c8d9686249 100644 --- a/components/api/src/test/java/com/hotels/styx/api/HttpResponseTest.java +++ b/components/api/src/test/java/com/hotels/styx/api/HttpResponseTest.java @@ -524,7 +524,7 @@ public void removesCookiesInSameBuilder() { @Test(expectedExceptions = IllegalArgumentException.class, expectedExceptionsMessageRegExp = "Invalid Content-Length found. -3") public void ensuresContentLengthIsPositive() { - HttpResponse r1 = HttpResponse.response() + response() .header("Content-Length", -3) .build(); } diff --git a/components/api/src/test/java/com/hotels/styx/api/LiveHttpRequestTest.java b/components/api/src/test/java/com/hotels/styx/api/LiveHttpRequestTest.java index 09d579202b..7a381fc76c 100644 --- a/components/api/src/test/java/com/hotels/styx/api/LiveHttpRequestTest.java +++ b/components/api/src/test/java/com/hotels/styx/api/LiveHttpRequestTest.java @@ -560,6 +560,13 @@ public void transformsByRemovingCookieList() { assertEquals(request.cookie("cookie"), Optional.empty()); } + @Test(expectedExceptions = IllegalArgumentException.class, expectedExceptionsMessageRegExp = "Invalid Content-Length found. -3") + public void ensuresContentLengthIsPositive() { + LiveHttpRequest.post("/y") + .header("Content-Length", -3) + .build(); + } + private static ByteStream body(String... contents) { return new ByteStream( diff --git a/components/api/src/test/java/com/hotels/styx/api/LiveHttpResponseTest.java b/components/api/src/test/java/com/hotels/styx/api/LiveHttpResponseTest.java index cb72ccecc0..23f5d03050 100644 --- a/components/api/src/test/java/com/hotels/styx/api/LiveHttpResponseTest.java +++ b/components/api/src/test/java/com/hotels/styx/api/LiveHttpResponseTest.java @@ -488,6 +488,13 @@ public void transformerReplacesBody() { assertEquals(buf2.delegate().refCnt(), 0); } + @Test(expectedExceptions = IllegalArgumentException.class, expectedExceptionsMessageRegExp = "Invalid Content-Length found. -3") + public void ensuresContentLengthIsPositive() { + response(OK) + .header("Content-Length", -3) + .build(); + } + private static LiveHttpResponse.Builder response() { return LiveHttpResponse.response(); } From 01378a490d58ce5b44a4794620136e15cdc460aa Mon Sep 17 00:00:00 2001 From: Mikko Karjalainen Date: Tue, 11 Dec 2018 15:14:40 +0000 Subject: [PATCH 4/5] Address code review comments. --- .../api/src/main/java/com/hotels/styx/api/HttpRequest.java | 4 ++-- .../api/src/main/java/com/hotels/styx/api/HttpResponse.java | 4 ++-- .../src/main/java/com/hotels/styx/api/LiveHttpRequest.java | 4 ++-- .../src/main/java/com/hotels/styx/api/LiveHttpResponse.java | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/components/api/src/main/java/com/hotels/styx/api/HttpRequest.java b/components/api/src/main/java/com/hotels/styx/api/HttpRequest.java index 1d7feacdec..e8943708d2 100644 --- a/components/api/src/main/java/com/hotels/styx/api/HttpRequest.java +++ b/components/api/src/main/java/com/hotels/styx/api/HttpRequest.java @@ -716,7 +716,7 @@ private boolean isMethodValid() { private void ensureContentLengthIsValid() { requireNotDuplicatedHeader(CONTENT_LENGTH).ifPresent(contentLength -> - checkArgument(isPositiveInteger(contentLength), "Invalid Content-Length found. %s", contentLength) + checkArgument(isNonNegativeInteger(contentLength), "Invalid Content-Length found. %s", contentLength) ); } @@ -728,7 +728,7 @@ private Optional requireNotDuplicatedHeader(CharSequence headerName) { return headerValues.isEmpty() ? Optional.empty() : Optional.of(headerValues.get(0)); } - private static boolean isPositiveInteger(String contentLength) { + private static boolean isNonNegativeInteger(String contentLength) { try { long value = parseLong(contentLength); return value >= 0; diff --git a/components/api/src/main/java/com/hotels/styx/api/HttpResponse.java b/components/api/src/main/java/com/hotels/styx/api/HttpResponse.java index b254d095a9..fd17ac49ae 100644 --- a/components/api/src/main/java/com/hotels/styx/api/HttpResponse.java +++ b/components/api/src/main/java/com/hotels/styx/api/HttpResponse.java @@ -564,12 +564,12 @@ Builder ensureContentLengthIsValid() { checkArgument(contentLengths.size() <= 1, "Duplicate Content-Length found. %s", contentLengths); if (contentLengths.size() == 1) { - checkArgument(isPositiveInteger(contentLengths.get(0)), "Invalid Content-Length found. %s", contentLengths.get(0)); + checkArgument(isNonNegativeInteger(contentLengths.get(0)), "Invalid Content-Length found. %s", contentLengths.get(0)); } return this; } - private static boolean isPositiveInteger(String contentLength) { + private static boolean isNonNegativeInteger(String contentLength) { try { long value = parseLong(contentLength); return value >= 0; diff --git a/components/api/src/main/java/com/hotels/styx/api/LiveHttpRequest.java b/components/api/src/main/java/com/hotels/styx/api/LiveHttpRequest.java index eaab62ee38..cadc0783cd 100644 --- a/components/api/src/main/java/com/hotels/styx/api/LiveHttpRequest.java +++ b/components/api/src/main/java/com/hotels/styx/api/LiveHttpRequest.java @@ -1003,7 +1003,7 @@ private boolean isMethodValid() { private void ensureContentLengthIsValid() { requireNotDuplicatedHeader(CONTENT_LENGTH).ifPresent(contentLength -> - checkArgument(isPositiveInteger(contentLength), "Invalid Content-Length found. %s", contentLength) + checkArgument(isNonNegativeInteger(contentLength), "Invalid Content-Length found. %s", contentLength) ); } @@ -1015,7 +1015,7 @@ private Optional requireNotDuplicatedHeader(CharSequence headerName) { return headerValues.isEmpty() ? Optional.empty() : Optional.of(headerValues.get(0)); } - private static boolean isPositiveInteger(String contentLength) { + private static boolean isNonNegativeInteger(String contentLength) { try { long value = parseLong(contentLength); return value >= 0; diff --git a/components/api/src/main/java/com/hotels/styx/api/LiveHttpResponse.java b/components/api/src/main/java/com/hotels/styx/api/LiveHttpResponse.java index 35f49c7d82..63c4de0825 100644 --- a/components/api/src/main/java/com/hotels/styx/api/LiveHttpResponse.java +++ b/components/api/src/main/java/com/hotels/styx/api/LiveHttpResponse.java @@ -864,12 +864,12 @@ Builder ensureContentLengthIsValid() { checkArgument(contentLengths.size() <= 1, "Duplicate Content-Length found. %s", contentLengths); if (contentLengths.size() == 1) { - checkArgument(isInteger(contentLengths.get(0)), "Invalid Content-Length found. %s", contentLengths.get(0)); + checkArgument(isNonNegativeInteger(contentLengths.get(0)), "Invalid Content-Length found. %s", contentLengths.get(0)); } return this; } - private static boolean isInteger(String contentLength) { + private static boolean isNonNegativeInteger(String contentLength) { try { long value = parseLong(contentLength); return value >= 0; From 52da9a567505d62da2370bee10d5c5c9e5597f31 Mon Sep 17 00:00:00 2001 From: Mikko Karjalainen Date: Mon, 17 Dec 2018 08:52:08 +0000 Subject: [PATCH 5/5] Change HttpMessage.contentLength. --- .../api/src/main/java/com/hotels/styx/api/HttpMessage.java | 4 ++-- .../styx/common/http/handler/StaticBodyHttpHandlerTest.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/components/api/src/main/java/com/hotels/styx/api/HttpMessage.java b/components/api/src/main/java/com/hotels/styx/api/HttpMessage.java index ce55a8ff83..a39527f10c 100644 --- a/components/api/src/main/java/com/hotels/styx/api/HttpMessage.java +++ b/components/api/src/main/java/com/hotels/styx/api/HttpMessage.java @@ -84,8 +84,8 @@ default List headers(CharSequence name) { * * @return the content-length if present */ - default Optional contentLength() { - return header(CONTENT_LENGTH).map(Integer::valueOf); + default Optional contentLength() { + return header(CONTENT_LENGTH).map(Long::valueOf); } /** diff --git a/components/common/src/test/java/com/hotels/styx/common/http/handler/StaticBodyHttpHandlerTest.java b/components/common/src/test/java/com/hotels/styx/common/http/handler/StaticBodyHttpHandlerTest.java index 12e6bd4fa6..e5ce061942 100644 --- a/components/common/src/test/java/com/hotels/styx/common/http/handler/StaticBodyHttpHandlerTest.java +++ b/components/common/src/test/java/com/hotels/styx/common/http/handler/StaticBodyHttpHandlerTest.java @@ -44,8 +44,8 @@ public void respondsWithStaticBody() { assertThat(fullResponse.bodyAs(UTF_8), is("foo")); } - private Integer length(String string) { - return string.getBytes().length; + private Long length(String string) { + return (long) string.getBytes().length; } }