3232import java .text .DateFormat ;
3333import java .text .ParseException ;
3434import java .text .SimpleDateFormat ;
35- import java .util .ArrayList ;
36- import java .util .Calendar ;
37- import java .util .Collections ;
38- import java .util .Date ;
39- import java .util .GregorianCalendar ;
40- import java .util .LinkedHashMap ;
41- import java .util .List ;
42- import java .util .Map ;
43- import java .util .TimeZone ;
35+ import java .util .*;
4436import java .util .logging .Logger ;
4537
4638/**
4941 */
5042public final class RequestContent implements Serializable {
5143 private static final Logger LOGGER = Logger .getLogger (RequestContent .class .getName ());
44+
45+ /**
46+ * The official format of the Date header value (and other date-type headers) is defined by
47+ * RFC 1123 ({@link #DATE_FORMAT_RFC1123})
48+ */
49+ @ Deprecated
5250 public static final String DATE_FORMAT = "EEE MMM d HH:mm:ss yyyy zzz" ;
5351
52+ public static final String DATE_FORMAT_RFC1123 = "EEE, dd MMM yyyy HH:mm:ss zzz" ;
53+
54+ private static final List <String > SUPPORTED_DATE_FORMATS = Arrays .asList (DATE_FORMAT_RFC1123 , DATE_FORMAT );
55+
5456 private static final long serialVersionUID = -2968642080214687631L ;
5557
5658 @ Deprecated
@@ -77,14 +79,13 @@ public static final class Builder {
7779
7880 @ Deprecated
7981 public Builder setRequestLine (String requestLine ) {
80- LOGGER .warning ("[setRequestLine] Use of the request-line header is deprecated. Please use (request-target) instead." );
8182 this .requestLine = requestLine ;
8283 return this ;
8384 }
8485
8586 public Builder setRequestTarget (String method , String path ) {
86- this .method = method . toUpperCase ();
87- this .path = path ;
87+ this .method = method != null ? method . trim (). toUpperCase () : null ;
88+ this .path = path != null ? path . trim () : null ;
8889 return this ;
8990 }
9091
@@ -96,23 +97,28 @@ public Builder setRequestTarget(String method, String path) {
9697 * @return
9798 */
9899 public Builder addHeader (final String name , final String value ) {
99- final String _name = name .toLowerCase ();
100- if (Constants .IGNORE_HEADERS .contains (_name ) || _name .startsWith (":" )) {
100+ if (value != null ) {
101+ final String _value = value .trim ();
102+ final String _name = name .trim ().toLowerCase ();
103+ if (Constants .IGNORE_HEADERS .contains (_name ) || _name .startsWith (":" )) {
101104 /* skip ignored headers and names which begin with a colon */
102- return this ;
103- } else if (Constants .HEADER_REQUEST_TARGET .equals (_name )) {
104- return this ;
105- } else if (!Constants .HEADER_DATE .equals (_name ) || tryParseDate (value )) {
106- List <String > values = null ;
107- if (headers .containsKey (_name )) {
108- headers .get (_name );
109- } else {
110- values = new ArrayList <String >();
111- headers .put (_name , values );
112- }
105+ return this ;
106+ } else if (Constants .HEADER_REQUEST_LINE .equals (_name )) {
107+ return this ;
108+ } else if (Constants .HEADER_REQUEST_TARGET .equals (_name )) {
109+ return this ;
110+ } else if (!Constants .HEADER_DATE .equals (_name ) || tryParseDate (_value ) != null ) {
111+ List <String > values = null ;
112+ if (headers .containsKey (_name )) {
113+ headers .get (_name );
114+ } else {
115+ values = new ArrayList <String >();
116+ headers .put (_name , values );
117+ }
113118
114- if (values != null ) {
115- values .add (value );
119+ if (values != null ) {
120+ values .add (_value );
121+ }
116122 }
117123 }
118124 return this ;
@@ -128,7 +134,7 @@ public Builder addHeader(final String name, final String value) {
128134 */
129135 public Builder addDate (Calendar calendar ) {
130136 if (calendar != null ) {
131- DateFormat dateFormat = new SimpleDateFormat (DATE_FORMAT );
137+ DateFormat dateFormat = new SimpleDateFormat (DATE_FORMAT_RFC1123 );
132138 dateFormat .setTimeZone (calendar .getTimeZone ());
133139 this .addHeader (Constants .HEADER_DATE , dateFormat .format (calendar .getTime ()));
134140 }
@@ -186,18 +192,22 @@ public byte[] getContent(List<String> headers, Charset charset) {
186192 * @return
187193 */
188194 public String getContentString (List <String > headers ) {
189- StringBuilder hashBuilder = new StringBuilder ("" );
195+ StringBuilder hashBuilder = new StringBuilder ();
190196 if (headers != null ) {
191197 for (String header : headers ) {
192198 String _header = header .toLowerCase ();
193199 if (!Constants .IGNORE_HEADERS .contains (_header ) && !_header .startsWith (":" )) {
194- if (Constants .HEADER_REQUEST_TARGET .equals (_header )) {
200+ if (Constants .HEADER_REQUEST_LINE .equals (_header )) {
201+ if (this .requestLine != null ) {
202+ hashBuilder .append (this .requestLine ).append ('\n' );
203+ }
204+ } else if (Constants .HEADER_REQUEST_TARGET .equals (_header )) {
195205 if (this .getRequestTarget () != null ) {
196- hashBuilder .append (this .getRequestTarget ()).append (" \n " );
206+ hashBuilder .append (this .getRequestTarget ()).append ('\n' );
197207 }
198208 } else {
199209 for (String value : this .getHeaderValues (_header )) {
200- hashBuilder .append (_header ).append (": " ).append (value ).append (" \n " );
210+ hashBuilder .append (_header ).append (": " ).append (value ).append ('\n' );
201211 }
202212 }
203213 }
@@ -224,7 +234,6 @@ public List<String> getHeaderNames() {
224234 return Collections .unmodifiableList (headerNames );
225235 }
226236
227-
228237 /**
229238 * @return the request-line if set
230239 */
@@ -258,7 +267,12 @@ public String getDate() {
258267 */
259268 public List <String > getHeaderValues (String name ) {
260269 String _name = name .toLowerCase ();
261- if (Constants .HEADER_REQUEST_TARGET .equals (_name )) {
270+ if (Constants .HEADER_REQUEST_LINE .equals (_name )) {
271+ LOGGER .warning ("[getHeaderValues] Use of the request-line header is deprecated. Please use (request-target) instead." );
272+ return this .requestLine != null ? Collections .singletonList (
273+ this .requestLine
274+ ) : Collections .<String >emptyList ();
275+ } else if (Constants .HEADER_REQUEST_TARGET .equals (_name )) {
262276 return this .getRequestTarget () != null ? Collections .singletonList (
263277 this .getRequestTarget ()
264278 ) : Collections .<String >emptyList ();
@@ -272,38 +286,34 @@ public List<String> getHeaderValues(String name) {
272286 /**
273287 * Sets the literal date header value.
274288 *
275- * @param date a date string conforming to {@link #DATE_FORMAT}
289+ * @param date a date string conforming to {@link #DATE_FORMAT_RFC1123} or to the deprecated {@link # DATE_FORMAT}
276290 * @return true if the date header was set successfully. false if the header is already set or the provided
277- * string does not conform to {@link #DATE_FORMAT}
291+ * string does not conform to {@link #DATE_FORMAT_RFC1123} or to {@link # DATE_FORMAT}
278292 */
279- private static boolean tryParseDate (String date ) {
293+ protected static Date tryParseDate (String date ) {
280294 if (date != null ) {
281- try {
282- DateFormat dateFormat = new SimpleDateFormat (DATE_FORMAT );
283- dateFormat .parse (date );
284- return true ;
285- } catch (ParseException e ) {
286- LOGGER .warning ("[addDate] date string " + date + " does not match format " + DATE_FORMAT );
295+
296+ for (String formatString : SUPPORTED_DATE_FORMATS ) {
297+ try {
298+ DateFormat dateFormat = new SimpleDateFormat (formatString );
299+ dateFormat .setTimeZone (getGMT ());
300+ return dateFormat .parse (date );
301+ } catch (ParseException e ) {
302+ LOGGER .warning ("[tryParseDate] date string " + date + " does not match format " + formatString );
303+ }
287304 }
288305 }
289- return false ;
306+ return null ;
290307 }
291308
292-
293309 /**
294310 * Returns the currently set date header value converted to a {@link Date} object in the GMT time zone
295311 *
296312 * @return a {@link Date} object in GMT or null if header is not set or not valid
297313 */
298314 public Date getDateGMT () {
299315 if (this .getDate () != null ) {
300- try {
301- DateFormat dateFormat = new SimpleDateFormat (DATE_FORMAT );
302- dateFormat .setTimeZone (getGMT ());
303- return dateFormat .parse (this .getDate ());
304- } catch (ParseException e ) {
305- LOGGER .warning ("[getDateGMT] date string " + this .getDate () + " does not match format " + DATE_FORMAT );
306- }
316+ return tryParseDate (this .getDate ());
307317 }
308318 return null ;
309319 }
@@ -316,8 +326,8 @@ public Date getDateGMT() {
316326 * @return a {@link Calendar} in the specified time zone or in the default time zone if the timeZone parameter is null
317327 */
318328 public Calendar getDateTZ (TimeZone timeZone ) {
319- Date dateGMT = this .getDateGMT ();
320329 TimeZone tz = timeZone != null ? timeZone : TimeZone .getDefault ();
330+ Date dateGMT = this .getDateGMT ();
321331 if (dateGMT != null ) {
322332 Calendar calGMT = new GregorianCalendar (getGMT ());
323333 calGMT .setTime (dateGMT );
0 commit comments