/*
* 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() {
}
}