diff options
author | Henning Baldersheim <balder@yahoo-inc.com> | 2017-08-29 19:48:12 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-08-29 19:48:12 +0200 |
commit | 02ba009b734276edd1df011f1832adbd4d7b0a1c (patch) | |
tree | be12408f0d609d78143c8ae0931a3bf9d00e8cd6 /jdisc_http_service | |
parent | cb6c9abf466ce0d497245b0a3fbd567669feb2eb (diff) |
Revert "Remove Netty by replacing cookie codec with Jetty + Java SE"
Diffstat (limited to 'jdisc_http_service')
4 files changed, 54 insertions, 133 deletions
diff --git a/jdisc_http_service/pom.xml b/jdisc_http_service/pom.xml index 0c19f2c3d15..2dfcb0bd166 100644 --- a/jdisc_http_service/pom.xml +++ b/jdisc_http_service/pom.xml @@ -22,6 +22,10 @@ <classifier>no_aop</classifier> </dependency> <dependency> + <groupId>io.netty</groupId> + <artifactId>netty</artifactId> + </dependency> + <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> </dependency> diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/Cookie.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/Cookie.java index 2256a3299a7..8f04a870dc9 100644 --- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/Cookie.java +++ b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/Cookie.java @@ -1,22 +1,20 @@ // Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.jdisc.http; -import org.eclipse.jetty.server.CookieCutter; -import org.eclipse.jetty.server.Response; +import org.jboss.netty.handler.codec.http.cookie.ClientCookieDecoder; +import org.jboss.netty.handler.codec.http.cookie.ClientCookieEncoder; +import org.jboss.netty.handler.codec.http.cookie.DefaultCookie; +import org.jboss.netty.handler.codec.http.cookie.ServerCookieDecoder; +import org.jboss.netty.handler.codec.http.cookie.ServerCookieEncoder; -import java.net.HttpCookie; -import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Objects; import java.util.Set; -import java.util.StringTokenizer; import java.util.concurrent.TimeUnit; -import java.util.logging.Level; -import java.util.logging.Logger; import java.util.stream.Collectors; +import java.util.stream.StreamSupport; /** * A RFC 6265 compliant cookie. @@ -28,8 +26,6 @@ import java.util.stream.Collectors; */ public class Cookie { - private final static Logger log = Logger.getLogger(Cookie.class.getName()); - private final Set<Integer> ports = new HashSet<>(); private String name; private String value; @@ -218,18 +214,26 @@ public class Cookie { ret.append(name).append("=").append(value); return ret.toString(); } - // NOTE cookie encoding and decoding: - // The implementation uses Jetty for server-side (encoding of Set-Cookie and decoding of Cookie header), - // and java.net.HttpCookie for client-side (encoding of Cookie and decoding of Set-Cookie header). - // - // Implementation is RFC-6265 compliant. public static String toCookieHeader(Iterable<? extends Cookie> cookies) { - return encodeCookieHeaderValue(toCookieList(cookies)); + ClientCookieEncoder encoder = ClientCookieEncoder.STRICT; + List<org.jboss.netty.handler.codec.http.cookie.Cookie> nettyCookies = + StreamSupport.stream(cookies.spliterator(), false) + // NOTE: Only name and value is included in Cookie header as of RFC-6265 + .map(cookie -> new DefaultCookie(cookie.getName(), cookie.getValue())) + .collect(Collectors.toList()); + return encoder.encode(nettyCookies); } public static List<Cookie> fromCookieHeader(String headerVal) { - return decodeCookieHeaderValue(headerVal); + if (headerVal == null) return Collections.emptyList(); + + ServerCookieDecoder decoder = ServerCookieDecoder.STRICT; + Set<org.jboss.netty.handler.codec.http.cookie.Cookie> nettyCookies = decoder.decode(headerVal); + return nettyCookies.stream() + // NOTE: Only name and value is included in Cookie header as of RFC-6265 + .map(nettyCookie -> new Cookie(nettyCookie.name(), nettyCookie.value())) + .collect(Collectors.toList()); } /** @@ -237,124 +241,40 @@ public class Cookie { */ @Deprecated public static String toSetCookieHeader(Iterable<? extends Cookie> cookies) { - List<String> encodedCookies = encodeSetCookieHeaderValue(cookies); + List<String> encodedCookies = toSetCookieHeaderAll(cookies); return encodedCookies.isEmpty() ? null : encodedCookies.get(0); } // TODO Rename to toSetCookieHeader for Vespa 7 public static List<String> toSetCookieHeaderAll(Iterable<? extends Cookie> cookies) { - return encodeSetCookieHeaderValue(cookies); + ServerCookieEncoder encoder = ServerCookieEncoder.STRICT; + List<org.jboss.netty.handler.codec.http.cookie.Cookie> nettyCookies = + StreamSupport.stream(cookies.spliterator(), false) + .map(cookie -> { + org.jboss.netty.handler.codec.http.cookie.Cookie nettyCookie + = new DefaultCookie(cookie.getName(), cookie.getValue()); + nettyCookie.setPath(cookie.getPath()); + nettyCookie.setMaxAge(cookie.getMaxAge(TimeUnit.SECONDS)); + nettyCookie.setSecure(cookie.isSecure()); + nettyCookie.setHttpOnly(cookie.isHttpOnly()); + nettyCookie.setDomain(cookie.getDomain()); + return nettyCookie; + }) + .collect(Collectors.toList()); + return encoder.encode(nettyCookies); } // TODO Change return type to Cookie for Vespa 7 public static List<Cookie> fromSetCookieHeader(String headerVal) { - return decodeSetCookieHeaderValue(headerVal); - } - - - private static List<String> encodeSetCookieHeaderValue(Iterable<? extends Cookie> cookies) { - // Ugly, bot Jetty does not provide a dedicated cookie parser (will be included in Jetty 10) - Response response = new Response(null, null); - for (Cookie cookie : cookies) { - response.addSetRFC6265Cookie( - cookie.getName(), - cookie.getValue(), - cookie.getDomain(), - cookie.getPath(), - cookie.getMaxAge(TimeUnit.SECONDS), - cookie.isSecure(), - cookie.isHttpOnly()); - } - return new ArrayList<>(response.getHeaders("Set-Cookie")); - } - - private static String encodeCookieHeaderValue(List<Cookie> cookies) { - return cookies.stream() - .map(cookie -> { - HttpCookie httpCookie = new HttpCookie(cookie.getName(), cookie.getValue()); - httpCookie.setComment(cookie.getComment()); - httpCookie.setCommentURL(cookie.getCommentURL()); - httpCookie.setDiscard(cookie.isDiscard()); - httpCookie.setDomain(cookie.getDomain()); - httpCookie.setHttpOnly(cookie.isHttpOnly()); - httpCookie.setMaxAge(cookie.getMaxAge(TimeUnit.SECONDS)); - httpCookie.setPath(cookie.getPath()); - httpCookie.setSecure(cookie.isSecure()); - httpCookie.setVersion(cookie.getVersion()); - String portList = cookie.ports().stream() - .map(Number::toString) - .collect(Collectors.joining(",")); - httpCookie.setPortlist(portList); - return httpCookie.toString(); - }) - .collect(Collectors.joining(";")); - } - - private static List<Cookie> decodeSetCookieHeaderValue(String headerVal) { - - return HttpCookie.parse(headerVal).stream() - .map(httpCookie -> { - Cookie cookie = new Cookie(); - cookie.setName(httpCookie.getName()); - cookie.setValue(httpCookie.getValue()); - cookie.setComment(httpCookie.getComment()); - cookie.setCommentUrl(httpCookie.getCommentURL()); - cookie.setDiscard(httpCookie.getDiscard()); - cookie.setDomain(httpCookie.getDomain()); - cookie.setHttpOnly(httpCookie.isHttpOnly()); - int maxAge = (int) httpCookie.getMaxAge(); - cookie.setMaxAge(maxAge != -1 ? maxAge : Integer.MIN_VALUE, TimeUnit.SECONDS); - cookie.setPath(httpCookie.getPath()); - cookie.setSecure(httpCookie.getSecure()); - cookie.setVersion(httpCookie.getVersion()); - cookie.ports().addAll(parsePortList(httpCookie.getPortlist())); - return cookie; - }) - .collect(Collectors.toList()); - } - - private static List<Cookie> decodeCookieHeaderValue(String headerVal) { - CookieCutter cookieCutter = new CookieCutter(); - cookieCutter.addCookieField(headerVal); - return Arrays.stream(cookieCutter.getCookies()) - .map(servletCookie -> { - Cookie cookie = new Cookie(); - cookie.setName(servletCookie.getName()); - cookie.setValue(servletCookie.getValue()); - cookie.setComment(servletCookie.getComment()); - cookie.setPath(servletCookie.getPath()); - cookie.setDomain(servletCookie.getDomain()); - int maxAge = servletCookie.getMaxAge(); - cookie.setMaxAge(maxAge != -1 ? maxAge : Integer.MIN_VALUE, TimeUnit.SECONDS); - cookie.setSecure(servletCookie.getSecure()); - cookie.setVersion(servletCookie.getVersion()); - cookie.setHttpOnly(servletCookie.isHttpOnly()); - return cookie; - }) - .collect(Collectors.toList()); - } - - private static List<Integer> parsePortList(String rawPortList) { - if (rawPortList == null) return Collections.emptyList(); - - List<Integer> ports = new ArrayList<>(); - StringTokenizer tokenizer = new StringTokenizer(rawPortList, ","); - while (tokenizer.hasMoreTokens()) { - String rawPort = tokenizer.nextToken().trim(); - if (!rawPort.isEmpty()) { - try { - ports.add(Integer.parseInt(rawPort)); - } catch (NumberFormatException e) { - log.log(Level.FINE, "Unable to parse port: " + rawPort, e); - } - } - } - return ports; - } - - private static ArrayList<Cookie> toCookieList(Iterable<? extends Cookie> cookies) { - ArrayList<Cookie> cookieList = new ArrayList<>(); - cookies.forEach(cookieList::add); - return cookieList; + if (headerVal == null) return Collections.emptyList(); + + ClientCookieDecoder encoder = ClientCookieDecoder.STRICT; + org.jboss.netty.handler.codec.http.cookie.Cookie nettyCookie = encoder.decode(headerVal); + return Collections.singletonList(new Cookie(nettyCookie.name(), nettyCookie.value()) + .setHttpOnly(nettyCookie.isHttpOnly()) + .setSecure(nettyCookie.isSecure()) + .setMaxAge(nettyCookie.maxAge(), TimeUnit.SECONDS) + .setPath(nettyCookie.path()) + .setDomain(nettyCookie.domain())); } } diff --git a/jdisc_http_service/src/test/java/com/yahoo/jdisc/http/CookieTestCase.java b/jdisc_http_service/src/test/java/com/yahoo/jdisc/http/CookieTestCase.java index ca12de72ec2..0c98f294c82 100644 --- a/jdisc_http_service/src/test/java/com/yahoo/jdisc/http/CookieTestCase.java +++ b/jdisc_http_service/src/test/java/com/yahoo/jdisc/http/CookieTestCase.java @@ -106,14 +106,14 @@ public class CookieTestCase { "foo.name=foo.value", Collections.singletonList(newCookie("foo"))); assertEncodeCookie( - "foo.name=foo.value;bar.name=bar.value", + "foo.name=foo.value; bar.name=bar.value", Arrays.asList(newCookie("foo"), newCookie("bar"))); } @Test public void requireThatSetCookieCanBeEncoded() { assertEncodeSetCookie( - Collections.singletonList("foo.name=foo.value;Path=path;Domain=domain;Secure;HttpOnly"), + Collections.singletonList("foo.name=foo.value; Path=path; Domain=domain; Secure; HTTPOnly"), Collections.singletonList(newSetCookie("foo"))); } @@ -131,7 +131,6 @@ public class CookieTestCase { } @Test - @SuppressWarnings("deprecation") public void requireThatSetCookieCanBeDecoded() { final Cookie foo = new Cookie(); foo.setName("foo.name"); @@ -141,7 +140,6 @@ public class CookieTestCase { foo.setMaxAge(0, TimeUnit.SECONDS); foo.setSecure(true); foo.setHttpOnly(true); - foo.setVersion(1); assertDecodeSetCookie(foo, "foo.name=foo.value;Max-Age=0;Path=path;Domain=domain;Secure;HTTPOnly;"); final Cookie bar = new Cookie(); @@ -150,7 +148,6 @@ public class CookieTestCase { bar.setPath("path"); bar.setDomain("domain"); bar.setMaxAge(0, TimeUnit.SECONDS); - bar.setVersion(1); assertDecodeSetCookie(bar, "bar.name=bar.value;Max-Age=0;Path=path;Domain=domain;"); } diff --git a/jdisc_http_service/src/test/java/com/yahoo/jdisc/http/server/jetty/HttpServerTest.java b/jdisc_http_service/src/test/java/com/yahoo/jdisc/http/server/jetty/HttpServerTest.java index 7ed13decbf6..221a1adc1fe 100644 --- a/jdisc_http_service/src/test/java/com/yahoo/jdisc/http/server/jetty/HttpServerTest.java +++ b/jdisc_http_service/src/test/java/com/yahoo/jdisc/http/server/jetty/HttpServerTest.java @@ -356,7 +356,7 @@ public class HttpServerTest { driver.client().get("/status.html") .expectStatusCode(is(OK)) .expectHeader("Set-Cookie", - is("foo=bar;Path=/foopath;Domain=.localhost;Secure;HttpOnly")); + is("foo=bar; Path=/foopath; Domain=.localhost; Secure; HTTPOnly")); assertThat(driver.close(), is(true)); } |