    001// Licensed under the Apache License, Version 2.0 (the "License");
    002// you may not use this file except in compliance with the License.
    003// You may obtain a copy of the License at
    004//
    005// http://www.apache.org/licenses/LICENSE-2.0
    006//
    007// Unless required by applicable law or agreed to in writing, software
    008// distributed under the License is distributed on an "AS IS" BASIS,
    009// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    010// See the License for the specific language governing permissions and
    011// limitations under the License.
    012package org.apache.tapestry5.http.services;
    013
    014import java.util.Optional;
    015
    016import javax.servlet.http.HttpServletRequest;
    017import javax.servlet.http.HttpServletResponse;
    018
    019import org.apache.tapestry5.http.TapestryHttpSymbolConstants;
    020
    021/**
    022 * Service that provides useful methods for {@link CorsHandler} implementations.
    023 *
    024 * @see CorsHandler
    025 * @since 5.8.2
    026 */
    027public interface CorsHandlerHelper {
    028
    029    /**
    030     * Returns the requested URL path, using the same logic as {@link Request#getPath()}.
    031     * @param request an {@link HttpServletRequest}.
    032     * @return a {@link String} with the path.
    033     */
    034    String getPath(HttpServletRequest request);
    035
    036    /**
    037     * Returns the value of the Origin HTTP header.
    038     * @param request an {@link HttpServletRequest}.
    039     * @return an {@link Optional} wrapping the Origin HTTP header value.
    040     */
    041    Optional<String> getOrigin(HttpServletRequest request);
    042
    043    /**
    044     * Tells whether this request is a CORS preflight one (i.e. HTTP method OPTION and
    045     * non-empty Origin HTTP header).
    046     *
    047     * @param request an {@link HttpServletRequest}.
    048     * @return <code>true</code> if it's a preflight request, <code>false</code> otherwise.
    049     */
    050    boolean isPreflight(HttpServletRequest request);
    051
    052    /**
    053     * Returns the origin of this requests, if it's allowed.
    054     * @param request an {@link HttpServletRequest}.
    055     * @return an {@link Optional} wrapping the allowed origin.
    056     * @see TapestryHttpSymbolConstants#CORS_ALLOWED_ORIGINS
    057     */
    058    Optional<String> getAllowedOrigin(HttpServletRequest request);
    059
    060    /**
    061     * Sets the Access-Control-Allow-Origin HTTP header with a given value.
    062     * @param value a {@linkplain String}.
    063     * @param response an {@link HttpServletResponse} instance.
    064     * @see #ALLOW_ORIGIN_HEADER
    065     */
    066    void configureOrigin(HttpServletResponse response, String value);
    067
    068    /**
    069     * Conditionally sets the Access-Control-Allow-Credentials HTTP header.
    070     * Out-of-the-box, this is done based on the
    071     * {@link TapestryHttpSymbolConstants#CORS_ALLOW_CREDENTIALS} symbol.
    072     * @param response an {@link HttpServletResponse}.
    073     * @see TapestryHttpSymbolConstants#CORS_ALLOW_CREDENTIALS
    074     */
    075    void configureCredentials(HttpServletResponse response);
    076
    077    /**
    078     * Conditionally sets the Access-Control-Allow-Methods HTTP header in responses
    079     * to preflight CORS requests.
    080     * Out-of-the-box, the value comes from
    081     * {@link TapestryHttpSymbolConstants#CORS_ALLOW_CREDENTIALS} symbol
    082     * and the header is only set if the value isn't empty.
    083     * @param response an {@link HttpServletResponse}.
    084     * @see TapestryHttpSymbolConstants#CORS_ALLOW_CREDENTIALS
    085     */
    086    void configureMethods(HttpServletResponse response);
    087
    088    /**
    089     * Conditionally the Access-Control-Request-Headers HTTP header.
    090     * Out-of-the-box, the value comes from
    091     * {@link TapestryHttpSymbolConstants#CORS_ALLOWED_HEADERS} symbol if not empty.
    092     * Otherwise, it comes from the value of the same HTTP header from the request,
    093     * also if not empty. Otherwise, the header isn't set.
    094     * @param response an {@link HttpServletResponse}.
    095     * @param request an {@link HttpServletRequest}.
    096     * @see TapestryHttpSymbolConstants#CORS_ALLOWED_HEADERS
    097     */
    098    void configureAllowedHeaders(HttpServletResponse response, HttpServletRequest request);
    099
    100    /**
    101     * Conditionally sets the Access-Control-Expose-Headers HTTP header.
    102     * Out-of-the-box, the value comes from
    103     * {@link TapestryHttpSymbolConstants#CORS_EXPOSE_HEADERS} symbol, if not empty.
    104     * Otherwise, the header isn't set.
    105     * @param response an {@link HttpServletResponse}.
    106     * @see TapestryHttpSymbolConstants#CORS_EXPOSE_HEADERS
    107     */
    108    void configureExposeHeaders(HttpServletResponse response);
    109
    110    /**
    111     * Conditionally sets the Access-Control-Max-Age HTTP header.
    112     * Out-of-the-box, the value comes from
    113     * {@link TapestryHttpSymbolConstants#CORS_MAX_AGE} symbol, if not empty.
    114     * Otherwise, the header isn't set.
    115     * @param response an {@link HttpServletResponse}.
    116     * @see TapestryHttpSymbolConstants#CORS_MAX_AGE
    117     */
    118    void configureMaxAge(HttpServletResponse response);
    119
    120    /**
    121     * Adds a value to the Vary HTTP header.
    122     * @param response an {@link HttpServletResponse} instance.
    123     * @param value the value to be added.
    124     */
    125    default void addValueToVaryHeader(HttpServletResponse response, String value)
    126    {
    127        final String vary = response.getHeader(VARY_HEADER);
    128        response.setHeader(VARY_HEADER, vary == null ? value : vary + ", " + value);
    129    }
    130
    131    /**
    132     * Name of the Origin HTTP header.
    133     */
    134    String ORIGIN_HEADER = "Origin";
    135
    136    /**
    137     * Name of the Access-Control-Allow-Origin HTTP header.
    138     */
    139    String ALLOW_ORIGIN_HEADER = "Access-Control-Allow-Origin";
    140
    141    /**
    142     * Name of the Access-Control-Allow-Credentials HTTP header.
    143     */
    144    String ALLOW_CREDENTIALS_HEADER = "Access-Control-Allow-Credentials";
    145
    146    /**
    147     * Name of the Access-Control-Allow-Methods HTTP header.
    148     */
    149    String ALLOW_METHODS_HEADER = "Access-Control-Allow-Methods";
    150
    151    /**
    152     * Name of the Access-Control-Request-Headers HTTP header.
    153     */
    154    String REQUEST_HEADERS_HEADER = "Access-Control-Request-Headers";
    155
    156    /**
    157     * Name of the Access-Control-Allow-Headers HTTP header.
    158     */
    159    String ALLOW_HEADERS_HEADER = "Access-Control-Allow-Headers";
    160
    161    /**
    162     * Name of the Access-Control-Expose-Headers HTTP header.
    163     */
    164    String EXPOSE_HEADERS_HEADER = "Access-Control-Expose-Headers";
    165
    166    /**
    167     * Name of the Access-Control-Max-Age HTTP header.
    168     */
    169    String MAX_AGE_HEADER = "Access-Control-Max-Age";
    170
    171    /**
    172     * Name of the Vary HTTP header.
    173     */
    174    String VARY_HEADER = "Vary";
    175
    176    /**
    177     * OPTIONS HTTP method name.
    178     */
    179    String OPTIONS_METHOD = "OPTIONS";
    180
    181    /**
    182     * The CORS Origin wildcard.
    183     */
    184    String ORIGIN_WILDCARD = "*";
    185
    186}