View Javadoc
1   /*
2    * Copyright 2015 The Netty Project
3    *
4    * The Netty Project licenses this file to you under the Apache License,
5    * version 2.0 (the "License"); you may not use this file except in compliance
6    * with the License. You may obtain a copy of the License at:
7    *
8    *   http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13   * License for the specific language governing permissions and limitations
14   * under the License.
15   */
16  package org.jboss.netty.handler.codec.http.cookie;
17  
18  import static org.jboss.netty.handler.codec.http.cookie.CookieUtil.*;
19  
20  import org.jboss.netty.handler.codec.http.HttpHeaderDateFormat;
21  import org.jboss.netty.handler.codec.http.HttpRequest;
22  
23  import java.util.ArrayList;
24  import java.util.Collection;
25  import java.util.Collections;
26  import java.util.Date;
27  import java.util.List;
28  
29  /**
30   * A <a href="http://tools.ietf.org/html/rfc6265">RFC6265</a> compliant cookie encoder to be used server side,
31   * so some fields are sent (Version is typically ignored).
32   *
33   * As Netty's Cookie merges Expires and MaxAge into one single field, only Max-Age field is sent.
34   *
35   * Note that multiple cookies are supposed to be sent at once in a single "Set-Cookie" header.
36   *
37   * <pre>
38   * // Example
39   * {@link HttpRequest} req = ...;
40   * res.setHeader("Cookie", {@link ServerCookieEncoder}.encode("JSESSIONID", "1234"));
41   * </pre>
42   *
43   * @see ServerCookieDecoder
44   */
45  public final class ServerCookieEncoder extends CookieEncoder {
46  
47      /**
48       * Strict encoder that validates that name and value chars are in the valid scope
49       * defined in RFC6265
50       */
51      public static final ServerCookieEncoder STRICT = new ServerCookieEncoder(true);
52  
53      /**
54       * Lax instance that doesn't validate name and value
55       */
56      public static final ServerCookieEncoder LAX = new ServerCookieEncoder(false);
57  
58      private ServerCookieEncoder(boolean strict) {
59          super(strict);
60      }
61  
62      /**
63       * Encodes the specified cookie name-value pair into a Set-Cookie header value.
64       *
65       * @param name the cookie name
66       * @param value the cookie value
67       * @return a single Set-Cookie header value
68       */
69      public String encode(String name, String value) {
70          return encode(new DefaultCookie(name, value));
71      }
72  
73      /**
74       * Encodes the specified cookie into a Set-Cookie header value.
75       *
76       * @param cookie the cookie
77       * @return a single Set-Cookie header value
78       */
79      public String encode(Cookie cookie) {
80          if (cookie == null) {
81              throw new NullPointerException("cookie");
82          }
83          final String name = cookie.name();
84          final String value = cookie.value() != null ? cookie.value() : "";
85  
86          validateCookie(name, value);
87  
88          StringBuilder buf = new StringBuilder();
89  
90          if (cookie.wrap()) {
91              addQuoted(buf, name, value);
92          } else {
93              add(buf, name, value);
94          }
95  
96          if (cookie.maxAge() != Integer.MIN_VALUE) {
97              add(buf, CookieHeaderNames.MAX_AGE, cookie.maxAge());
98              Date expires = new Date((long) cookie.maxAge() * 1000 + System.currentTimeMillis());
99              add(buf, CookieHeaderNames.EXPIRES, HttpHeaderDateFormat.get().format(expires));
100         }
101 
102         if (cookie.path() != null) {
103             add(buf, CookieHeaderNames.PATH, cookie.path());
104         }
105 
106         if (cookie.domain() != null) {
107             add(buf, CookieHeaderNames.DOMAIN, cookie.domain());
108         }
109         if (cookie.isSecure()) {
110             add(buf, CookieHeaderNames.SECURE);
111         }
112         if (cookie.isHttpOnly()) {
113             add(buf, CookieHeaderNames.HTTPONLY);
114         }
115 
116         return stripTrailingSeparator(buf);
117     }
118 
119     /**
120      * Batch encodes cookies into Set-Cookie header values.
121      *
122      * @param cookies a bunch of cookies
123      * @return the corresponding bunch of Set-Cookie headers
124      */
125     public List<String> encode(Cookie... cookies) {
126         if (cookies == null) {
127             throw new NullPointerException("cookies");
128         }
129         if (cookies.length == 0) {
130             return Collections.emptyList();
131         }
132 
133         List<String> encoded = new ArrayList<String>(cookies.length);
134         for (Cookie c : cookies) {
135             if (c == null) {
136                 break;
137             }
138             encoded.add(encode(c));
139         }
140         return encoded;
141     }
142 
143     /**
144      * Batch encodes cookies into Set-Cookie header values.
145      *
146      * @param cookies a bunch of cookies
147      * @return the corresponding bunch of Set-Cookie headers
148      */
149     public List<String> encode(Collection<? extends Cookie> cookies) {
150         if (cookies == null) {
151             throw new NullPointerException("cookies");
152         }
153         if (cookies.isEmpty()) {
154             return Collections.emptyList();
155         }
156 
157         List<String> encoded = new ArrayList<String>(cookies.size());
158         for (Cookie c : cookies) {
159             if (c == null) {
160                 break;
161             }
162             encoded.add(encode(c));
163         }
164         return encoded;
165     }
166 
167     /**
168      * Batch encodes cookies into Set-Cookie header values.
169      *
170      * @param cookies a bunch of cookies
171      * @return the corresponding bunch of Set-Cookie headers
172      */
173     public List<String> encode(Iterable<? extends Cookie> cookies) {
174         if (cookies == null) {
175             throw new NullPointerException("cookies");
176         }
177         if (cookies.iterator().hasNext()) {
178             return Collections.emptyList();
179         }
180 
181         List<String> encoded = new ArrayList<String>();
182         for (Cookie c : cookies) {
183             if (c == null) {
184                 break;
185             }
186             encoded.add(encode(c));
187         }
188         return encoded;
189     }
190 }