diff --git a/config/checkstyle/checkstyle.xml b/config/checkstyle/checkstyle.xml
deleted file mode 100644
index 3dc3e16..0000000
--- a/config/checkstyle/checkstyle.xml
+++ /dev/null
@@ -1,323 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/gradle.properties b/gradle.properties
index cc9dda8..6e7bda7 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -1,6 +1,6 @@
group = org.xbib
name = netty-http
-version = 4.1.36.7
+version = 4.1.36.8
# main packages
netty.version = 4.1.36.Final
@@ -18,14 +18,13 @@ reactivestreams.version = 1.0.2
# rest
xbib-guice.version = 4.0.4
-# xmlrpc-client
-commons-httpclient.version = 3.1
-
# test packages
junit.version = 5.4.2
junit4.version = 4.12
conscrypt.version = 2.0.0
-jackson.version = 2.8.11.1
+jackson.version = 2.9.9
+
+# doc
asciidoclet.version = 1.5.4
org.gradle.warning.mode = all
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index c157b6f..128e8c2 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
-#Mon Apr 22 17:45:04 CEST 2019
+#Tue Aug 06 15:30:36 CEST 2019
+distributionUrl=https\://services.gradle.org/distributions/gradle-5.3.1-all.zip
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-5.3-all.zip
+zipStoreBase=GRADLE_USER_HOME
diff --git a/netty-http-client/src/main/java/org/xbib/netty/http/client/Client.java b/netty-http-client/src/main/java/org/xbib/netty/http/client/Client.java
index abd2699..9bfe22c 100644
--- a/netty-http-client/src/main/java/org/xbib/netty/http/client/Client.java
+++ b/netty-http-client/src/main/java/org/xbib/netty/http/client/Client.java
@@ -34,7 +34,7 @@ import org.xbib.netty.http.client.transport.HttpTransport;
import org.xbib.netty.http.client.transport.Transport;
import org.xbib.netty.http.common.HttpAddress;
import org.xbib.netty.http.common.NetworkUtils;
-import org.xbib.netty.http.common.SecurityUtil;
+import org.xbib.netty.http.common.security.SecurityUtil;
import javax.net.ssl.SNIHostName;
import javax.net.ssl.SNIServerName;
diff --git a/netty-http-client/src/main/java/org/xbib/netty/http/client/ClientConfig.java b/netty-http-client/src/main/java/org/xbib/netty/http/client/ClientConfig.java
index 4be2491..c3f5c10 100644
--- a/netty-http-client/src/main/java/org/xbib/netty/http/client/ClientConfig.java
+++ b/netty-http-client/src/main/java/org/xbib/netty/http/client/ClientConfig.java
@@ -10,7 +10,7 @@ import io.netty.handler.ssl.CipherSuiteFilter;
import io.netty.handler.ssl.SslProvider;
import org.xbib.netty.http.client.retry.BackOff;
import org.xbib.netty.http.common.HttpAddress;
-import org.xbib.netty.http.common.SecurityUtil;
+import org.xbib.netty.http.common.security.SecurityUtil;
import javax.net.ssl.TrustManagerFactory;
import java.io.InputStream;
diff --git a/netty-http-client/src/main/java/org/xbib/netty/http/client/cookie/ClientCookieDecoder.java b/netty-http-client/src/main/java/org/xbib/netty/http/client/cookie/ClientCookieDecoder.java
index 2fc7ebc..e8882b6 100644
--- a/netty-http-client/src/main/java/org/xbib/netty/http/client/cookie/ClientCookieDecoder.java
+++ b/netty-http-client/src/main/java/org/xbib/netty/http/client/cookie/ClientCookieDecoder.java
@@ -4,7 +4,8 @@ import org.xbib.netty.http.common.cookie.Cookie;
import org.xbib.netty.http.common.cookie.CookieDecoder;
import org.xbib.netty.http.common.cookie.CookieHeaderNames;
import org.xbib.netty.http.common.cookie.DefaultCookie;
-import org.xbib.netty.http.common.util.DateTimeUtils;
+import org.xbib.netty.http.common.cookie.SameSite;
+import org.xbib.netty.http.common.util.DateTimeUtil;
import java.time.Instant;
import java.util.Locale;
@@ -42,7 +43,7 @@ public final class ClientCookieDecoder extends CookieDecoder {
public Cookie decode(String header) {
final int headerLen = Objects.requireNonNull(header, "header").length();
if (headerLen == 0) {
- return null;
+ throw new IllegalArgumentException("header length is 0");
}
CookieBuilder cookieBuilder = null;
int i = 0;
@@ -116,7 +117,10 @@ public final class ClientCookieDecoder extends CookieDecoder {
}
}
}
- return cookieBuilder != null ? cookieBuilder.cookie() : null;
+ if (cookieBuilder == null) {
+ throw new IllegalArgumentException("no cookie found");
+ }
+ return cookieBuilder.cookie();
}
private static class CookieBuilder {
@@ -139,7 +143,7 @@ public final class ClientCookieDecoder extends CookieDecoder {
private boolean httpOnly;
- private Cookie.SameSite sameSite = Cookie.SameSite.STRICT;
+ private SameSite sameSite = SameSite.STRICT;
CookieBuilder(DefaultCookie cookie, String header) {
this.cookie = cookie;
@@ -208,7 +212,7 @@ public final class ClientCookieDecoder extends CookieDecoder {
if (maxAge != Long.MIN_VALUE) {
return maxAge;
} else if (isValueDefined(expiresStart, expiresEnd)) {
- Instant expiresDate = DateTimeUtils.parseDate(header, expiresStart, expiresEnd);
+ Instant expiresDate = DateTimeUtil.parseDate(header, expiresStart, expiresEnd);
if (expiresDate != null) {
Instant now = Instant.now();
long maxAgeMillis = expiresDate.toEpochMilli() - now.toEpochMilli();
@@ -233,7 +237,7 @@ public final class ClientCookieDecoder extends CookieDecoder {
} else if (header.regionMatches(true, nameStart, CookieHeaderNames.SAMESITE, 0, 8)) {
String string = computeValue(valueStart, valueEnd);
if (string != null) {
- setSameSite(Cookie.SameSite.valueOf(string.toUpperCase(Locale.ROOT)));
+ setSameSite(SameSite.valueOf(string.toUpperCase(Locale.ROOT)));
}
}
}
@@ -246,7 +250,7 @@ public final class ClientCookieDecoder extends CookieDecoder {
return isValueDefined(valueStart, valueEnd) ? header.substring(valueStart, valueEnd) : null;
}
- private void setSameSite(Cookie.SameSite value) {
+ private void setSameSite(SameSite value) {
sameSite = value;
}
}
diff --git a/netty-http-client/src/test/java/org/xbib/netty/http/client/test/cookie/ClientCookieDecoderTest.java b/netty-http-client/src/test/java/org/xbib/netty/http/client/test/cookie/ClientCookieDecoderTest.java
index 2c359ab..9ea09e3 100644
--- a/netty-http-client/src/test/java/org/xbib/netty/http/client/test/cookie/ClientCookieDecoderTest.java
+++ b/netty-http-client/src/test/java/org/xbib/netty/http/client/test/cookie/ClientCookieDecoderTest.java
@@ -3,7 +3,8 @@ package org.xbib.netty.http.client.test.cookie;
import org.junit.jupiter.api.Test;
import org.xbib.netty.http.client.cookie.ClientCookieDecoder;
import org.xbib.netty.http.common.cookie.Cookie;
-import org.xbib.netty.http.common.util.DateTimeUtils;
+import org.xbib.netty.http.common.cookie.SameSite;
+import org.xbib.netty.http.common.util.DateTimeUtil;
import java.time.ZoneId;
import java.time.ZonedDateTime;
@@ -24,7 +25,7 @@ class ClientCookieDecoderTest {
void testDecodingSingleCookieV0() {
long millis = System.currentTimeMillis() + 50000;
String cookieString = "myCookie=myValue;expires=" +
- DateTimeUtils.formatMillis(millis) +
+ DateTimeUtil.formatMillis(millis) +
";path=/apathsomewhere;domain=.adomainsomewhere;secure;";
Cookie cookie = ClientCookieDecoder.STRICT.decode(cookieString);
assertNotNull(cookie);
@@ -55,8 +56,8 @@ class ClientCookieDecoderTest {
String cookieString = "myCookie=myValue;max-age=50;path=/apathsomewhere;domain=.adomainsomewhere" +
";secure;comment=this is a comment;version=1;";
Cookie cookie = ClientCookieDecoder.STRICT.decode(cookieString);
- assertEquals("myValue", cookie.value());
assertNotNull(cookie);
+ assertEquals("myValue", cookie.value());
assertEquals(".adomainsomewhere", cookie.domain());
assertEquals(50, cookie.maxAge());
assertEquals("/apathsomewhere", cookie.path());
@@ -134,6 +135,7 @@ class ClientCookieDecoderTest {
"__utmz=48461872.1258140131.1.1.utmcsr=overstock.com|utmccn=(referral)|" +
"utmcmd=referral|utmcct=/Home-Garden/Furniture/Clearance,/clearance,/32/dept.html";
Cookie cookie = ClientCookieDecoder.STRICT.decode(source);
+ assertNotNull(cookie);
assertEquals("ARPT", cookie.name());
assertEquals("LWUKQPSWRTUN04CKKJI", cookie.value());
}
@@ -144,6 +146,7 @@ class ClientCookieDecoderTest {
long expectedMaxAge = ((zonedDateTime.toEpochSecond() * 1000L) - System.currentTimeMillis()) / 1000;
String source = "Format=EU; expires=Fri, 31-Dec-2100 23:59:59 GMT; path=/";
Cookie cookie = ClientCookieDecoder.STRICT.decode(source);
+ assertNotNull(cookie);
assertTrue(Math.abs(expectedMaxAge - cookie.maxAge()) < 2);
}
@@ -159,6 +162,7 @@ class ClientCookieDecoderTest {
void testDecodingWeirdNames1() {
String src = "path=; expires=Mon, 01-Jan-1990 00:00:00 GMT; path=/; domain=.www.google.com";
Cookie cookie = ClientCookieDecoder.STRICT.decode(src);
+ assertNotNull(cookie);
assertEquals("path", cookie.name());
assertEquals("", cookie.value());
assertEquals("/", cookie.path());
@@ -168,15 +172,14 @@ class ClientCookieDecoderTest {
void testDecodingWeirdNames2() {
String src = "HTTPOnly=";
Cookie cookie = ClientCookieDecoder.STRICT.decode(src);
+ assertNotNull(cookie);
assertEquals("HTTPOnly", cookie.name());
assertEquals("", cookie.value());
}
@Test
void testDecodingValuesWithCommasAndEqualsFails() {
- String src = "A=v=1&lg=en-US,it-IT,it&intl=it&np=1;T=z=E";
- Cookie cookie = ClientCookieDecoder.STRICT.decode(src);
- assertNull(cookie);
+ assertNull(ClientCookieDecoder.STRICT.decode( "A=v=1&lg=en-US,it-IT,it&intl=it&np=1;T=z=E"));
}
@Test
@@ -226,6 +229,7 @@ class ClientCookieDecoderTest {
"%=KqtH_$?mi____'=KqtH_$?mx____'=KqtH_$D7]____#=J_#p_$D@T____#=J_#p_$V {
- ClientCookieEncoder.STRICT.encode(new DefaultCookie("myCookie", "foo;bar"));
- });
+ assertThrows(IllegalArgumentException.class, () ->
+ ClientCookieEncoder.STRICT.encode(new DefaultCookie("myCookie", "foo;bar")));
}
}
diff --git a/netty-http-common/src/main/java/org/xbib/netty/http/common/cookie/Cookie.java b/netty-http-common/src/main/java/org/xbib/netty/http/common/cookie/Cookie.java
index fb41eae..4890b0f 100644
--- a/netty-http-common/src/main/java/org/xbib/netty/http/common/cookie/Cookie.java
+++ b/netty-http-common/src/main/java/org/xbib/netty/http/common/cookie/Cookie.java
@@ -147,6 +147,4 @@ public interface Cookie extends Comparable {
* @param sameSite the same site value
*/
void setSameSite(SameSite sameSite);
-
- enum SameSite { STRICT, LAX }
}
diff --git a/netty-http-common/src/main/java/org/xbib/netty/http/common/cookie/CookieSigner.java b/netty-http-common/src/main/java/org/xbib/netty/http/common/cookie/CookieSigner.java
new file mode 100644
index 0000000..1ca2f1f
--- /dev/null
+++ b/netty-http-common/src/main/java/org/xbib/netty/http/common/cookie/CookieSigner.java
@@ -0,0 +1,169 @@
+package org.xbib.netty.http.common.cookie;
+
+import org.xbib.net.PercentDecoder;
+import org.xbib.net.PercentEncoder;
+import org.xbib.net.PercentEncoders;
+import org.xbib.netty.http.common.security.Codec;
+import org.xbib.netty.http.common.security.CryptUtil;
+import org.xbib.netty.http.common.security.HMac;
+
+import java.nio.charset.Charset;
+import java.nio.charset.CodingErrorAction;
+import java.nio.charset.MalformedInputException;
+import java.nio.charset.StandardCharsets;
+import java.nio.charset.UnmappableCharacterException;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.SignatureException;
+
+public class CookieSigner {
+
+ private String signature;
+
+ private final String publicValue;
+
+ private final String privateValue;
+
+ private String cookieValue;
+
+ /**
+ * Construct cookie for signing.
+ *
+ * @param charset the character set
+ * @param hmac the HMAC code
+ * @param codec the codec for the private value
+ * @param privateValue the private value
+ * @param publicValue the public value
+ * @param secret the secret
+ * @throws MalformedInputException if signing cookie fails
+ * @throws UnmappableCharacterException if signing cookie fails
+ * @throws NoSuchAlgorithmException if signing cookie fails
+ * @throws InvalidKeyException if signing cookie fails
+ */
+ private CookieSigner(Charset charset, HMac hmac, Codec codec, String privateValue, String publicValue, String secret)
+ throws MalformedInputException, UnmappableCharacterException, NoSuchAlgorithmException, InvalidKeyException {
+ PercentEncoder percentEncoder = PercentEncoders.getCookieEncoder(charset);
+ this.privateValue = privateValue;
+ this.publicValue = publicValue;
+ this.signature = CryptUtil.hmac(charset, hmac, codec, privateValue, secret);
+ this.cookieValue = percentEncoder.encode(String.join(":", publicValue, privateValue, signature));
+ }
+
+ /**
+ * Parse signed cookie value.
+ *
+ * @param charset the character set
+ * @param hmac the HMAC code
+ * @param codec the codec for the private value
+ * @param rawValue the raw value for parsing
+ * @param secret the secret
+ * @throws MalformedInputException if parsing failed
+ * @throws UnmappableCharacterException if parsing failed
+ * @throws NoSuchAlgorithmException if parsing failed
+ * @throws InvalidKeyException if parsing failed
+ * @throws SignatureException if signature is invalid
+ */
+ private CookieSigner(Charset charset, HMac hmac, Codec codec, String rawValue, String secret)
+ throws MalformedInputException, UnmappableCharacterException, NoSuchAlgorithmException, InvalidKeyException,
+ SignatureException {
+ PercentDecoder persentDecoder = new PercentDecoder(charset.newDecoder()
+ .onMalformedInput(CodingErrorAction.REPORT)
+ .onUnmappableCharacter(CodingErrorAction.REPORT)
+ );
+ String[] s = persentDecoder.decode(rawValue).split(":", 3);
+ if (s.length != 3) {
+ throw new IllegalStateException("unable to find three colon-separated components in cookie value");
+ }
+ this.signature = CryptUtil.hmac(charset, hmac, codec, s[1], secret);
+ if (!s[2].equals(signature)) {
+ throw new SignatureException("HMAC signature does not match");
+ }
+ this.publicValue = s[0];
+ this.privateValue = s[1];
+ this.cookieValue = rawValue;
+ }
+
+ public String getPublicValue() {
+ return publicValue;
+ }
+
+ public String getPrivateValue() {
+ return privateValue;
+ }
+
+ public String getCookieValue() {
+ return cookieValue;
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public static class Builder {
+
+ private Charset charset;
+
+ private HMac hmac;
+
+ private Codec codec;
+
+ private String privateValue;
+
+ private String publicValue;
+
+ private String secret;
+
+ private String rawValue;
+
+ public Builder() {
+ this.charset = StandardCharsets.UTF_8;
+ this.hmac = HMac.HMAC_SHA1;
+ this.codec = Codec.BASE64;
+ }
+
+ public Builder withCharset(Charset charset) {
+ this.charset = charset;
+ return this;
+ }
+
+ public Builder withHMac(HMac hmac) {
+ this.hmac = hmac;
+ return this;
+ }
+
+ public Builder withCodec(Codec codec) {
+ this.codec = codec;
+ return this;
+ }
+
+ public Builder withPrivateValue(String privateValue) {
+ this.privateValue = privateValue;
+ return this;
+ }
+
+ public Builder withPublicValue(String publicValue) {
+ this.publicValue = publicValue;
+ return this;
+ }
+
+ public Builder withSecret(String secret) {
+ this.secret = secret;
+ return this;
+ }
+
+ public Builder withRawValue(String rawValue) {
+ this.rawValue = rawValue;
+ return this;
+ }
+
+ public CookieSigner build() {
+ try {
+ return rawValue != null ?
+ new CookieSigner(charset, hmac, codec, rawValue, secret) :
+ new CookieSigner(charset, hmac, codec, privateValue, publicValue, secret);
+ } catch (Exception e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+ }
+}
diff --git a/netty-http-common/src/main/java/org/xbib/netty/http/common/cookie/DefaultCookie.java b/netty-http-common/src/main/java/org/xbib/netty/http/common/cookie/DefaultCookie.java
index e2277cd..ff4752d 100644
--- a/netty-http-common/src/main/java/org/xbib/netty/http/common/cookie/DefaultCookie.java
+++ b/netty-http-common/src/main/java/org/xbib/netty/http/common/cookie/DefaultCookie.java
@@ -25,6 +25,10 @@ public class DefaultCookie implements Cookie {
private SameSite sameSite;
+ public DefaultCookie(String name, CookieSigner cookieSigner) {
+ this(name, cookieSigner.getCookieValue());
+ }
+
/**
* Creates a new cookie with the specified name and value.
* @param name name
@@ -38,10 +42,6 @@ public class DefaultCookie implements Cookie {
setValue(value);
}
- public DefaultCookie(String name, Payload payload) {
- this(name, payload.toString());
- }
-
@Override
public String name() {
return name;
diff --git a/netty-http-common/src/main/java/org/xbib/netty/http/common/cookie/Payload.java b/netty-http-common/src/main/java/org/xbib/netty/http/common/cookie/Payload.java
deleted file mode 100644
index c296b92..0000000
--- a/netty-http-common/src/main/java/org/xbib/netty/http/common/cookie/Payload.java
+++ /dev/null
@@ -1,78 +0,0 @@
-package org.xbib.netty.http.common.cookie;
-
-import org.xbib.net.PercentDecoder;
-import org.xbib.net.PercentEncoder;
-import org.xbib.net.PercentEncoders;
-import org.xbib.netty.http.common.util.Codec;
-import org.xbib.netty.http.common.util.CryptUtils;
-import org.xbib.netty.http.common.util.HMac;
-
-import java.nio.charset.MalformedInputException;
-import java.nio.charset.StandardCharsets;
-import java.nio.charset.UnmappableCharacterException;
-import java.security.InvalidKeyException;
-import java.security.NoSuchAlgorithmException;
-import java.security.SignatureException;
-
-public class Payload {
-
- private static final PercentEncoder PERCENT_ENCODER = PercentEncoders.getCookieEncoder(StandardCharsets.UTF_8);
-
- private static final PercentDecoder PERCENT_DECODER = new PercentDecoder(StandardCharsets.UTF_8.newDecoder());
-
- private final Codec codec;
-
- private final HMac hmac;
-
- private final String publicValue;
-
- private final String privateValue;
-
- private final String secret;
-
- public Payload(Codec codec, HMac hmac, String publicValue, String privateValue, String secret) {
- this.codec = codec;
- this.hmac = hmac;
- this.publicValue = publicValue;
- this.privateValue = privateValue;
- this.secret = secret;
- }
-
- public Payload(Codec codec, HMac hmac, String rawValue, String secret)
- throws MalformedInputException, UnmappableCharacterException, InvalidKeyException,
- NoSuchAlgorithmException, SignatureException {
- this.codec = codec;
- this.hmac = hmac;
- String[] s = PERCENT_DECODER.decode(rawValue).split(":", 3);
- if (s.length != 3) {
- throw new IllegalStateException();
- }
- this.publicValue = s[0];
- this.privateValue = s[1];
- this.secret = secret;
- if (!s[2].equals(CryptUtils.hmac(codec, privateValue, secret, hmac))) {
- throw new SignatureException("HMAC signature does not match");
- }
- }
-
- public String getPublicValue() {
- return publicValue;
- }
-
- public String getPrivateValue() {
- return privateValue;
- }
-
- public String getSecret() {
- return secret;
- }
-
- public String toString() {
- try {
- return PERCENT_ENCODER.encode(String.join(":", publicValue, privateValue,
- CryptUtils.hmac(codec, privateValue, secret, hmac)));
- } catch (NoSuchAlgorithmException | InvalidKeyException | MalformedInputException | UnmappableCharacterException e) {
- throw new IllegalArgumentException(e);
- }
- }
-}
diff --git a/netty-http-common/src/main/java/org/xbib/netty/http/common/cookie/SameSite.java b/netty-http-common/src/main/java/org/xbib/netty/http/common/cookie/SameSite.java
new file mode 100644
index 0000000..26fdae3
--- /dev/null
+++ b/netty-http-common/src/main/java/org/xbib/netty/http/common/cookie/SameSite.java
@@ -0,0 +1,5 @@
+package org.xbib.netty.http.common.cookie;
+
+public enum SameSite {
+ STRICT, LAX
+}
diff --git a/netty-http-common/src/main/java/org/xbib/netty/http/common/util/Algo.java b/netty-http-common/src/main/java/org/xbib/netty/http/common/security/Algo.java
similarity index 88%
rename from netty-http-common/src/main/java/org/xbib/netty/http/common/util/Algo.java
rename to netty-http-common/src/main/java/org/xbib/netty/http/common/security/Algo.java
index 4dc2fae..3f03e48 100644
--- a/netty-http-common/src/main/java/org/xbib/netty/http/common/util/Algo.java
+++ b/netty-http-common/src/main/java/org/xbib/netty/http/common/security/Algo.java
@@ -1,4 +1,4 @@
-package org.xbib.netty.http.common.util;
+package org.xbib.netty.http.common.security;
public enum Algo {
MD5("MD5", "md5"),
diff --git a/netty-http-common/src/main/java/org/xbib/netty/http/common/security/Codec.java b/netty-http-common/src/main/java/org/xbib/netty/http/common/security/Codec.java
new file mode 100644
index 0000000..2bbab5b
--- /dev/null
+++ b/netty-http-common/src/main/java/org/xbib/netty/http/common/security/Codec.java
@@ -0,0 +1,5 @@
+package org.xbib.netty.http.common.security;
+
+public enum Codec {
+ BASE64, HEX
+}
diff --git a/netty-http-common/src/main/java/org/xbib/netty/http/common/util/CryptUtils.java b/netty-http-common/src/main/java/org/xbib/netty/http/common/security/CryptUtil.java
similarity index 75%
rename from netty-http-common/src/main/java/org/xbib/netty/http/common/util/CryptUtils.java
rename to netty-http-common/src/main/java/org/xbib/netty/http/common/security/CryptUtil.java
index 4adac32..f0a86f4 100644
--- a/netty-http-common/src/main/java/org/xbib/netty/http/common/util/CryptUtils.java
+++ b/netty-http-common/src/main/java/org/xbib/netty/http/common/security/CryptUtil.java
@@ -1,7 +1,8 @@
-package org.xbib.netty.http.common.util;
+package org.xbib.netty.http.common.security;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
+import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
@@ -15,10 +16,13 @@ import java.util.Base64;
* A utility class for invoking encryption methods and returning password strings,
* using {@link java.security.MessageDigest} and {@link javax.crypto.Mac}.
*/
-public class CryptUtils {
+public class CryptUtil {
private static final Random random = new SecureRandom();
+ private CryptUtil() {
+ }
+
public static String randomHex(int length) {
byte[] b = new byte[length];
random.nextBytes(b);
@@ -53,32 +57,32 @@ public class CryptUtils {
return digest(Codec.BASE64, plainText.getBytes(StandardCharsets.UTF_8), salt, Algo.SSHA512.algo, Algo.SSHA512.prefix);
}
- public static String hmacSHA1(String plainText, String secret) throws NoSuchAlgorithmException, InvalidKeyException {
- return hmac(Codec.BASE64, plainText.getBytes(StandardCharsets.UTF_8), secret.getBytes(StandardCharsets.UTF_8), HMac.HMAC_SHA1);
+ public static String hmacSHA1(Charset charset, String plainText, String secret) throws NoSuchAlgorithmException, InvalidKeyException {
+ return hmac(HMac.HMAC_SHA1, Codec.BASE64, plainText.getBytes(charset), secret.getBytes(charset));
}
- public static String hmacSHA1(byte[] plainText, String secret) throws InvalidKeyException, NoSuchAlgorithmException {
- return hmac(Codec.BASE64, plainText, secret.getBytes(StandardCharsets.UTF_8), HMac.HMAC_SHA1);
+ public static String hmacSHA1(Charset charset, byte[] plainText, String secret) throws InvalidKeyException, NoSuchAlgorithmException {
+ return hmac(HMac.HMAC_SHA1, Codec.BASE64, plainText, secret.getBytes(charset));
}
public static String hmacSHA1(byte[] plainText, byte[] secret) throws InvalidKeyException, NoSuchAlgorithmException {
- return hmac(Codec.BASE64, plainText, secret, HMac.HMAC_SHA1);
+ return hmac(HMac.HMAC_SHA1, Codec.BASE64, plainText, secret);
}
- public static String hmacSHA256(String plainText, String secret) throws NoSuchAlgorithmException, InvalidKeyException {
- return hmac(Codec.BASE64, plainText.getBytes(StandardCharsets.UTF_8), secret.getBytes(StandardCharsets.UTF_8), HMac.HMAC_SHA256);
+ public static String hmacSHA256(Charset charset, String plainText, String secret) throws NoSuchAlgorithmException, InvalidKeyException {
+ return hmac(HMac.HMAC_SHA256, Codec.BASE64, plainText.getBytes(charset), secret.getBytes(charset));
}
- public static String hmacSHA256(byte[] plainText, String secret) throws InvalidKeyException, NoSuchAlgorithmException {
- return hmac(Codec.BASE64, plainText, secret.getBytes(StandardCharsets.UTF_8), HMac.HMAC_SHA256);
+ public static String hmacSHA256(Charset charset, byte[] plainText, String secret) throws InvalidKeyException, NoSuchAlgorithmException {
+ return hmac(HMac.HMAC_SHA256, Codec.BASE64, plainText, secret.getBytes(charset));
}
public static String hmacSHA256(byte[] plainText, byte[] secret) throws InvalidKeyException, NoSuchAlgorithmException {
- return hmac(Codec.BASE64, plainText, secret, HMac.HMAC_SHA256);
+ return hmac(HMac.HMAC_SHA256, Codec.BASE64, plainText, secret);
}
- public static String hmac(Codec codec, String plainText, String secret, HMac hmac) throws InvalidKeyException, NoSuchAlgorithmException {
- return hmac(codec, plainText.getBytes(StandardCharsets.UTF_8), secret.getBytes(StandardCharsets.UTF_8), hmac);
+ public static String hmac(Charset charset, HMac hmac, Codec codec, String plainText, String secret) throws InvalidKeyException, NoSuchAlgorithmException {
+ return hmac(hmac, codec, plainText.getBytes(charset), secret.getBytes(charset));
}
public static String digest(Codec codec, byte[] plainText, byte[] salt, String algo, String prefix) throws NoSuchAlgorithmException {
@@ -98,11 +102,11 @@ public class CryptUtils {
codec == Codec.HEX ? encodeHex(bytes) : null);
}
- public static String hmac(Codec codec, byte[] plainText, byte[] secret, HMac hmac) throws NoSuchAlgorithmException, InvalidKeyException {
+ public static String hmac(HMac hmac, Codec codec, byte[] plainText, byte[] secret) throws NoSuchAlgorithmException, InvalidKeyException {
Objects.requireNonNull(plainText);
Objects.requireNonNull(secret);
- Mac mac = Mac.getInstance(hmac.algo);
- SecretKeySpec secretKeySpec = new SecretKeySpec(secret, hmac.algo);
+ Mac mac = Mac.getInstance(hmac.getAlgo());
+ SecretKeySpec secretKeySpec = new SecretKeySpec(secret, hmac.getAlgo());
mac.init(secretKeySpec);
return codec == Codec.BASE64 ? Base64.getEncoder().encodeToString(mac.doFinal(plainText)) :
codec == Codec.HEX ? encodeHex(mac.doFinal(plainText)) : null;
diff --git a/netty-http-common/src/main/java/org/xbib/netty/http/common/util/HMac.java b/netty-http-common/src/main/java/org/xbib/netty/http/common/security/HMac.java
similarity index 60%
rename from netty-http-common/src/main/java/org/xbib/netty/http/common/util/HMac.java
rename to netty-http-common/src/main/java/org/xbib/netty/http/common/security/HMac.java
index 3c3e842..b0433f5 100644
--- a/netty-http-common/src/main/java/org/xbib/netty/http/common/util/HMac.java
+++ b/netty-http-common/src/main/java/org/xbib/netty/http/common/security/HMac.java
@@ -1,4 +1,4 @@
-package org.xbib.netty.http.common.util;
+package org.xbib.netty.http.common.security;
public enum HMac {
HMAC_SHA1("HMacSHA1"),
@@ -9,4 +9,8 @@ public enum HMac {
HMac(String algo) {
this.algo = algo;
}
+
+ public String getAlgo() {
+ return algo;
+ }
}
diff --git a/netty-http-common/src/main/java/org/xbib/netty/http/common/SecurityUtil.java b/netty-http-common/src/main/java/org/xbib/netty/http/common/security/SecurityUtil.java
similarity index 94%
rename from netty-http-common/src/main/java/org/xbib/netty/http/common/SecurityUtil.java
rename to netty-http-common/src/main/java/org/xbib/netty/http/common/security/SecurityUtil.java
index a90edb2..c569e05 100644
--- a/netty-http-common/src/main/java/org/xbib/netty/http/common/SecurityUtil.java
+++ b/netty-http-common/src/main/java/org/xbib/netty/http/common/security/SecurityUtil.java
@@ -1,4 +1,4 @@
-package org.xbib.netty.http.common;
+package org.xbib.netty.http.common.security;
import io.netty.handler.codec.http2.Http2SecurityUtil;
import io.netty.handler.ssl.CipherSuiteFilter;
@@ -23,6 +23,9 @@ public class SecurityUtil {
}
}
+ private SecurityUtil() {
+ }
+
public interface Defaults {
List OPENSSL_CIPHERS = Http2SecurityUtil.CIPHERS;
diff --git a/netty-http-common/src/main/java/org/xbib/netty/http/common/util/Codec.java b/netty-http-common/src/main/java/org/xbib/netty/http/common/util/Codec.java
deleted file mode 100644
index 1b3e92d..0000000
--- a/netty-http-common/src/main/java/org/xbib/netty/http/common/util/Codec.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package org.xbib.netty.http.common.util;
-
-public enum Codec {
- BASE64, HEX
-}
diff --git a/netty-http-common/src/main/java/org/xbib/netty/http/common/util/DateTimeUtils.java b/netty-http-common/src/main/java/org/xbib/netty/http/common/util/DateTimeUtil.java
similarity index 97%
rename from netty-http-common/src/main/java/org/xbib/netty/http/common/util/DateTimeUtils.java
rename to netty-http-common/src/main/java/org/xbib/netty/http/common/util/DateTimeUtil.java
index 8f7dd95..c07b535 100644
--- a/netty-http-common/src/main/java/org/xbib/netty/http/common/util/DateTimeUtils.java
+++ b/netty-http-common/src/main/java/org/xbib/netty/http/common/util/DateTimeUtil.java
@@ -8,7 +8,7 @@ import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.Locale;
-public class DateTimeUtils {
+public class DateTimeUtil {
private static final ZoneId ZONE_UTC = ZoneId.of("UTC");
@@ -18,6 +18,9 @@ public class DateTimeUtils {
private static final String ASCIITIME_PATTERN = "EEE MMM d HH:mm:ss yyyyy";
+ private DateTimeUtil() {
+ }
+
public static String formatInstant(Instant instant) {
return DateTimeFormatter.RFC_1123_DATE_TIME.format(ZonedDateTime.ofInstant(instant, ZoneOffset.UTC));
}
diff --git a/netty-http-common/src/test/java/org/xbib/netty/http/common/test/cookie/CookieSignerTest.java b/netty-http-common/src/test/java/org/xbib/netty/http/common/test/cookie/CookieSignerTest.java
new file mode 100644
index 0000000..d068cd2
--- /dev/null
+++ b/netty-http-common/src/test/java/org/xbib/netty/http/common/test/cookie/CookieSignerTest.java
@@ -0,0 +1,85 @@
+package org.xbib.netty.http.common.test.cookie;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.xbib.netty.http.common.cookie.DefaultCookie;
+import org.xbib.netty.http.common.cookie.CookieSigner;
+import org.xbib.netty.http.common.security.HMac;
+
+import java.nio.charset.StandardCharsets;
+import java.util.Base64;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class CookieSignerTest {
+
+ @Test
+ void testEncodeSignedCookie() {
+ String id = "dummy";
+ CookieSigner cookieSigner = CookieSigner.builder().withHMac(HMac.HMAC_SHA256)
+ .withPublicValue(id)
+ .withPrivateValue(Base64.getEncoder().encodeToString("Hello".getBytes(StandardCharsets.UTF_8)))
+ .withSecret("d9fd3a19707be6025b4f5a98c320745960a1b95144f040afcda2a4997dbae0cb")
+ .build();
+ DefaultCookie cookie = new DefaultCookie("SESS", cookieSigner);
+ assertEquals("dummy", cookieSigner.getPublicValue());
+ assertEquals("dummy%3ASGVsbG8%3D%3AqEdbImuwfh7r%2BmOaShC3IjXhkdiiF3Y1RgSZ%2FFAZrQ4%3D", cookie.value());
+ }
+
+ @Test
+ void testDecodeSignedCookie() {
+ String rawValue = "dummy%3ASGVsbG8%3D%3AqEdbImuwfh7r%2BmOaShC3IjXhkdiiF3Y1RgSZ%2FFAZrQ4%3D";
+ CookieSigner cookieSigner = CookieSigner.builder()
+ .withHMac(HMac.HMAC_SHA256)
+ .withRawValue(rawValue)
+ .withSecret("d9fd3a19707be6025b4f5a98c320745960a1b95144f040afcda2a4997dbae0cb")
+ .build();
+ DefaultCookie cookie = new DefaultCookie("SESS", cookieSigner);
+ assertEquals("dummy%3ASGVsbG8%3D%3AqEdbImuwfh7r%2BmOaShC3IjXhkdiiF3Y1RgSZ%2FFAZrQ4%3D", cookie.value());
+ assertEquals("dummy", cookieSigner.getPublicValue());
+ assertEquals("Hello", new String(Base64.getDecoder().decode(cookieSigner.getPrivateValue()),
+ StandardCharsets.UTF_8));
+ }
+
+ @Test
+ void testDecodeInvalidTuple() {
+ Assertions.assertThrows(IllegalArgumentException.class, () -> {
+ String rawValue = "dummy%3JSGVsbG8%3D%3AqEdbImuwfh7r%2BmOaShC3IjXhkdiiF3Y1RgSZ%2FFAZrQ4%3D";
+ CookieSigner.builder()
+ .withHMac(HMac.HMAC_SHA256)
+ .withRawValue(rawValue)
+ .withSecret("d9fd3a19707be6025b4f5a98c320745960a1b95144f040afcda2a4997dbae0cb")
+ .build();
+
+ });
+ }
+
+ @Test
+ void testDecodeISOGivesMalformedInputException() {
+ Assertions.assertThrows(IllegalArgumentException.class, () -> {
+ String rawValue = "dummy%FCSGVsbG8%3D%3AqEdbImuwfh7r%2BmOaShC3IjXhkdiiF3Y1RgSZ%2FFAZrQ4%3D";
+ CookieSigner.builder()
+ .withHMac(HMac.HMAC_SHA256)
+ .withRawValue(rawValue)
+ .withSecret("d9fd3a19707be6025b4f5a98c320745960a1b95144f040afcda2a4997dbae0cb")
+ .build();
+
+ });
+ }
+
+ @Test
+ void testDecodeISO() {
+ String rawValue = "d%FCmmy%3ASGVsbG8%3D%3AqEdbImuwfh7r%2BmOaShC3IjXhkdiiF3Y1RgSZ%2FFAZrQ4%3D";
+ CookieSigner cookieSigner = CookieSigner.builder()
+ .withCharset(StandardCharsets.ISO_8859_1)
+ .withHMac(HMac.HMAC_SHA256)
+ .withRawValue(rawValue)
+ .withSecret("d9fd3a19707be6025b4f5a98c320745960a1b95144f040afcda2a4997dbae0cb")
+ .build();
+ DefaultCookie cookie = new DefaultCookie("SESS", cookieSigner);
+ assertEquals("d%FCmmy%3ASGVsbG8%3D%3AqEdbImuwfh7r%2BmOaShC3IjXhkdiiF3Y1RgSZ%2FFAZrQ4%3D", cookie.value());
+ assertEquals("dümmy", cookieSigner.getPublicValue());
+ assertEquals("Hello", new String(Base64.getDecoder().decode(cookieSigner.getPrivateValue()),
+ StandardCharsets.UTF_8));
+ }
+}
diff --git a/netty-http-common/src/test/java/org/xbib/netty/http/common/test/cookie/SignedCookieTest.java b/netty-http-common/src/test/java/org/xbib/netty/http/common/test/cookie/SignedCookieTest.java
deleted file mode 100644
index cad6062..0000000
--- a/netty-http-common/src/test/java/org/xbib/netty/http/common/test/cookie/SignedCookieTest.java
+++ /dev/null
@@ -1,72 +0,0 @@
-package org.xbib.netty.http.common.test.cookie;
-
-import org.junit.jupiter.api.Test;
-import org.xbib.netty.http.common.cookie.Cookie;
-import org.xbib.netty.http.common.cookie.DefaultCookie;
-import org.xbib.netty.http.common.cookie.Payload;
-import org.xbib.netty.http.common.util.Codec;
-import org.xbib.netty.http.common.util.HMac;
-
-import java.nio.charset.MalformedInputException;
-import java.nio.charset.StandardCharsets;
-import java.nio.charset.UnmappableCharacterException;
-import java.security.InvalidKeyException;
-import java.security.NoSuchAlgorithmException;
-import java.security.SignatureException;
-import java.util.Base64;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-
-class SignedCookieTest {
-
- @Test
- void testEncodeDefaultCookie() {
- Base64Codec codec = new Base64Codec();
- String cookieName = "SESS";
- String domain = ".hbz-nrw.de";
- String path = "/";
- String id = "dummy";
- Payload payload = new Payload(Codec.BASE64, HMac.HMAC_SHA256,
- id, new String(codec.encode("Hello"), StandardCharsets.UTF_8),
- "d9fd3a19707be6025b4f5a98c320745960a1b95144f040afcda2a4997dbae0cb");
- DefaultCookie cookie = new DefaultCookie(cookieName, payload);
- cookie.setDomain(domain);
- cookie.setPath(path);
- cookie.setMaxAge(3600);
- cookie.setHttpOnly(true);
- cookie.setSecure(true);
- cookie.setSameSite(Cookie.SameSite.LAX);
- assertEquals("dummy%3ASGVsbG8%3D%3AqEdbImuwfh7r%2BmOaShC3IjXhkdiiF3Y1RgSZ%2FFAZrQ4%3D", cookie.value());
- assertEquals(domain, cookie.domain());
- assertEquals(path, cookie.path());
- assertEquals(3600, cookie.maxAge());
- assertEquals(cookieName, cookie.name());
- assertTrue(cookie.isHttpOnly());
- assertTrue(cookie.isSecure());
- assertEquals(Cookie.SameSite.LAX, cookie.sameSite());
- }
-
- @Test
- void testCookieValue()
- throws MalformedInputException, UnmappableCharacterException, NoSuchAlgorithmException, InvalidKeyException, SignatureException {
- Base64Codec codec = new Base64Codec();
- String rawCookieValue = "dummy%3ASGVsbG8%3D%3AqEdbImuwfh7r%2BmOaShC3IjXhkdiiF3Y1RgSZ%2FFAZrQ4%3D";
- Payload payload = new Payload(Codec.BASE64, HMac.HMAC_SHA256,
- rawCookieValue, "d9fd3a19707be6025b4f5a98c320745960a1b95144f040afcda2a4997dbae0cb");
- DefaultCookie cookie = new DefaultCookie("SESS", payload);
- assertEquals("dummy", payload.getPublicValue());
- assertEquals("Hello", codec.decode(payload.getPrivateValue().getBytes(StandardCharsets.UTF_8)));
- }
-
- class Base64Codec {
-
- byte[] encode(String payload) {
- return Base64.getEncoder().encode(payload.getBytes(StandardCharsets.UTF_8));
- }
-
- String decode(byte[] bytes) {
- return new String(Base64.getDecoder().decode(bytes), StandardCharsets.UTF_8);
- }
- }
-}
diff --git a/netty-http-common/src/test/java/org/xbib/netty/http/common/test/CryptUtilsTest.java b/netty-http-common/src/test/java/org/xbib/netty/http/common/test/security/CryptUtilTest.java
similarity index 60%
rename from netty-http-common/src/test/java/org/xbib/netty/http/common/test/CryptUtilsTest.java
rename to netty-http-common/src/test/java/org/xbib/netty/http/common/test/security/CryptUtilTest.java
index 7abf203..1248c9a 100644
--- a/netty-http-common/src/test/java/org/xbib/netty/http/common/test/CryptUtilsTest.java
+++ b/netty-http-common/src/test/java/org/xbib/netty/http/common/test/security/CryptUtilTest.java
@@ -1,33 +1,33 @@
-package org.xbib.netty.http.common.test;
+package org.xbib.netty.http.common.test.security;
import org.junit.jupiter.api.Test;
-import org.xbib.netty.http.common.util.CryptUtils;
+import org.xbib.netty.http.common.security.CryptUtil;
+import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import static org.junit.jupiter.api.Assertions.assertEquals;
-class CryptUtilsTest {
+class CryptUtilTest {
@Test
void testRfc2307() throws NoSuchAlgorithmException {
-
assertEquals("{md5}ixqZU8RhEpaoJ6v4xHgE1w==",
- CryptUtils.md5("Hello"));
+ CryptUtil.md5("Hello"));
assertEquals("{sha}9/+ei3uy4Jtwk1pdeF4MxdnQq/A=",
- CryptUtils.sha("Hello"));
+ CryptUtil.sha("Hello"));
assertEquals("{sha256}GF+NsyJx/iX1Yab8k4suJkMG7DBO2lGAB9F2SCY4GWk=",
- CryptUtils.sha256("Hello"));
+ CryptUtil.sha256("Hello"));
assertEquals("{sha512}NhX4DJ0pPtdAJof5SyLVjlKbjMeRb4+sf933+9WvTPd309eVp6AKFr9+fz+5Vh7puq5IDan+ehh2nnGIawPzFQ==",
- CryptUtils.sha512("Hello"));
+ CryptUtil.sha512("Hello"));
}
@Test
void testHmac() throws InvalidKeyException, NoSuchAlgorithmException {
assertEquals("Wgxn2SLeDKU+MGJQ5oWMH20sSUM=",
- CryptUtils.hmacSHA1("hello", "world"));
+ CryptUtil.hmacSHA1(StandardCharsets.ISO_8859_1, "hello", "world"));
assertEquals("PPp27xSTfBwOpRn4/AV6gPzQSnQg+Oi80KdWfCcuAHs=",
- CryptUtils.hmacSHA256("hello", "world"));
+ CryptUtil.hmacSHA256(StandardCharsets.ISO_8859_1, "hello", "world"));
}
}
diff --git a/netty-http-server/src/main/java/org/xbib/netty/http/server/Domain.java b/netty-http-server/src/main/java/org/xbib/netty/http/server/Domain.java
index 3901c66..bd955ed 100644
--- a/netty-http-server/src/main/java/org/xbib/netty/http/server/Domain.java
+++ b/netty-http-server/src/main/java/org/xbib/netty/http/server/Domain.java
@@ -8,7 +8,7 @@ import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslContextBuilder;
import io.netty.handler.ssl.SslProvider;
import org.xbib.netty.http.common.HttpAddress;
-import org.xbib.netty.http.common.SecurityUtil;
+import org.xbib.netty.http.common.security.SecurityUtil;
import org.xbib.netty.http.server.endpoint.HttpEndpoint;
import org.xbib.netty.http.server.endpoint.HttpEndpointResolver;
import org.xbib.netty.http.server.endpoint.service.Service;
@@ -147,7 +147,7 @@ public class Domain {
this.serverName = serverName;
this.aliases = new LinkedHashSet<>();
this.httpEndpointResolvers = new ArrayList<>();
- this.trustManagerFactory = SecurityUtil.Defaults.DEFAULT_TRUST_MANAGER_FACTORY; // InsecureTrustManagerFactory.INSTANCE;
+ this.trustManagerFactory = SecurityUtil.Defaults.DEFAULT_TRUST_MANAGER_FACTORY;
this.sslProvider = SecurityUtil.Defaults.DEFAULT_SSL_PROVIDER;
this.ciphers = SecurityUtil.Defaults.DEFAULT_CIPHERS;
this.cipherSuiteFilter = SecurityUtil.Defaults.DEFAULT_CIPHER_SUITE_FILTER;
diff --git a/netty-http-server/src/main/java/org/xbib/netty/http/server/Server.java b/netty-http-server/src/main/java/org/xbib/netty/http/server/Server.java
index 8714c7b..c408fb5 100644
--- a/netty-http-server/src/main/java/org/xbib/netty/http/server/Server.java
+++ b/netty-http-server/src/main/java/org/xbib/netty/http/server/Server.java
@@ -22,7 +22,7 @@ import org.xbib.netty.http.common.HttpAddress;
import org.xbib.netty.http.common.NetworkUtils;
import org.xbib.netty.http.server.handler.http.HttpChannelInitializer;
import org.xbib.netty.http.server.handler.http2.Http2ChannelInitializer;
-import org.xbib.netty.http.common.SecurityUtil;
+import org.xbib.netty.http.common.security.SecurityUtil;
import org.xbib.netty.http.server.transport.HttpTransport;
import org.xbib.netty.http.server.transport.Http2Transport;
import org.xbib.netty.http.server.transport.Transport;
@@ -83,8 +83,7 @@ public final class Server {
Class extends ServerSocketChannel> socketChannelClass) {
Objects.requireNonNull(serverConfig);
this.serverConfig = serverConfig;
- this.byteBufAllocator = byteBufAllocator != null ?
- byteBufAllocator : ByteBufAllocator.DEFAULT;
+ this.byteBufAllocator = byteBufAllocator != null ? byteBufAllocator : ByteBufAllocator.DEFAULT;
this.parentEventLoopGroup = createParentEventLoopGroup(serverConfig, parentEventLoopGroup);
this.childEventLoopGroup = createChildEventLoopGroup(serverConfig, childEventLoopGroup);
this.socketChannelClass = createSocketChannelClass(serverConfig, socketChannelClass);
@@ -191,6 +190,7 @@ public final class Server {
parentEventLoopGroup.shutdownGracefully();
try {
if (channelFuture != null) {
+ // close channel and wait
channelFuture.channel().closeFuture().sync();
}
} catch (InterruptedException e) {
diff --git a/netty-http-server/src/main/java/org/xbib/netty/http/server/cookie/ServerCookieEncoder.java b/netty-http-server/src/main/java/org/xbib/netty/http/server/cookie/ServerCookieEncoder.java
index b91fe46..f2d1138 100644
--- a/netty-http-server/src/main/java/org/xbib/netty/http/server/cookie/ServerCookieEncoder.java
+++ b/netty-http-server/src/main/java/org/xbib/netty/http/server/cookie/ServerCookieEncoder.java
@@ -5,7 +5,7 @@ import org.xbib.netty.http.common.cookie.CookieEncoder;
import org.xbib.netty.http.common.cookie.CookieHeaderNames;
import org.xbib.netty.http.common.cookie.CookieUtil;
import org.xbib.netty.http.common.cookie.DefaultCookie;
-import org.xbib.netty.http.common.util.DateTimeUtils;
+import org.xbib.netty.http.common.util.DateTimeUtil;
import java.time.Instant;
import java.util.ArrayList;
@@ -86,7 +86,7 @@ public final class ServerCookieEncoder extends CookieEncoder {
Instant expires = Instant.ofEpochMilli(cookie.maxAge() * 1000 + System.currentTimeMillis());
buf.append(CookieHeaderNames.EXPIRES);
buf.append(CookieUtil.EQUALS);
- buf.append(DateTimeUtils.formatMillis(expires.toEpochMilli()));
+ buf.append(DateTimeUtil.formatMillis(expires.toEpochMilli()));
buf.append(CookieUtil.SEMICOLON);
buf.append(CookieUtil.SP);
}
@@ -110,28 +110,6 @@ public final class ServerCookieEncoder extends CookieEncoder {
return CookieUtil.stripTrailingSeparator(buf);
}
- /**
- * Deduplicate a list of encoded cookies by keeping only the last instance with a given name.
- *
- * @param encoded The list of encoded cookies.
- * @param nameToLastIndex A map from cookie name to index of last cookie instance.
- * @return The encoded list with all but the last instance of a named cookie.
- */
- private static List dedup(List encoded, Map nameToLastIndex) {
- boolean[] isLastInstance = new boolean[encoded.size()];
- for (int idx : nameToLastIndex.values()) {
- isLastInstance[idx] = true;
- }
- List dedupd = new ArrayList<>(nameToLastIndex.size());
- int n = encoded.size();
- for (int i = 0; i < n; i++) {
- if (isLastInstance[i]) {
- dedupd.add(encoded.get(i));
- }
- }
- return dedupd;
- }
-
/**
* Batch encodes cookies into Set-Cookie header values.
*
@@ -204,4 +182,26 @@ public final class ServerCookieEncoder extends CookieEncoder {
}
return hasDupdName ? dedup(encoded, nameToIndex) : encoded;
}
+
+ /**
+ * Deduplicate a list of encoded cookies by keeping only the last instance with a given name.
+ *
+ * @param encoded The list of encoded cookies.
+ * @param nameToLastIndex A map from cookie name to index of last cookie instance.
+ * @return The encoded list with all but the last instance of a named cookie.
+ */
+ private static List dedup(List encoded, Map nameToLastIndex) {
+ boolean[] isLastInstance = new boolean[encoded.size()];
+ for (int idx : nameToLastIndex.values()) {
+ isLastInstance[idx] = true;
+ }
+ List dedupd = new ArrayList<>(nameToLastIndex.size());
+ int n = encoded.size();
+ for (int i = 0; i < n; i++) {
+ if (isLastInstance[i]) {
+ dedupd.add(encoded.get(i));
+ }
+ }
+ return dedupd;
+ }
}
diff --git a/netty-http-server/src/main/java/org/xbib/netty/http/server/endpoint/HttpEndpointDescriptor.java b/netty-http-server/src/main/java/org/xbib/netty/http/server/endpoint/HttpEndpointDescriptor.java
index 713f246..75b6855 100644
--- a/netty-http-server/src/main/java/org/xbib/netty/http/server/endpoint/HttpEndpointDescriptor.java
+++ b/netty-http-server/src/main/java/org/xbib/netty/http/server/endpoint/HttpEndpointDescriptor.java
@@ -32,7 +32,7 @@ public class HttpEndpointDescriptor implements EndpointDescriptor, Comparable endpoint.matches(httpEndpointDescriptor))
- .sorted(new HttpEndpoint.EndpointPathComparator(httpEndpointDescriptor.getPath())).collect(Collectors.toList()));
+ .sorted(new HttpEndpoint.EndpointPathComparator(httpEndpointDescriptor.getPath()))
+ .collect(Collectors.toList()));
List matchingEndpoints = endpointDescriptors.get(httpEndpointDescriptor);
if (logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE, () -> "endpoint = " + httpEndpointDescriptor +
@@ -83,7 +83,7 @@ public class HttpEndpointResolver {
return endpointDescriptors;
}
- protected HttpEndpoint createDefaultEndpoint() {
+ private HttpEndpoint createDefaultEndpoint() {
return HttpEndpoint.builder()
.setPath("/**")
.addMethod("GET")
@@ -94,27 +94,6 @@ public class HttpEndpointResolver {
}).build();
}
- /**
- * A simple LRU cache, based on a {@link LinkedHashMap}.
- *
- * @param the key type parameter
- * @param the vale type parameter
- */
- @SuppressWarnings("serial")
- private static class LRUCache extends LinkedHashMap {
-
- private final int cacheSize;
-
- LRUCache(int cacheSize) {
- super(16, 0.75f, true);
- this.cacheSize = cacheSize;
- }
-
- protected boolean removeEldestEntry(Map.Entry eldest) {
- return size() > cacheSize;
- }
- }
-
public static Builder builder() {
return new Builder();
}
diff --git a/netty-http-server/src/main/java/org/xbib/netty/http/server/endpoint/service/ResourceService.java b/netty-http-server/src/main/java/org/xbib/netty/http/server/endpoint/service/ResourceService.java
index 4c491c6..bb2a792 100644
--- a/netty-http-server/src/main/java/org/xbib/netty/http/server/endpoint/service/ResourceService.java
+++ b/netty-http-server/src/main/java/org/xbib/netty/http/server/endpoint/service/ResourceService.java
@@ -6,7 +6,7 @@ import io.netty.handler.codec.http.HttpHeaders;
import io.netty.handler.codec.http.HttpMethod;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.handler.stream.ChunkedNioStream;
-import org.xbib.netty.http.common.util.DateTimeUtils;
+import org.xbib.netty.http.common.util.DateTimeUtil;
import org.xbib.netty.http.server.ServerRequest;
import org.xbib.netty.http.server.ServerResponse;
import org.xbib.netty.http.server.util.MimeTypeUtils;
@@ -55,14 +55,14 @@ public abstract class ResourceService implements Service {
long maxAgeSeconds = 24 * 3600;
long expirationMillis = System.currentTimeMillis() + 1000 * maxAgeSeconds;
if (isCacheResponseEnabled()) {
- serverResponse.withHeader(HttpHeaderNames.EXPIRES, DateTimeUtils.formatMillis(expirationMillis))
+ serverResponse.withHeader(HttpHeaderNames.EXPIRES, DateTimeUtil.formatMillis(expirationMillis))
.withHeader(HttpHeaderNames.CACHE_CONTROL, "public, max-age=" + maxAgeSeconds);
}
boolean sent = false;
if (isETagResponseEnabled()) {
Instant lastModifiedInstant = resource.getLastModified();
String eTag = resource.getResourcePath().hashCode() + "/" + lastModifiedInstant.toEpochMilli() + "/" + resource.getLength();
- Instant ifUnmodifiedSinceInstant = DateTimeUtils.parseDate(headers.get(HttpHeaderNames.IF_UNMODIFIED_SINCE));
+ Instant ifUnmodifiedSinceInstant = DateTimeUtil.parseDate(headers.get(HttpHeaderNames.IF_UNMODIFIED_SINCE));
if (ifUnmodifiedSinceInstant != null &&
ifUnmodifiedSinceInstant.plusMillis(1000L).isAfter(lastModifiedInstant)) {
ServerResponse.write(serverResponse, HttpResponseStatus.PRECONDITION_FAILED);
@@ -76,20 +76,20 @@ public abstract class ResourceService implements Service {
String ifNoneMatch = headers.get(HttpHeaderNames.IF_NONE_MATCH);
if (ifNoneMatch != null && matches(ifNoneMatch, eTag)) {
serverResponse.withHeader(HttpHeaderNames.ETAG, eTag)
- .withHeader(HttpHeaderNames.EXPIRES, DateTimeUtils.formatMillis(expirationMillis));
+ .withHeader(HttpHeaderNames.EXPIRES, DateTimeUtil.formatMillis(expirationMillis));
ServerResponse.write(serverResponse, HttpResponseStatus.NOT_MODIFIED);
return;
}
- Instant ifModifiedSinceInstant = DateTimeUtils.parseDate(headers.get(HttpHeaderNames.IF_MODIFIED_SINCE));
+ Instant ifModifiedSinceInstant = DateTimeUtil.parseDate(headers.get(HttpHeaderNames.IF_MODIFIED_SINCE));
if (ifModifiedSinceInstant != null &&
ifModifiedSinceInstant.plusMillis(1000L).isAfter(lastModifiedInstant)) {
serverResponse.withHeader(HttpHeaderNames.ETAG, eTag)
- .withHeader(HttpHeaderNames.EXPIRES, DateTimeUtils.formatMillis(expirationMillis));
+ .withHeader(HttpHeaderNames.EXPIRES, DateTimeUtil.formatMillis(expirationMillis));
ServerResponse.write(serverResponse, HttpResponseStatus.NOT_MODIFIED);
return;
}
serverResponse.withHeader(HttpHeaderNames.ETAG, eTag)
- .withHeader(HttpHeaderNames.LAST_MODIFIED, DateTimeUtils.formatInstant(lastModifiedInstant));
+ .withHeader(HttpHeaderNames.LAST_MODIFIED, DateTimeUtil.formatInstant(lastModifiedInstant));
if (isRangeResponseEnabled()) {
performRangeResponse(serverRequest, serverResponse, resource, contentType, eTag, headers);
sent = true;
@@ -119,7 +119,7 @@ public abstract class ResourceService implements Service {
String ifRange = headers.get(HttpHeaderNames.IF_RANGE);
if (ifRange != null && !ifRange.equals(eTag)) {
try {
- Instant ifRangeTime = DateTimeUtils.parseDate(ifRange);
+ Instant ifRangeTime = DateTimeUtil.parseDate(ifRange);
if (ifRangeTime != null && ifRangeTime.plusMillis(1000).isBefore(resource.getLastModified())) {
ranges.add(full);
}
diff --git a/netty-http-server/src/test/java/org/xbib/netty/http/server/test/cookie/ServerCookieEncoderTest.java b/netty-http-server/src/test/java/org/xbib/netty/http/server/test/cookie/ServerCookieEncoderTest.java
index 1643acd..835c033 100644
--- a/netty-http-server/src/test/java/org/xbib/netty/http/server/test/cookie/ServerCookieEncoderTest.java
+++ b/netty-http-server/src/test/java/org/xbib/netty/http/server/test/cookie/ServerCookieEncoderTest.java
@@ -4,7 +4,7 @@ import org.junit.jupiter.api.Test;
import org.xbib.netty.http.client.cookie.ClientCookieEncoder;
import org.xbib.netty.http.common.cookie.Cookie;
import org.xbib.netty.http.common.cookie.DefaultCookie;
-import org.xbib.netty.http.common.util.DateTimeUtils;
+import org.xbib.netty.http.common.util.DateTimeUtil;
import org.xbib.netty.http.server.cookie.ServerCookieEncoder;
import java.time.Instant;
@@ -35,7 +35,7 @@ class ServerCookieEncoderTest {
String encodedCookie = ServerCookieEncoder.STRICT.encode(cookie);
Matcher matcher = Pattern.compile(result).matcher(encodedCookie);
assertTrue(matcher.find());
- Instant expire = DateTimeUtils.parseDate(matcher.group(1));
+ Instant expire = DateTimeUtil.parseDate(matcher.group(1));
long diff = (expire.toEpochMilli() - System.currentTimeMillis()) / 1000;
assertTrue(Math.abs(diff - maxAge) <= 2);
}