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

18
19 package io.undertow.server.session;
20
21 import java.util.Deque;
22 import java.util.Locale;
23
24 import io.undertow.UndertowLogger;
25 import io.undertow.server.HttpServerExchange;
26
27 /**
28  * Session config that is based on a path parameter and URL rewriting
29  *
30  * @author Stuart Douglas
31  */

32 public class PathParameterSessionConfig implements SessionConfig {
33
34     private final String name;
35
36     public PathParameterSessionConfig(final String name) {
37         this.name = name;
38     }
39
40     public PathParameterSessionConfig() {
41         this(SessionCookieConfig.DEFAULT_SESSION_ID.toLowerCase(Locale.ENGLISH));
42     }
43
44     @Override
45     public void setSessionId(final HttpServerExchange exchange, final String sessionId) {
46         exchange.getPathParameters().remove(name);
47         exchange.addPathParam(name, sessionId);
48         UndertowLogger.SESSION_LOGGER.tracef("Setting path parameter session id %s on %s", sessionId, exchange);
49     }
50
51     @Override
52     public void clearSession(final HttpServerExchange exchange, final String sessionId) {
53         UndertowLogger.SESSION_LOGGER.tracef("Clearing path parameter session id %s on %s", sessionId, exchange);
54         exchange.getPathParameters().remove(name);
55     }
56
57     @Override
58     public String findSessionId(final HttpServerExchange exchange) {
59         Deque<String> stringDeque = exchange.getPathParameters().get(name);
60         if (stringDeque == null) {
61             return null;
62         }
63         UndertowLogger.SESSION_LOGGER.tracef("Found path parameter session id %s on %s", stringDeque.getFirst(), exchange);
64         return stringDeque.getFirst();
65     }
66
67     @Override
68     public SessionCookieSource sessionCookieSource(HttpServerExchange exchange) {
69         return findSessionId(exchange) != null ? SessionCookieSource.URL : SessionCookieSource.NONE;
70     }
71
72     /**
73      * Return the specified URL with the specified session identifier
74      * suitably encoded.
75      *
76      * @param url       URL to be encoded with the session id
77      * @param sessionId Session id to be included in the encoded URL
78      */

79     @Override
80     public String rewriteUrl(final String url, final String sessionId) {
81         if ((url == null) || (sessionId == null))
82             return (url);
83
84         String path = url;
85         String query = "";
86         String anchor = "";
87         final int question = url.indexOf('?');
88         if (question >= 0) {
89             path = url.substring(0, question);
90             query = url.substring(question);
91         }
92         final int pound = path.indexOf('#');
93         if (pound >= 0) {
94             anchor = path.substring(pound);
95             path = path.substring(0, pound);
96         }
97         final StringBuilder sb = new StringBuilder();
98         // look for param
99         final int paramIndex = path.indexOf(";" + name);
100         // found param, strip it off from path
101         if (paramIndex >= 0) {
102             sb.append(path.substring(0, paramIndex));
103             final String remainder = path.substring(paramIndex + name.length() + 1);
104             final int endIndex1 = remainder.indexOf(";");
105             final int endIndex2 = remainder.indexOf("/");
106             if (endIndex1 != -1) {
107                 if (endIndex2 != -1 && endIndex2 < endIndex1) {
108                     sb.append(remainder.substring(endIndex2));
109                 } else {
110                     sb.append(remainder.substring(endIndex1));
111                 }
112             } else if (endIndex2 != -1) {
113                 sb.append(remainder.substring(endIndex2));
114             }
115             // else the rest of the path will be discarded, as it contains just the parameter we want to exclude
116         } else {
117             // name param was not found, we can use the path as is
118             sb.append(path);
119         }
120         // append ;name=sessionId
121         sb.append(';');
122         sb.append(name);
123         sb.append('=');
124         sb.append(sessionId);
125         // apend anchor and query
126         sb.append(anchor);
127         sb.append(query);
128         UndertowLogger.SESSION_LOGGER.tracef("Rewrote URL from %s to %s", url, sb);
129         return sb.toString();
130     }
131 }
132