Skip to content

Commit

Permalink
Added support of 'Access-Control-Max-Age'. Issue #1109. Reported by T…
Browse files Browse the repository at this point in the history
…al Liron.
  • Loading branch information
thboileau committed May 2, 2016
1 parent 2beef8b commit dc6f513
Show file tree
Hide file tree
Showing 7 changed files with 181 additions and 57 deletions.
2 changes: 2 additions & 0 deletions build/tmpl/text/changes.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ Changes log
- Fixed support of non-bytes ranges. Issue #1132.
- Fixed encoding issue when using CookieAuthenticator. Issue #1159.
Reported by Arjohn Kampman.
- Added support of 'Access-Control-Max-Age'. Issue #1109.
Reported by Tal Liron.

- 2.3.7 (03/14/2016)
- Bugs fixed
Expand Down
61 changes: 43 additions & 18 deletions modules/org.restlet/src/org/restlet/Response.java
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,13 @@ public static void setCurrent(Response response) {
private volatile Set<String> accessControlExposeHeaders;

/**
* Estimated amount of time since a response was generated or revalidated by
* the origin server.
* When used in the context of CORS support, it indicates how long the results of a preflight request can be cached
* in a preflight result cache.
*/
private volatile int accessControlMaxAge;

/**
* Estimated amount of time since a response was generated or revalidated by the origin server.
*/
private volatile int age;

Expand Down Expand Up @@ -328,6 +333,17 @@ public Set<String> getAccessControlExposeHeaders() {
return a;
}

/**
* Indicates how long the results of a preflight CORS request can be cached in a preflight result cache.<br>
* In case of a negative value, the results of a preflight request is not meant to be cached.<br>
* Note that when used with HTTP connectors, this property maps to the "Access-Control-Max-Age" header.
*
* @return Indicates how long the results of a preflight request can be cached in a preflight result cache.
*/
public int getAccessControlMaxAge() {
return accessControlMaxAge;
}

/**
* Returns the estimated amount of time since a response was generated or
* revalidated by the origin server. Origin servers should leave the 0
Expand Down Expand Up @@ -541,8 +557,7 @@ public Status getStatus() {
* processing a request on the server-side, setting this property to 'false'
* let you ask to the server connector to wait before sending the response
* back to the client when the initial calling thread returns. This will let
* you do further updates to the response and manually calling
* {@link #commit()} later on, using another thread.
* you do further updates to the response and manually calling {@link #commit()} later on, using another thread.
*
* @return True if the response should be automatically committed.
*/
Expand All @@ -565,8 +580,7 @@ public boolean isConfidential() {
}

/**
* Indicates if the response is final or provisional. It relies on the
* {@link Status#isInformational()} method.
* Indicates if the response is final or provisional. It relies on the {@link Status#isInformational()} method.
*
* @return True if the response is final.
*/
Expand All @@ -575,8 +589,7 @@ public boolean isFinal() {
}

/**
* Indicates if the response is provisional or final. It relies on the
* {@link Status#isInformational()} method.
* Indicates if the response is provisional or final. It relies on the {@link Status#isInformational()} method.
*
* @return True if the response is provisional.
*/
Expand All @@ -601,8 +614,8 @@ public void redirectPermanent(Reference targetRef) {
* to reuse the same method for the new request.<br>
* <br>
* If you pass a relative target URI, it will be resolved with the current
* base reference of the request's resource reference (see
* {@link Request#getResourceRef()} and {@link Reference#getBaseRef()}.
* base reference of the request's resource reference (see {@link Request#getResourceRef()} and
* {@link Reference#getBaseRef()}.
*
* @param targetUri
* The target URI.
Expand Down Expand Up @@ -635,8 +648,8 @@ public void redirectSeeOther(Reference targetRef) {
* originally requested resource.<br>
* <br>
* If you pass a relative target URI, it will be resolved with the current
* base reference of the request's resource reference (see
* {@link Request#getResourceRef()} and {@link Reference#getBaseRef()}.
* base reference of the request's resource reference (see {@link Request#getResourceRef()} and
* {@link Reference#getBaseRef()}.
*
* @param targetUri
* The target URI.
Expand All @@ -663,8 +676,8 @@ public void redirectTemporary(Reference targetRef) {
* to reuse the same method for the new request.<br>
* <br>
* If you pass a relative target URI, it will be resolved with the current
* base reference of the request's resource reference (see
* {@link Request#getResourceRef()} and {@link Reference#getBaseRef()}.
* base reference of the request's resource reference (see {@link Request#getResourceRef()} and
* {@link Reference#getBaseRef()}.
*
* @param targetUri
* The target URI.
Expand All @@ -688,6 +701,19 @@ public void setAccessControlAllowCredentials(
this.accessControlAllowCredentials = accessControlAllowCredentials;
}

/**
* When used as part of a response to a preflight CORS request, indicates how long (in seconds) the results of a
* preflight request can be cached in a preflight result cache.<br>
* Note that when used with HTTP connectors, this property maps to the "Access-Control-Max-Age" header.<br>
* In case of negative value, the header is not set.
*
* @param accessControlMaxAge
* How long the results of a preflight request can be cached in a preflight result cache.
*/
public void setAccessControlMaxAge(int accessControlMaxAge) {
this.accessControlMaxAge = accessControlMaxAge;
}

/**
* Sets the set of headers allowed by the actual request on the current
* resource when used as part of a response to a preflight CORS request.<br>
Expand Down Expand Up @@ -928,8 +954,7 @@ public void setLocationRef(Reference locationRef) {
* Sets the reference that the client should follow for redirections or
* resource creations. If you pass a relative location URI, it will be
* resolved with the current base reference of the request's resource
* reference (see {@link Request#getResourceRef()} and
* {@link Reference#getBaseRef()}.<br>
* reference (see {@link Request#getResourceRef()} and {@link Reference#getBaseRef()}.<br>
* <br>
* Note that when used with HTTP connectors, this property maps to the
* "Location" header.
Expand All @@ -954,8 +979,8 @@ public void setLocationRef(String locationUri) {

/**
* Sets the modifiable list of authentication requests sent by a proxy to a
* client. The list instance set must be thread-safe (use
* {@link CopyOnWriteArrayList} for example. Note that when used with HTTP
* client. The list instance set must be thread-safe (use {@link CopyOnWriteArrayList} for example. Note that when
* used with HTTP
* connectors, this property maps to the "Proxy-Authenticate" header. This
* method clears the current list and adds all entries in the parameter
* list.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,8 @@ public class CorsFilter extends Filter {
private boolean allowedCredentials = false;

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

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

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

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

/** The value of 'Access-Control-Max-Age' response header. Default is that the header is not set. */
private int maxAge = -1;

/**
* If true, the filter does not call the server resource for OPTIONS method
* of CORS request and set Access-Control-Allow-Methods header with
* {@link #defaultAllowedMethods}. Default is false.
* of CORS request and set Access-Control-Allow-Methods header with {@link #defaultAllowedMethods}. Default is
* false.
*/
private boolean skippingResourceForCorsOptions = false;

Expand Down Expand Up @@ -122,9 +128,22 @@ public CorsFilter(Context context, Restlet next) {
}

/**
* Skip the call to the server resource if the {@link #skippingResourceForCorsOptions}
* is true and if the current request use the OPTIONS method and is a CORS request.
*
* Add CORS headers to response
*
* @param request
* The request to handle.
* @param response
* The response
*/
@Override
protected void afterHandle(Request request, Response response) {
getCorsResponseHelper().addCorsResponseHeaders(request, response);
}

/**
* Skip the call to the server resource if the {@link #skippingResourceForCorsOptions} is true and if the current
* request use the OPTIONS method and is a CORS request.
*
* @param request
* The request to handle.
* @param response
Expand All @@ -142,19 +161,6 @@ && getCorsResponseHelper().isCorsRequest(request)) {
}
}

/**
* Add CORS headers to response
*
* @param request
* The request to handle.
* @param response
* The response
*/
@Override
protected void afterHandle(Request request, Response response) {
getCorsResponseHelper().addCorsResponseHeaders(request, response);
}

/**
* Returns the modifiable set of headers allowed by the actual request on
* the current resource.<br>
Expand All @@ -181,8 +187,7 @@ public Set<String> getAllowedOrigins() {
}

/**
* Returns a lazy-initialized instance of
* {@link org.restlet.engine.application.CorsResponseHelper}.
* Returns a lazy-initialized instance of {@link org.restlet.engine.application.CorsResponseHelper}.
*/
protected CorsResponseHelper getCorsResponseHelper() {
if (corsResponseHelper == null) {
Expand All @@ -193,12 +198,14 @@ protected CorsResponseHelper getCorsResponseHelper() {
.setAllowAllRequestedHeaders(allowAllRequestedHeaders);
corsResponseHelper.setAllowedHeaders(allowedHeaders);
corsResponseHelper.setExposedHeaders(exposedHeaders);
corsResponseHelper.setMaxAge(maxAge);
}
return corsResponseHelper;
}

/**
* Returns the list of methods allowed by default, used when {@link #skippingResourceForCorsOptions} is turned on.
*
* @return The list of methods allowed by default, used when {@link #skippingResourceForCorsOptions} is turned on.
*/
public Set<Method> getDefaultAllowedMethods() {
Expand All @@ -218,6 +225,17 @@ public Set<String> getExposedHeaders() {
return exposedHeaders;
}

/**
* Indicates how long (in seconds) the results of a preflight request can be cached in a preflight result cache.<br>
* In case of a negative value, the results of a preflight request is not meant to be cached.<br>
* Note that when used with HTTP connectors, this property maps to the "Access-Control-Max-Age" header.
*
* @return Indicates how long the results of a preflight request can be cached in a preflight result cache.
*/
public int getMaxAge() {
return maxAge;
}

/**
* If true, indicates that the value of 'Access-Control-Request-Headers'
* request header will be copied into the 'Access-Control-Allow-Headers'
Expand All @@ -239,11 +257,11 @@ public boolean isAllowedCredentials() {

/**
* If true, the filter does not call the server resource for OPTIONS method
* of CORS request and set Access-Control-Allow-Methods header with
* {@link #defaultAllowedMethods}. Default is false.
*
* of CORS request and set Access-Control-Allow-Methods header with {@link #defaultAllowedMethods}. Default is
* false.
*
* @return True if the filter does not call the server resource for
* OPTIONS method of CORS request.
* OPTIONS method of CORS request.
*/
public boolean isSkippingResourceForCorsOptions() {
return skippingResourceForCorsOptions;
Expand Down Expand Up @@ -305,7 +323,10 @@ public CorsFilter setAllowingAllRequestedHeaders(

/**
* Sets the list of methods allowed by default, used when {@link #skippingResourceForCorsOptions} is turned on.
* @param defaultAllowedMethods The list of methods allowed by default, used when {@link #skippingResourceForCorsOptions} is turned on.
*
* @param defaultAllowedMethods
* The list of methods allowed by default, used when {@link #skippingResourceForCorsOptions} is turned
* on.
*/
public CorsFilter setDefaultAllowedMethods(Set<Method> defaultAllowedMethods) {
this.defaultAllowedMethods = defaultAllowedMethods;
Expand All @@ -324,12 +345,24 @@ public CorsFilter setExposedHeaders(Set<String> exposedHeaders) {
return this;
}

/**
* Sets the value of 'Access-Control-Max-Age' response header.<br>
* In case of negative value, the header is not set.
*
* @param maxAge
* The value of 'Access-Control-Max-Age' response header.
*/
public CorsFilter setMaxAge(int maxAge) {
this.maxAge = maxAge;
return this;
}

/**
* Sets the value of skipResourceForCorsOptions field.
*
*
* @param skipResourceForCorsOptions
* True if the filter does not call the server resource for
* OPTIONS method of CORS request.
* True if the filter does not call the server resource for
* OPTIONS method of CORS request.
* @return Itself for chaining methods calls.
*/
public CorsFilter setSkippingResourceForCorsOptions(boolean skipResourceForCorsOptions) {
Expand Down
Loading

0 comments on commit dc6f513

Please sign in to comment.