diff --git a/README.rst b/README.rst
index ee41933..50ad997 100644
--- a/README.rst
+++ b/README.rst
@@ -2,7 +2,7 @@ netty-http
==========
A library to develop HTTP services with `Netty `__. Supports the capability to route end-points based on `JAX-RS `__-style annotations. Implements Guava's Service interface to manage the runtime-state of the HTTP service.
-Need for this library
+Need for this library
---------------------
`Netty `__ is a powerful framework to write asynchronous event-driven high-performance applications. While it is relatively easy to write a RESTful HTTP service using netty, the mapping between HTTP routes to handlers is
not a straight-forward task.
@@ -142,7 +142,7 @@ Example: Sample HTTP service that manages an application lifecycle:
// Setup HTTP service and add Handlers
- // You can either add varargs of HttpHandler or as a list of HttpHanlders as below to the NettyService Builder
+ // You can either add varargs of HttpHandler or as a list of HttpHandlers as below to the NettyService Builder
List handlers = new ArrayList<>();
handlers.add(new PingHandler());
@@ -175,7 +175,7 @@ Code Sample:
.setCertificatePassword("certificatePassword").build())
.build();
-* Set ``String:certificatePassword`` as "null" when not applicable
+* Set ``String:certificatePassword`` as "null" when not applicable
* ``File:keyStore`` points to the key store that holds your SSL certificate
References
diff --git a/src/main/java/io/cdap/http/internal/CookieParser.java b/src/main/java/io/cdap/http/internal/CookieParser.java
new file mode 100644
index 0000000..00f5754
--- /dev/null
+++ b/src/main/java/io/cdap/http/internal/CookieParser.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright © 2017-2019 Cask Data, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package io.cdap.http.internal;
+
+import io.netty.handler.codec.http.HttpHeaderNames;
+import io.netty.handler.codec.http.HttpRequest;
+import io.netty.handler.codec.http.cookie.Cookie;
+import io.netty.handler.codec.http.cookie.CookieDecoder;
+import io.netty.handler.codec.http.cookie.ServerCookieDecoder;
+
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Parses cookies from a request.
+ */
+public class CookieParser {
+ private final boolean strict;
+
+ public CookieParser(boolean strict) {
+ this.strict = strict;
+ }
+
+ public Map parseCookies(HttpRequest request) {
+ List headers = request.headers().getAll(HttpHeaderNames.COOKIE);
+ if (headers == null || headers.isEmpty()) {
+ return Collections.emptyMap();
+ }
+ ServerCookieDecoder decoder = getCookieDecoder();
+ Map cookies = new LinkedHashMap<>();
+ for (String value : headers) {
+ for (Cookie cookie : decoder.decode(value)) {
+ cookies.put(cookie.name(), cookie);
+ }
+ }
+ return cookies;
+ }
+
+ private ServerCookieDecoder getCookieDecoder() {
+ return strict ? ServerCookieDecoder.STRICT : ServerCookieDecoder.LAX;
+ }
+}
diff --git a/src/main/java/io/cdap/http/internal/HttpResourceModel.java b/src/main/java/io/cdap/http/internal/HttpResourceModel.java
index 96f0cc3..49d3bef 100644
--- a/src/main/java/io/cdap/http/internal/HttpResourceModel.java
+++ b/src/main/java/io/cdap/http/internal/HttpResourceModel.java
@@ -23,6 +23,8 @@
import io.netty.handler.codec.http.HttpRequest;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.handler.codec.http.QueryStringDecoder;
+import io.netty.handler.codec.http.cookie.Cookie;
+import io.netty.handler.codec.http.cookie.DefaultCookie;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
@@ -36,6 +38,7 @@
import java.util.Map;
import java.util.Set;
import javax.annotation.Nullable;
+import javax.ws.rs.CookieParam;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.PathParam;
@@ -48,7 +51,8 @@
public final class HttpResourceModel {
private static final Set> SUPPORTED_PARAM_ANNOTATIONS =
- Collections.unmodifiableSet(new HashSet<>(Arrays.asList(PathParam.class, QueryParam.class, HeaderParam.class)));
+ Collections.unmodifiableSet(new HashSet<>(Arrays.asList(PathParam.class, QueryParam.class, HeaderParam.class,
+ CookieParam.class)));
private final Set httpMethods;
private final String path;
@@ -58,6 +62,7 @@ public final class HttpResourceModel {
private final ExceptionHandler exceptionHandler;
private final boolean isSecured;
private final String[] requiredRoles;
+ private final CookieParser cookieParser = new CookieParser(false);
/**
* Construct a resource model with HttpMethod, method that handles httprequest, Object that contains the method.
@@ -137,6 +142,9 @@ public HttpMethodInfo handle(HttpRequest request,
if (info.containsKey(HeaderParam.class)) {
args[idx] = getHeaderParamValue(info, request);
}
+ if (info.containsKey(CookieParam.class)) {
+ args[idx] = getCookieParamValue(info, request);
+ }
idx++;
}
@@ -195,6 +203,16 @@ private Object getHeaderParamValue(Map, ParameterInf
return hasHeader ? info.convert(request.headers().getAll(headerName)) : info.convert(defaultValue(annotations));
}
+ @SuppressWarnings("unchecked")
+ private Object getCookieParamValue(Map, ParameterInfo>> annotations,
+ HttpRequest request) throws Exception {
+ Map cookies = cookieParser.parseCookies(request);
+ ParameterInfo info = (ParameterInfo) annotations.get(CookieParam.class);
+ CookieParam cookieParam = info.getAnnotation();
+ String cookieName = cookieParam.value();
+ boolean hasCookie = cookies.containsKey(cookieName);
+ return hasCookie ? info.convert(cookies.get(cookieName)) : info.convert(defaultCookie(cookieName, annotations));
+ }
/**
* Returns a List of String created based on the {@link DefaultValue} if it is presented in the annotations Map.
*
@@ -210,6 +228,19 @@ private List defaultValue(Map, ParameterInfo
return Collections.singletonList(defaultValue.value());
}
+ /**
+ * Returns a Cookie created based on the {@link DefaultValue} if it is presented in the annotations Map.
+ *
+ * @return a Cookie or null if {@link DefaultValue} is not presented
+ */
+ private Cookie defaultCookie(String name, Map, ParameterInfo>> annotations) {
+ List strings = defaultValue(annotations);
+ if (strings == null || strings.isEmpty()) {
+ return null;
+ }
+ return new DefaultCookie(name, strings.get(0));
+ }
+
/**
* Gathers all parameters' annotations for the given method, starting from the third parameter.
*/
@@ -239,6 +270,9 @@ private List