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;
018
019import java.nio.charset.Charset;
020import java.util.Locale;
021
022import org.apache.wicket.request.parameter.CombinedRequestParametersAdapter;
023import org.apache.wicket.request.parameter.EmptyRequestParameters;
024import org.apache.wicket.request.parameter.UrlRequestParametersAdapter;
025
026/**
027 * Request object.
028 * 
029 * @author Matej Knopp
030 */
031public abstract class Request
032{
033        /**
034         * Returns the URL for this request. URL is relative to Wicket filter path.
035         * 
036         * @return Url instance
037         */
038        public abstract Url getUrl();
039
040        /**
041         * Returns the url against which the client, usually the browser, will resolve relative urls in
042         * the rendered markup. If the client is a browser this is the url in the browser's address bar.
043         * 
044         * <p>
045         * Under normal circumstances the client and request ({@link #getUrl()}) urls are the same.
046         * Handling an Ajax request, however, is a good example of when they may be different.
047         * Technologies such as XHR are free to request whatever url they wish <strong>without
048         * modifying</strong> the client url; however, any produced urls will be evaluated by the client
049         * against the client url - not against the request url.
050         * </p>
051         * <p>
052         * Lets take a simple example: <br>
053         * 
054         * Suppose we are on a client detail page. This page contains an Ajax link which opens a list of
055         * client's orders. Each order has a link that goes to the order detail page.
056         * 
057         * The client detail page is located at
058         * 
059         * <pre>
060         * /detail/customer/15
061         * </pre>
062         * 
063         * and the order detail page is located at
064         * 
065         * <pre>
066         * /order/22
067         * </pre>
068         * 
069         * The Ajax link which renders the detail section is located at
070         * 
071         * <pre>
072         *  /detail/wicket?page 3
073         * </pre>
074         * 
075         * Lets run through the execution and see what happens when the XHR request is processed:
076         * 
077         * <pre>
078         * request 1: /details/customer/15
079         * client url: details/customer/15 (the url in the browser's address bar)
080         * request url: details/customer/15
081         * Wicket renders relative Ajax details anchor as ../../wicket/page?3  
082         * 
083         * ../../wicket/page?3 resolved against current client url details/customer/15 yields:
084         * request 2: /wicket/page?3
085         * client url: customer/15 (unchanged since XHRs requests dont change it)
086         * request url: wicket/ajax/page?3
087         * 
088         * now Wicket has to render a relative url to /details/order/22. If Wicket renders 
089         * it against the request url it will be: ../order/22, and later evaluated on the
090         * client will result in /customer/order/22 which is incorrect.
091         * </pre>
092         * 
093         * This is why implementations of {@link Request} must track the client url, so that relative
094         * urls can be rendered against the same url they will be evaluated against on the client -
095         * which is not always the same as the request url. For example, Wicket's Ajax implementation
096         * always sends the current client url in a header along with the XHR request so that Wicket can
097         * correctly render relative urls against it.
098         * </p>
099         * 
100         * @return client url
101         */
102        public abstract Url getClientUrl();
103
104        /**
105         * In case this request has been created using {@link #cloneWithUrl(Url)}, this method should
106         * return the original URL.
107         * 
108         * @return original URL
109         */
110        public Url getOriginalUrl()
111        {
112                return getUrl();
113        }
114
115        /**
116         * Note: Avoid calling this method yourself in you code base if you are using multipart to upload files in
117         * combination with Tomcat 11.x. Calling this method before multipart is processed, will cause Tomcat to parse
118         * by itself the multipart request and then wicket's multipart processing won't work. See WICKET-7154
119         * for details.
120         *
121         * @return POST request parameters for this request.
122         */
123        public IRequestParameters getPostParameters()
124        {
125                return EmptyRequestParameters.INSTANCE;
126        }
127
128        /**
129         * @return GET request parameters for this request.
130         */
131        public IRequestParameters getQueryParameters()
132        {
133                return new UrlRequestParametersAdapter(getUrl());
134        }
135
136        /**
137         * Note: Avoid calling this method yourself in you code base if you are using multipart to upload files in
138         * combination with Tomcat 11.x. Calling this method before multipart is processed, will cause Tomcat to parse
139         * by itself the multipart request and then wicket's multipart processing won't work. See WICKET-7154
140         * for details.
141         *
142         * @return all request parameters for this request (both POST and GET parameters)
143         */
144        public IRequestParameters getRequestParameters()
145        {
146                return new CombinedRequestParametersAdapter(getPostParameters(), getQueryParameters());
147        }
148
149        /**
150         * Returns locale for this request.
151         * 
152         * @return locale
153         */
154        public abstract Locale getLocale();
155
156        /**
157         * Returns request with specified URL and same POST parameters as this request.
158         * 
159         * @param url
160         *            Url instance
161         * @return request with specified URL.
162         */
163        public Request cloneWithUrl(final Url url)
164        {
165                return new Request()
166                {
167                        @Override
168                        public Url getUrl()
169                        {
170                                return url;
171                        }
172
173                        @Override
174                        public Url getOriginalUrl()
175                        {
176                                return Request.this.getOriginalUrl();
177                        }
178
179                        @Override
180                        public Locale getLocale()
181                        {
182                                return Request.this.getLocale();
183                        }
184
185                        @Override
186                        public IRequestParameters getPostParameters()
187                        {
188                                return Request.this.getPostParameters();
189                        }
190
191                        @Override
192                        public Charset getCharset()
193                        {
194                                return Request.this.getCharset();
195                        }
196
197                        @Override
198                        public Url getClientUrl()
199                        {
200                                return Request.this.getClientUrl();
201                        }
202
203                        @Override
204                        public Object getContainerRequest()
205                        {
206                                return Request.this.getContainerRequest();
207                        }
208                };
209        }
210
211        /**
212         * Returns prefix from Wicket Filter mapping to context path. This method does not take the
213         * actual URL into account.
214         * <p>
215         * For example if Wicket filter is mapped to hello/* this method should return ../ regardless of
216         * actual URL (after Wicket filter)
217         * 
218         * @return prefix to context path for this request.
219         * 
220         */
221        public String getPrefixToContextPath()
222        {
223                return "";
224        }
225
226        /**
227         * Returns the context path or an empty string if the application is running under root context.
228         * Returned path, unless an empty string, will always start with a slash and will never end with
229         * a slash.
230         * 
231         * @return context path
232         */
233        public String getContextPath()
234        {
235                return "";
236        }
237
238        /**
239         * Returns the path to which wicket Filter is mapped or an empty string if the filter is mapped
240         * to {@code /*}. Returned path, unless an empty string, will always start with a slash and will
241         * never end with a slash.
242         * 
243         * @return filter path
244         */
245        public String getFilterPath()
246        {
247                return "";
248        }
249
250        /**
251         * Gets charset of the request
252         * 
253         * @return request charset
254         */
255        public abstract Charset getCharset();
256
257        /**
258         * Provides access to the low-level container request object that implementaion of this
259         * {@link Request} delegate to. This allows users to access features provided by the container
260         * requests but not by generalized Wicket {@link Request} objects.
261         * 
262         * @return low-level container request object, or {@code null} if none
263         */
264        public abstract Object getContainerRequest();
265}