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 javax.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 302 (Moved temporarily) 079 */ 080 public RedirectRequestHandler(final String redirectUrl, final int status) 081 { 082 if ((status != HttpServletResponse.SC_MOVED_PERMANENTLY) && 083 (status != HttpServletResponse.SC_MOVED_TEMPORARILY) && 084 (status != HttpServletResponse.SC_SEE_OTHER)) 085 { 086 throw new IllegalStateException("Status must be either 301, 302 or 303, but was: " + status); 087 } 088 this.redirectUrl = Args.notEmpty(redirectUrl, "redirectUrl"); 089 this.status = status; 090 } 091 092 /** 093 * @return redirect url 094 */ 095 public String getRedirectUrl() 096 { 097 return redirectUrl; 098 } 099 100 /** 101 * @return http redirect status code 102 */ 103 public int getStatus() 104 { 105 return status; 106 } 107 108 public RedirectRequestHandler mode(Mode mode) 109 { 110 this.mode = mode != null ? mode : Mode.AUTO; 111 return this; 112 } 113 114 @Override 115 public void respond(final IRequestCycle requestCycle) 116 { 117 final String location; 118 119 final String url = getRedirectUrl(); 120 121 if (url.charAt(0) == '/') 122 { 123 // context-absolute url 124 location = requestCycle.getUrlRenderer().renderContextRelativeUrl(url); 125 } 126 else 127 { 128 // if relative url, servlet container will translate to absolute as 129 // per the servlet spec 130 // if absolute url still do the same 131 location = url; 132 } 133 134 WebResponse response = (WebResponse)requestCycle.getResponse(); 135 136 if (mode == Mode.REDIRECT) 137 { 138 response.sendRedirect(location); 139 } 140 else if (mode == Mode.STATUS) 141 { 142 setStatus(response, requestCycle, location); 143 } 144 // Mode.AUTO 145 else if (status == HttpServletResponse.SC_MOVED_TEMPORARILY) 146 { 147 response.sendRedirect(location); 148 } 149 else 150 { 151 setStatus(response, requestCycle, location); 152 } 153 } 154 155 private void setStatus(final WebResponse response, final IRequestCycle requestCycle, final String location) { 156 response.setStatus(status); 157 158 if (((WebRequest)requestCycle.getRequest()).isAjax()) 159 { 160 response.setHeader("Ajax-Location", location); 161 } 162 else 163 { 164 response.setHeader("Location", location); 165 } 166 } 167}