/*
 * JBoss, Home of Professional Open Source.
 * Copyright 2014 Red Hat, Inc., and individual contributors
 * as indicated by the @author tags.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package io.undertow.util;

import io.undertow.server.HttpServerExchange;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Deque;
import java.util.Map;

Utility class for building redirects.
Author:Stuart Douglas
/** * Utility class for building redirects. * * @author Stuart Douglas */
public class RedirectBuilder { public static final String UTF_8 = StandardCharsets.UTF_8.name();
Redirects to a new relative path. All other data from the exchange is preserved.
Params:
  • exchange – The HTTP server exchange
  • newRelativePath – The new relative path
Returns:
/** * Redirects to a new relative path. All other data from the exchange is preserved. * * @param exchange The HTTP server exchange * @param newRelativePath The new relative path * @return */
public static String redirect(final HttpServerExchange exchange, final String newRelativePath) { return redirect(exchange, newRelativePath, true); }
Redirects to a new relative path. All other data from the exchange is preserved.
Params:
  • exchange – The HTTP server exchange
  • newRelativePath – The new relative path
  • includeParameters – If query and path parameters from the exchange should be included
Returns:
/** * Redirects to a new relative path. All other data from the exchange is preserved. * * @param exchange The HTTP server exchange * @param newRelativePath The new relative path * @param includeParameters If query and path parameters from the exchange should be included * @return */
public static String redirect(final HttpServerExchange exchange, final String newRelativePath, final boolean includeParameters) { try { StringBuilder uri = new StringBuilder(exchange.getRequestScheme()); uri.append("://"); uri.append(exchange.getHostAndPort()); uri.append(encodeUrlPart(exchange.getResolvedPath())); if (exchange.getResolvedPath().endsWith("/")) { if (newRelativePath.startsWith("/")) { uri.append(encodeUrlPart(newRelativePath.substring(1))); } else { uri.append(encodeUrlPart(newRelativePath)); } } else { if (!newRelativePath.startsWith("/")) { uri.append('/'); } uri.append(encodeUrlPart(newRelativePath)); } if (includeParameters) { if (!exchange.getPathParameters().isEmpty()) { boolean first = true; uri.append(';'); for (Map.Entry<String, Deque<String>> param : exchange.getPathParameters().entrySet()) { for (String value : param.getValue()) { if (first) { first = false; } else { uri.append('&'); } uri.append(URLEncoder.encode(param.getKey(), UTF_8)); uri.append('='); uri.append(URLEncoder.encode(value, UTF_8)); } } } if (!exchange.getQueryString().isEmpty()) { uri.append('?'); uri.append(exchange.getQueryString()); } } return uri.toString(); } catch (UnsupportedEncodingException e) { throw new RuntimeException(e); } }
perform URL encoding

TODO: this whole thing is kinda crappy.
Returns:
/** * perform URL encoding * <p/> * TODO: this whole thing is kinda crappy. * * @return */
private static String encodeUrlPart(final String part) throws UnsupportedEncodingException { //we need to go through and check part by part that a section does not need encoding int pos = 0; for (int i = 0; i < part.length(); ++i) { char c = part.charAt(i); if(c == '?') { break; } else if (c == '/') { if (pos != i) { String original = part.substring(pos, i); String encoded = URLEncoder.encode(original, UTF_8); if (!encoded.equals(original)) { return realEncode(part, pos); } } pos = i + 1; } else if (c == ' ') { return realEncode(part, pos); } } return part; } private static String realEncode(String part, int startPos) throws UnsupportedEncodingException { StringBuilder sb = new StringBuilder(); sb.append(part.substring(0, startPos)); int pos = startPos; for (int i = startPos; i < part.length(); ++i) { char c = part.charAt(i); if(c == '?') { break; } else if (c == '/') { if (pos != i) { String original = part.substring(pos, i); String encoded = URLEncoder.encode(original, UTF_8); sb.append(encoded); sb.append('/'); pos = i + 1; } } } String original = part.substring(pos); String encoded = URLEncoder.encode(original, UTF_8); sb.append(encoded); return sb.toString(); } private RedirectBuilder() { } }