Skip to content

Commit dc6f513

Browse files
committed
Added support of 'Access-Control-Max-Age'. Issue #1109. Reported by Tal Liron.
1 parent 2beef8b commit dc6f513

File tree

7 files changed

+181
-57
lines changed

7 files changed

+181
-57
lines changed

build/tmpl/text/changes.txt

+2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ Changes log
1010
- Fixed support of non-bytes ranges. Issue #1132.
1111
- Fixed encoding issue when using CookieAuthenticator. Issue #1159.
1212
Reported by Arjohn Kampman.
13+
- Added support of 'Access-Control-Max-Age'. Issue #1109.
14+
Reported by Tal Liron.
1315

1416
- 2.3.7 (03/14/2016)
1517
- Bugs fixed

modules/org.restlet/src/org/restlet/Response.java

+43-18
Original file line numberDiff line numberDiff line change
@@ -116,8 +116,13 @@ public static void setCurrent(Response response) {
116116
private volatile Set<String> accessControlExposeHeaders;
117117

118118
/**
119-
* Estimated amount of time since a response was generated or revalidated by
120-
* the origin server.
119+
* When used in the context of CORS support, it indicates how long the results of a preflight request can be cached
120+
* in a preflight result cache.
121+
*/
122+
private volatile int accessControlMaxAge;
123+
124+
/**
125+
* Estimated amount of time since a response was generated or revalidated by the origin server.
121126
*/
122127
private volatile int age;
123128

@@ -328,6 +333,17 @@ public Set<String> getAccessControlExposeHeaders() {
328333
return a;
329334
}
330335

336+
/**
337+
* Indicates how long the results of a preflight CORS request can be cached in a preflight result cache.<br>
338+
* In case of a negative value, the results of a preflight request is not meant to be cached.<br>
339+
* Note that when used with HTTP connectors, this property maps to the "Access-Control-Max-Age" header.
340+
*
341+
* @return Indicates how long the results of a preflight request can be cached in a preflight result cache.
342+
*/
343+
public int getAccessControlMaxAge() {
344+
return accessControlMaxAge;
345+
}
346+
331347
/**
332348
* Returns the estimated amount of time since a response was generated or
333349
* revalidated by the origin server. Origin servers should leave the 0
@@ -541,8 +557,7 @@ public Status getStatus() {
541557
* processing a request on the server-side, setting this property to 'false'
542558
* let you ask to the server connector to wait before sending the response
543559
* back to the client when the initial calling thread returns. This will let
544-
* you do further updates to the response and manually calling
545-
* {@link #commit()} later on, using another thread.
560+
* you do further updates to the response and manually calling {@link #commit()} later on, using another thread.
546561
*
547562
* @return True if the response should be automatically committed.
548563
*/
@@ -565,8 +580,7 @@ public boolean isConfidential() {
565580
}
566581

567582
/**
568-
* Indicates if the response is final or provisional. It relies on the
569-
* {@link Status#isInformational()} method.
583+
* Indicates if the response is final or provisional. It relies on the {@link Status#isInformational()} method.
570584
*
571585
* @return True if the response is final.
572586
*/
@@ -575,8 +589,7 @@ public boolean isFinal() {
575589
}
576590

577591
/**
578-
* Indicates if the response is provisional or final. It relies on the
579-
* {@link Status#isInformational()} method.
592+
* Indicates if the response is provisional or final. It relies on the {@link Status#isInformational()} method.
580593
*
581594
* @return True if the response is provisional.
582595
*/
@@ -601,8 +614,8 @@ public void redirectPermanent(Reference targetRef) {
601614
* to reuse the same method for the new request.<br>
602615
* <br>
603616
* If you pass a relative target URI, it will be resolved with the current
604-
* base reference of the request's resource reference (see
605-
* {@link Request#getResourceRef()} and {@link Reference#getBaseRef()}.
617+
* base reference of the request's resource reference (see {@link Request#getResourceRef()} and
618+
* {@link Reference#getBaseRef()}.
606619
*
607620
* @param targetUri
608621
* The target URI.
@@ -635,8 +648,8 @@ public void redirectSeeOther(Reference targetRef) {
635648
* originally requested resource.<br>
636649
* <br>
637650
* If you pass a relative target URI, it will be resolved with the current
638-
* base reference of the request's resource reference (see
639-
* {@link Request#getResourceRef()} and {@link Reference#getBaseRef()}.
651+
* base reference of the request's resource reference (see {@link Request#getResourceRef()} and
652+
* {@link Reference#getBaseRef()}.
640653
*
641654
* @param targetUri
642655
* The target URI.
@@ -663,8 +676,8 @@ public void redirectTemporary(Reference targetRef) {
663676
* to reuse the same method for the new request.<br>
664677
* <br>
665678
* If you pass a relative target URI, it will be resolved with the current
666-
* base reference of the request's resource reference (see
667-
* {@link Request#getResourceRef()} and {@link Reference#getBaseRef()}.
679+
* base reference of the request's resource reference (see {@link Request#getResourceRef()} and
680+
* {@link Reference#getBaseRef()}.
668681
*
669682
* @param targetUri
670683
* The target URI.
@@ -688,6 +701,19 @@ public void setAccessControlAllowCredentials(
688701
this.accessControlAllowCredentials = accessControlAllowCredentials;
689702
}
690703

704+
/**
705+
* When used as part of a response to a preflight CORS request, indicates how long (in seconds) the results of a
706+
* preflight request can be cached in a preflight result cache.<br>
707+
* Note that when used with HTTP connectors, this property maps to the "Access-Control-Max-Age" header.<br>
708+
* In case of negative value, the header is not set.
709+
*
710+
* @param accessControlMaxAge
711+
* How long the results of a preflight request can be cached in a preflight result cache.
712+
*/
713+
public void setAccessControlMaxAge(int accessControlMaxAge) {
714+
this.accessControlMaxAge = accessControlMaxAge;
715+
}
716+
691717
/**
692718
* Sets the set of headers allowed by the actual request on the current
693719
* resource when used as part of a response to a preflight CORS request.<br>
@@ -928,8 +954,7 @@ public void setLocationRef(Reference locationRef) {
928954
* Sets the reference that the client should follow for redirections or
929955
* resource creations. If you pass a relative location URI, it will be
930956
* resolved with the current base reference of the request's resource
931-
* reference (see {@link Request#getResourceRef()} and
932-
* {@link Reference#getBaseRef()}.<br>
957+
* reference (see {@link Request#getResourceRef()} and {@link Reference#getBaseRef()}.<br>
933958
* <br>
934959
* Note that when used with HTTP connectors, this property maps to the
935960
* "Location" header.
@@ -954,8 +979,8 @@ public void setLocationRef(String locationUri) {
954979

955980
/**
956981
* Sets the modifiable list of authentication requests sent by a proxy to a
957-
* client. The list instance set must be thread-safe (use
958-
* {@link CopyOnWriteArrayList} for example. Note that when used with HTTP
982+
* client. The list instance set must be thread-safe (use {@link CopyOnWriteArrayList} for example. Note that when
983+
* used with HTTP
959984
* connectors, this property maps to the "Proxy-Authenticate" header. This
960985
* method clears the current list and adds all entries in the parameter
961986
* list.

modules/org.restlet/src/org/restlet/engine/application/CorsFilter.java

+64-31
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,8 @@ public class CorsFilter extends Filter {
6767
private boolean allowedCredentials = false;
6868

6969
/**
70-
* The value of 'Access-Control-Allow-Headers' response header. Used only if
71-
* {@link #allowAllRequestedHeaders} is false.
70+
* The value of 'Access-Control-Allow-Headers' response header. Used only if {@link #allowAllRequestedHeaders} is
71+
* false.
7272
*/
7373
private Set<String> allowedHeaders = null;
7474

@@ -78,17 +78,23 @@ public class CorsFilter extends Filter {
7878
/** Helper for generating CORS response. */
7979
private CorsResponseHelper corsResponseHelper;
8080

81-
/** The set of methods allowed by default, used when {@link #skippingResourceForCorsOptions} is turned on. By default: GET, PUT, POST, DELETE, PATCH. */
81+
/**
82+
* The set of methods allowed by default, used when {@link #skippingResourceForCorsOptions} is turned on. By
83+
* default: GET, PUT, POST, DELETE, PATCH.
84+
*/
8285
private Set<Method> defaultAllowedMethods = new HashSet<>(Arrays.asList(Method.GET, Method.POST, Method.PUT,
8386
Method.DELETE, Method.PATCH));
8487

8588
/** The value of 'Access-Control-Expose-Headers' response header. */
8689
private Set<String> exposedHeaders = null;
8790

91+
/** The value of 'Access-Control-Max-Age' response header. Default is that the header is not set. */
92+
private int maxAge = -1;
93+
8894
/**
8995
* If true, the filter does not call the server resource for OPTIONS method
90-
* of CORS request and set Access-Control-Allow-Methods header with
91-
* {@link #defaultAllowedMethods}. Default is false.
96+
* of CORS request and set Access-Control-Allow-Methods header with {@link #defaultAllowedMethods}. Default is
97+
* false.
9298
*/
9399
private boolean skippingResourceForCorsOptions = false;
94100

@@ -122,9 +128,22 @@ public CorsFilter(Context context, Restlet next) {
122128
}
123129

124130
/**
125-
* Skip the call to the server resource if the {@link #skippingResourceForCorsOptions}
126-
* is true and if the current request use the OPTIONS method and is a CORS request.
127-
*
131+
* Add CORS headers to response
132+
*
133+
* @param request
134+
* The request to handle.
135+
* @param response
136+
* The response
137+
*/
138+
@Override
139+
protected void afterHandle(Request request, Response response) {
140+
getCorsResponseHelper().addCorsResponseHeaders(request, response);
141+
}
142+
143+
/**
144+
* Skip the call to the server resource if the {@link #skippingResourceForCorsOptions} is true and if the current
145+
* request use the OPTIONS method and is a CORS request.
146+
*
128147
* @param request
129148
* The request to handle.
130149
* @param response
@@ -142,19 +161,6 @@ && getCorsResponseHelper().isCorsRequest(request)) {
142161
}
143162
}
144163

145-
/**
146-
* Add CORS headers to response
147-
*
148-
* @param request
149-
* The request to handle.
150-
* @param response
151-
* The response
152-
*/
153-
@Override
154-
protected void afterHandle(Request request, Response response) {
155-
getCorsResponseHelper().addCorsResponseHeaders(request, response);
156-
}
157-
158164
/**
159165
* Returns the modifiable set of headers allowed by the actual request on
160166
* the current resource.<br>
@@ -181,8 +187,7 @@ public Set<String> getAllowedOrigins() {
181187
}
182188

183189
/**
184-
* Returns a lazy-initialized instance of
185-
* {@link org.restlet.engine.application.CorsResponseHelper}.
190+
* Returns a lazy-initialized instance of {@link org.restlet.engine.application.CorsResponseHelper}.
186191
*/
187192
protected CorsResponseHelper getCorsResponseHelper() {
188193
if (corsResponseHelper == null) {
@@ -193,12 +198,14 @@ protected CorsResponseHelper getCorsResponseHelper() {
193198
.setAllowAllRequestedHeaders(allowAllRequestedHeaders);
194199
corsResponseHelper.setAllowedHeaders(allowedHeaders);
195200
corsResponseHelper.setExposedHeaders(exposedHeaders);
201+
corsResponseHelper.setMaxAge(maxAge);
196202
}
197203
return corsResponseHelper;
198204
}
199205

200206
/**
201207
* Returns the list of methods allowed by default, used when {@link #skippingResourceForCorsOptions} is turned on.
208+
*
202209
* @return The list of methods allowed by default, used when {@link #skippingResourceForCorsOptions} is turned on.
203210
*/
204211
public Set<Method> getDefaultAllowedMethods() {
@@ -218,6 +225,17 @@ public Set<String> getExposedHeaders() {
218225
return exposedHeaders;
219226
}
220227

228+
/**
229+
* Indicates how long (in seconds) the results of a preflight request can be cached in a preflight result cache.<br>
230+
* In case of a negative value, the results of a preflight request is not meant to be cached.<br>
231+
* Note that when used with HTTP connectors, this property maps to the "Access-Control-Max-Age" header.
232+
*
233+
* @return Indicates how long the results of a preflight request can be cached in a preflight result cache.
234+
*/
235+
public int getMaxAge() {
236+
return maxAge;
237+
}
238+
221239
/**
222240
* If true, indicates that the value of 'Access-Control-Request-Headers'
223241
* request header will be copied into the 'Access-Control-Allow-Headers'
@@ -239,11 +257,11 @@ public boolean isAllowedCredentials() {
239257

240258
/**
241259
* If true, the filter does not call the server resource for OPTIONS method
242-
* of CORS request and set Access-Control-Allow-Methods header with
243-
* {@link #defaultAllowedMethods}. Default is false.
244-
*
260+
* of CORS request and set Access-Control-Allow-Methods header with {@link #defaultAllowedMethods}. Default is
261+
* false.
262+
*
245263
* @return True if the filter does not call the server resource for
246-
* OPTIONS method of CORS request.
264+
* OPTIONS method of CORS request.
247265
*/
248266
public boolean isSkippingResourceForCorsOptions() {
249267
return skippingResourceForCorsOptions;
@@ -305,7 +323,10 @@ public CorsFilter setAllowingAllRequestedHeaders(
305323

306324
/**
307325
* Sets the list of methods allowed by default, used when {@link #skippingResourceForCorsOptions} is turned on.
308-
* @param defaultAllowedMethods The list of methods allowed by default, used when {@link #skippingResourceForCorsOptions} is turned on.
326+
*
327+
* @param defaultAllowedMethods
328+
* The list of methods allowed by default, used when {@link #skippingResourceForCorsOptions} is turned
329+
* on.
309330
*/
310331
public CorsFilter setDefaultAllowedMethods(Set<Method> defaultAllowedMethods) {
311332
this.defaultAllowedMethods = defaultAllowedMethods;
@@ -324,12 +345,24 @@ public CorsFilter setExposedHeaders(Set<String> exposedHeaders) {
324345
return this;
325346
}
326347

348+
/**
349+
* Sets the value of 'Access-Control-Max-Age' response header.<br>
350+
* In case of negative value, the header is not set.
351+
*
352+
* @param maxAge
353+
* The value of 'Access-Control-Max-Age' response header.
354+
*/
355+
public CorsFilter setMaxAge(int maxAge) {
356+
this.maxAge = maxAge;
357+
return this;
358+
}
359+
327360
/**
328361
* Sets the value of skipResourceForCorsOptions field.
329-
*
362+
*
330363
* @param skipResourceForCorsOptions
331-
* True if the filter does not call the server resource for
332-
* OPTIONS method of CORS request.
364+
* True if the filter does not call the server resource for
365+
* OPTIONS method of CORS request.
333366
* @return Itself for chaining methods calls.
334367
*/
335368
public CorsFilter setSkippingResourceForCorsOptions(boolean skipResourceForCorsOptions) {

0 commit comments

Comments
 (0)