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.handler; 018 019import jakarta.servlet.http.HttpServletResponse; 020 021import org.apache.wicket.request.IRequestCycle; 022import org.apache.wicket.request.IRequestHandler; 023import org.apache.wicket.request.http.WebRequest; 024import org.apache.wicket.request.http.WebResponse; 025import org.apache.wicket.util.lang.Args; 026 027/** 028 * A request handler that redirects to the given url. 029 * 030 * the url should be one of the following: 031 * <ul> 032 * <li>Fully qualified "http://foo.com/bar"</li> 033 * <li>Relative to the Wicket filter/servlet, e.g. "?wicket:interface=foo", "mounted_page"</li> 034 * <li>Absolute within your web application's <strong>context root</strong>, e.g. "/foo.html"</li> 035 * </ul> 036 * 037 * @author igor.vaynberg 038 * @author jcompagner 039 */ 040public class RedirectRequestHandler implements IRequestHandler 041{ 042 public enum Mode 043 { 044 /** 045 * Use {@link WebResponse#sendRedirect(String)}. 046 * It will call {@link WebResponse#encodeRedirectURL(CharSequence)} and may URL-encode some parts of the {@code location} 047 */ 048 REDIRECT, 049 /** 050 * Use {@link WebResponse#setStatus(int)} + {@link WebResponse#setHeader(String, String)}. 051 * Sets the {@code location} as a value of {@code Location} response header as is, i.e. without url-encoding. 052 */ 053 STATUS, 054 /** 055 * Decide dynamically depending on the value of {@code status} field 056 */ 057 AUTO; 058 } 059 060 private final String redirectUrl; 061 private final int status; 062 063 private Mode mode = Mode.AUTO; 064 065 /** 066 * @param redirectUrl 067 * URL to redirect to. 068 */ 069 public RedirectRequestHandler(final String redirectUrl) 070 { 071 this(redirectUrl, HttpServletResponse.SC_MOVED_TEMPORARILY); 072 } 073 074 /** 075 * @param redirectUrl 076 * URL to redirect to. 077 * @param status 078 * 301 (Moved permanently) or 079 * 302 (Found (former Moved temporarily)) or 080 * 303 (See other) or 081 * 307 (Temporary redirect) or 082 * 308 (Permanent recirect) 083 */ 084 public RedirectRequestHandler(final String redirectUrl, final int status) 085 { 086 if ((status != HttpServletResponse.SC_MOVED_PERMANENTLY) && 087 (status != HttpServletResponse.SC_FOUND) && 088 (status != HttpServletResponse.SC_SEE_OTHER) && 089 (status != HttpServletResponse.SC_TEMPORARY_REDIRECT) && 090 (status != 308 /* Constant HttpServletResponse.SC_PERMANENT_REDIRECT, requires Jakarta servlet-api 6.1 */)) 091 { 092 throw new IllegalStateException("Status must be either 301, 302, 303, 307 or 308 but was: " + status); 093 } 094 this.redirectUrl = Args.notEmpty(redirectUrl, "redirectUrl"); 095 this.status = status; 096 } 097 098 /** 099 * @return redirect url 100 */ 101 public String getRedirectUrl() 102 { 103 return redirectUrl; 104 } 105 106 /** 107 * @return http redirect status code 108 */ 109 public int getStatus() 110 { 111 return status; 112 } 113 114 public RedirectRequestHandler mode(Mode mode) 115 { 116 this.mode = mode != null ? mode : Mode.AUTO; 117 return this; 118 } 119 120 @Override 121 public void respond(final IRequestCycle requestCycle) 122 { 123 final String location; 124 125 final String url = getRedirectUrl(); 126 127 if (url.charAt(0) == '/') 128 { 129 // context-absolute url 130 location = requestCycle.getUrlRenderer().renderContextRelativeUrl(url); 131 } 132 else 133 { 134 // if relative url, servlet container will translate to absolute as 135 // per the servlet spec 136 // if absolute url still do the same 137 location = url; 138 } 139 140 WebResponse response = (WebResponse)requestCycle.getResponse(); 141 142 if (mode == Mode.REDIRECT) 143 { 144 response.sendRedirect(location); 145 } 146 else if (mode == Mode.STATUS) 147 { 148 setStatus(response, requestCycle, location); 149 } 150 // Mode.AUTO 151 else if (status == HttpServletResponse.SC_FOUND) 152 { 153 response.sendRedirect(location); 154 } 155 else 156 { 157 setStatus(response, requestCycle, location); 158 } 159 } 160 161 private void setStatus(final WebResponse response, final IRequestCycle requestCycle, final String location) { 162 response.setStatus(status); 163 164 if (((WebRequest)requestCycle.getRequest()).isAjax()) 165 { 166 response.setHeader("Ajax-Location", location); 167 } 168 else 169 { 170 response.setHeader("Location", location); 171 } 172 } 173}