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}