/*
* 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.server.session;
import java.util.Deque;
import java.util.Locale;
import io.undertow.UndertowLogger;
import io.undertow.server.HttpServerExchange;
Session config that is based on a path parameter and URL rewriting
Author: Stuart Douglas
/**
* Session config that is based on a path parameter and URL rewriting
*
* @author Stuart Douglas
*/
public class PathParameterSessionConfig implements SessionConfig {
private final String name;
public PathParameterSessionConfig(final String name) {
this.name = name;
}
public PathParameterSessionConfig() {
this(SessionCookieConfig.DEFAULT_SESSION_ID.toLowerCase(Locale.ENGLISH));
}
@Override
public void setSessionId(final HttpServerExchange exchange, final String sessionId) {
exchange.getPathParameters().remove(name);
exchange.addPathParam(name, sessionId);
UndertowLogger.SESSION_LOGGER.tracef("Setting path parameter session id %s on %s", sessionId, exchange);
}
@Override
public void clearSession(final HttpServerExchange exchange, final String sessionId) {
UndertowLogger.SESSION_LOGGER.tracef("Clearing path parameter session id %s on %s", sessionId, exchange);
exchange.getPathParameters().remove(name);
}
@Override
public String findSessionId(final HttpServerExchange exchange) {
Deque<String> stringDeque = exchange.getPathParameters().get(name);
if (stringDeque == null) {
return null;
}
UndertowLogger.SESSION_LOGGER.tracef("Found path parameter session id %s on %s", stringDeque.getFirst(), exchange);
return stringDeque.getFirst();
}
@Override
public SessionCookieSource sessionCookieSource(HttpServerExchange exchange) {
return findSessionId(exchange) != null ? SessionCookieSource.URL : SessionCookieSource.NONE;
}
Return the specified URL with the specified session identifier
suitably encoded.
Params: - url – URL to be encoded with the session id
- sessionId – Session id to be included in the encoded URL
/**
* Return the specified URL with the specified session identifier
* suitably encoded.
*
* @param url URL to be encoded with the session id
* @param sessionId Session id to be included in the encoded URL
*/
@Override
public String rewriteUrl(final String url, final String sessionId) {
if ((url == null) || (sessionId == null))
return (url);
String path = url;
String query = "";
String anchor = "";
String fragment = "";
int question = url.indexOf('?');
if (question >= 0) {
path = url.substring(0, question);
query = url.substring(question);
}
int pound = path.indexOf('#');
if (pound >= 0) {
anchor = path.substring(pound);
path = path.substring(0, pound);
}
int fragmentIndex = path.lastIndexOf(';');
if(fragmentIndex >= 0) {
fragment = path.substring(fragmentIndex);
path = path.substring(0, fragmentIndex);
}
StringBuilder sb = new StringBuilder(path);
if (sb.length() > 0) { // jsessionid can't be first.
if(fragmentIndex > 0) {
if(fragment.contains(name)) {
//this does not necessarily mean that this parameter is present. It could be part of the value, or the
//name could be a substring of a larger key name
sb.append(';'); //we make sure we append the fragment portion
String key = null;
StringBuilder paramBuilder = new StringBuilder();
for (int i = 1; i < fragment.length(); ++i) {
char c = fragment.charAt(i);
if (key == null) {
if (c == '&' || c == '=') {
key = paramBuilder.toString();
paramBuilder.setLength(0);
if (c == '&') {
if (!key.equals(name)) { //we don't append if it matches the name
sb.append(key);
sb.append('&');
}
key = null;
}
} else {
paramBuilder.append(c);
}
} else {
if (c == '&') {
String value = paramBuilder.toString();
paramBuilder.setLength(0);
if (!key.equals(name)) { //we don't append if it matches the name
sb.append(key);
sb.append('=');
sb.append(value);
sb.append('&');
}
key = null;
} else {
paramBuilder.append(c);
}
}
}
if(paramBuilder.length() > 0) {
if(key == null) {
key = paramBuilder.toString();
if (!key.equals(name)) { //we don't append if it matches the name
sb.append(key);
sb.append('&');
}
} else {
String value = paramBuilder.toString();
if (!key.equals(name)) { //we don't append if it matches the name
sb.append(key);
sb.append('=');
sb.append(value);
sb.append('&');
}
}
}
} else {
sb.append(fragment);
sb.append("&");
}
} else {
sb.append(';');
}
sb.append(name);
sb.append('=');
sb.append(sessionId);
}
sb.append(anchor);
sb.append(query);
UndertowLogger.SESSION_LOGGER.tracef("Rewrote URL from %s to %s", url, sessionId);
return (sb.toString());
}
}