1
1
/*
2
- * Copyright 2002-2015 the original author or authors.
2
+ * Copyright 2002-2016 the original author or authors.
3
3
*
4
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
5
* you may not use this file except in compliance with the License.
21
21
import java .util .Iterator ;
22
22
import java .util .Locale ;
23
23
import java .util .Map ;
24
+
24
25
import javax .servlet .http .HttpServletRequest ;
25
26
import javax .servlet .http .HttpServletResponse ;
26
27
import javax .servlet .http .HttpSession ;
@@ -47,6 +48,8 @@ public class ServletWebRequest extends ServletRequestAttributes implements Nativ
47
48
48
49
private static final String HEADER_IF_MODIFIED_SINCE = "If-Modified-Since" ;
49
50
51
+ private static final String HEADER_IF_UNMODIFIED_SINCE = "If-Unmodified-Since" ;
52
+
50
53
private static final String HEADER_IF_NONE_MATCH = "If-None-Match" ;
51
54
52
55
private static final String HEADER_LAST_MODIFIED = "Last-Modified" ;
@@ -55,6 +58,12 @@ public class ServletWebRequest extends ServletRequestAttributes implements Nativ
55
58
56
59
private static final String METHOD_HEAD = "HEAD" ;
57
60
61
+ private static final String METHOD_POST = "POST" ;
62
+
63
+ private static final String METHOD_PUT = "PUT" ;
64
+
65
+ private static final String METHOD_DELETE = "DELETE" ;
66
+
58
67
59
68
/** Checking for Servlet 3.0+ HttpServletResponse.getHeader(String) */
60
69
private static final boolean servlet3Present =
@@ -183,11 +192,18 @@ public boolean checkNotModified(long lastModifiedTimestamp) {
183
192
if (isCompatibleWithConditionalRequests (response )) {
184
193
this .notModified = isTimestampNotModified (lastModifiedTimestamp );
185
194
if (response != null ) {
186
- if (this .notModified && supportsNotModifiedStatus ()) {
187
- response .setStatus (HttpServletResponse .SC_NOT_MODIFIED );
195
+ if (supportsNotModifiedStatus ()) {
196
+ if (this .notModified ) {
197
+ response .setStatus (HttpServletResponse .SC_NOT_MODIFIED );
198
+ }
199
+ if (isHeaderAbsent (response , HEADER_LAST_MODIFIED )) {
200
+ response .setDateHeader (HEADER_LAST_MODIFIED , lastModifiedTimestamp );
201
+ }
188
202
}
189
- if (isHeaderAbsent (response , HEADER_LAST_MODIFIED )) {
190
- response .setDateHeader (HEADER_LAST_MODIFIED , lastModifiedTimestamp );
203
+ else if (supportsConditionalUpdate ()) {
204
+ if (this .notModified ) {
205
+ response .setStatus (HttpServletResponse .SC_PRECONDITION_FAILED );
206
+ }
191
207
}
192
208
}
193
209
}
@@ -223,14 +239,21 @@ public boolean checkNotModified(String etag, long lastModifiedTimestamp) {
223
239
etag = addEtagPadding (etag );
224
240
this .notModified = isEtagNotModified (etag ) && isTimestampNotModified (lastModifiedTimestamp );
225
241
if (response != null ) {
226
- if (this .notModified && supportsNotModifiedStatus ()) {
227
- response .setStatus (HttpServletResponse .SC_NOT_MODIFIED );
228
- }
229
- if (isHeaderAbsent (response , HEADER_ETAG )) {
230
- response .setHeader (HEADER_ETAG , etag );
242
+ if (supportsNotModifiedStatus ()) {
243
+ if (this .notModified ) {
244
+ response .setStatus (HttpServletResponse .SC_NOT_MODIFIED );
245
+ }
246
+ if (isHeaderAbsent (response , HEADER_ETAG )) {
247
+ response .setHeader (HEADER_ETAG , etag );
248
+ }
249
+ if (isHeaderAbsent (response , HEADER_LAST_MODIFIED )) {
250
+ response .setDateHeader (HEADER_LAST_MODIFIED , lastModifiedTimestamp );
251
+ }
231
252
}
232
- if (isHeaderAbsent (response , HEADER_LAST_MODIFIED )) {
233
- response .setDateHeader (HEADER_LAST_MODIFIED , lastModifiedTimestamp );
253
+ else if (supportsConditionalUpdate ()) {
254
+ if (this .notModified ) {
255
+ response .setStatus (HttpServletResponse .SC_PRECONDITION_FAILED );
256
+ }
234
257
}
235
258
}
236
259
}
@@ -250,7 +273,8 @@ private boolean isCompatibleWithConditionalRequests(HttpServletResponse response
250
273
return true ;
251
274
}
252
275
return HttpStatus .valueOf (response .getStatus ()).is2xxSuccessful ();
253
- } catch (IllegalArgumentException e ) {
276
+ }
277
+ catch (IllegalArgumentException e ) {
254
278
return true ;
255
279
}
256
280
}
@@ -268,27 +292,46 @@ private boolean supportsNotModifiedStatus() {
268
292
return (METHOD_GET .equals (method ) || METHOD_HEAD .equals (method ));
269
293
}
270
294
271
- @ SuppressWarnings ("deprecation" )
295
+ private boolean supportsConditionalUpdate () {
296
+ String method = getRequest ().getMethod ();
297
+ String ifUnmodifiedHeader = getRequest ().getHeader (HEADER_IF_UNMODIFIED_SINCE );
298
+ return (METHOD_POST .equals (method ) || METHOD_PUT .equals (method ) || METHOD_DELETE .equals (method ))
299
+ && StringUtils .hasLength (ifUnmodifiedHeader );
300
+ }
301
+
272
302
private boolean isTimestampNotModified (long lastModifiedTimestamp ) {
273
- long ifModifiedSince = -1 ;
303
+ long ifModifiedSince = parseDateHeader (HEADER_IF_MODIFIED_SINCE );
304
+ if (ifModifiedSince != -1 ) {
305
+ return (ifModifiedSince >= (lastModifiedTimestamp / 1000 * 1000 ));
306
+ }
307
+ long ifUnmodifiedSince = parseDateHeader (HEADER_IF_UNMODIFIED_SINCE );
308
+ if (ifUnmodifiedSince != -1 ) {
309
+ return (ifUnmodifiedSince < (lastModifiedTimestamp / 1000 * 1000 ));
310
+ }
311
+ return false ;
312
+ }
313
+
314
+ @ SuppressWarnings ("deprecation" )
315
+ private long parseDateHeader (String headerName ) {
316
+ long dateValue = -1 ;
274
317
try {
275
- ifModifiedSince = getRequest ().getDateHeader (HEADER_IF_MODIFIED_SINCE );
318
+ dateValue = getRequest ().getDateHeader (headerName );
276
319
}
277
320
catch (IllegalArgumentException ex ) {
278
- String headerValue = getRequest ().getHeader (HEADER_IF_MODIFIED_SINCE );
321
+ String headerValue = getRequest ().getHeader (headerName );
279
322
// Possibly an IE 10 style value: "Wed, 09 Apr 2014 09:57:42 GMT; length=13774"
280
323
int separatorIndex = headerValue .indexOf (';' );
281
324
if (separatorIndex != -1 ) {
282
325
String datePart = headerValue .substring (0 , separatorIndex );
283
326
try {
284
- ifModifiedSince = Date .parse (datePart );
327
+ dateValue = Date .parse (datePart );
285
328
}
286
329
catch (IllegalArgumentException ex2 ) {
287
330
// Giving up
288
331
}
289
332
}
290
333
}
291
- return ( ifModifiedSince >= ( lastModifiedTimestamp / 1000 * 1000 )) ;
334
+ return dateValue ;
292
335
}
293
336
294
337
private boolean isEtagNotModified (String etag ) {
0 commit comments