001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.wicket.request.http;
018
019import java.nio.charset.Charset;
020import java.time.Instant;
021import java.util.List;
022import java.util.Locale;
023import javax.servlet.http.Cookie;
024import org.apache.wicket.request.IRequestParameters;
025import org.apache.wicket.request.Request;
026import org.apache.wicket.request.Url;
027import org.apache.wicket.util.string.StringValueConversionException;
028import org.apache.wicket.util.string.Strings;
029
030/**
031 * Base class for request that provides additional web-related information.
032 * 
033 * @author Matej Knopp
034 * @author Igor Vaynberg
035 */
036public abstract class WebRequest extends Request
037{
038        /** marker for Ajax requests */
039        public static final String PARAM_AJAX = "wicket-ajax";
040        /** marker for Ajax requests */
041        public static final String HEADER_AJAX = "Wicket-Ajax";
042        /** marker for Ajax-relative url */
043        public static final String PARAM_AJAX_BASE_URL = "wicket-ajax-baseurl";
044        /** marker for Ajax-relative url */
045        public static final String HEADER_AJAX_BASE_URL = "Wicket-Ajax-BaseURL";
046        /** anti-cache query parameter added by Wicket.Ajax.Request at its URL */
047        public static final String PARAM_AJAX_REQUEST_ANTI_CACHE = "_";
048        /** {@code Origin} http header */
049        public static final String HEADER_ORIGIN = "Origin";
050        /** {@code Referer} http header */
051        public static final String HEADER_REFERER = "Referer";
052
053        private Boolean isAjax;
054
055        /**
056         * @return request cookies
057         */
058        public abstract List<Cookie> getCookies();
059
060        /**
061         * @param cookieName
062         * @return cookie with specified name or <code>null</code> if the cookie does not exist
063         */
064        public Cookie getCookie(final String cookieName)
065        {
066                for (Cookie cookie : getCookies())
067                {
068                        if (cookie.getName().equals(cookieName))
069                        {
070                                return cookie;
071                        }
072                }
073                return null;
074        }
075
076        /**
077         * Returns all the values of the specified request header.
078         * 
079         * @param name
080         * @return unmodifiable list of header values
081         */
082        public abstract List<String> getHeaders(String name);
083
084        /**
085         * Returns the value of the specified request header as a <code>String</code>
086         * 
087         * @param name
088         * @return string value of request header
089         */
090        public abstract String getHeader(String name);
091
092        /**
093         * Returns the value of the specified request header as a <code>long</code> value that
094         * represents a <code>Date</code> object. Use this method with headers that contain dates, such
095         * as <code>If-Modified-Since</code>.
096         * 
097         * @param name
098         * @return date value of request header or <code>null</code> if not found
099         */
100        public abstract Instant getDateHeader(String name);
101
102        /**
103         * Convenience method for retrieving If-Modified-Since header.
104         * 
105         * @return date representing the header or <code>null</code> if not set
106         */
107        public final Instant getIfModifiedSinceHeader()
108        {
109                return getDateHeader("If-Modified-Since");
110        }
111
112
113        /**
114         * Returns whether this request is an Ajax request. This implementation checks for values of
115         * {@value #PARAM_AJAX} url parameter or the {@value #HEADER_AJAX} header. Subclasses can use
116         * other approaches.
117         * 
118         * @return <code>true</code> if this request is an ajax request, <code>false</code> otherwise.
119         */
120        public boolean isAjax()
121        {
122                if (isAjax == null)
123                {
124                        try {
125                                isAjax = Strings.isTrue(getHeader(HEADER_AJAX)) ||
126                                                Strings.isTrue(getQueryParameters().getParameterValue(PARAM_AJAX).toString());
127                        } catch (StringValueConversionException invalidValue) {
128                                isAjax = false;
129                        }
130                }
131                return isAjax;
132        }
133
134        /**
135         * Signals whether or not request processing should preserve the current client url - in other
136         * words, handle this request without redirecting. By default, this method returns {@code false}
137         * .
138         * 
139         * For example, this method can be used to preserve the url that caused a 404 in the browser if
140         * Wicket is also responsible for rendering the 404 page. If this method returns the default
141         * value of {@code false} then Wicket will redirect to the bookmarkable url of the error page,
142         * instead of preserving the url that caused the 404 in the browser.
143         * 
144         * @return {@code true} if current client url should be preserved
145         */
146        public boolean shouldPreserveClientUrl()
147        {
148                return false;
149        }
150
151        /**
152         * Returns request with specified URL and same POST parameters as this request.
153         * 
154         * @param url
155         *            Url instance
156         * @return request with specified URL.
157         */
158        @Override
159        public WebRequest cloneWithUrl(final Url url)
160        {
161                return new WebRequest()
162                {
163                        @Override
164                        public Url getUrl()
165                        {
166                                return url;
167                        }
168
169                        @Override
170                        public Url getOriginalUrl()
171                        {
172                                return WebRequest.this.getOriginalUrl();
173                        }
174
175                        @Override
176                        public IRequestParameters getPostParameters()
177                        {
178                                return WebRequest.this.getPostParameters();
179                        }
180
181                        @Override
182                        public List<Cookie> getCookies()
183                        {
184                                return WebRequest.this.getCookies();
185                        }
186
187                        @Override
188                        public Instant getDateHeader(final String name)
189                        {
190                                return WebRequest.this.getDateHeader(name);
191                        }
192
193                        @Override
194                        public Locale getLocale()
195                        {
196                                return WebRequest.this.getLocale();
197                        }
198
199                        @Override
200                        public String getHeader(final String name)
201                        {
202                                return WebRequest.this.getHeader(name);
203                        }
204
205                        @Override
206                        public List<String> getHeaders(final String name)
207                        {
208                                return WebRequest.this.getHeaders(name);
209                        }
210
211                        @Override
212                        public Charset getCharset()
213                        {
214                                return WebRequest.this.getCharset();
215                        }
216
217                        @Override
218                        public Url getClientUrl()
219                        {
220                                return WebRequest.this.getClientUrl();
221                        }
222
223                        @Override
224                        public Object getContainerRequest()
225                        {
226                                return WebRequest.this.getContainerRequest();
227                        }
228
229                        @Override
230                        public boolean shouldPreserveClientUrl()
231                        {
232                                return WebRequest.this.shouldPreserveClientUrl();
233                        }
234                };
235        }
236
237}