View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
4   //  ------------------------------------------------------------------------
5   //  All rights reserved. This program and the accompanying materials
6   //  are made available under the terms of the Eclipse Public License v1.0
7   //  and Apache License v2.0 which accompanies this distribution.
8   //
9   //      The Eclipse Public License is available at
10  //      http://www.eclipse.org/legal/epl-v10.html
11  //
12  //      The Apache License v2.0 is available at
13  //      http://www.opensource.org/licenses/apache2.0.php
14  //
15  //  You may elect to redistribute this code under either of these licenses.
16  //  ========================================================================
17  //
18  
19  package org.eclipse.jetty.websocket.servlet;
20  
21  import java.net.HttpCookie;
22  import java.net.InetSocketAddress;
23  import java.net.URISyntaxException;
24  import java.security.Principal;
25  import java.security.cert.X509Certificate;
26  import java.util.ArrayList;
27  import java.util.Arrays;
28  import java.util.Collections;
29  import java.util.Enumeration;
30  import java.util.HashMap;
31  import java.util.Iterator;
32  import java.util.List;
33  import java.util.Map;
34  
35  import javax.servlet.http.Cookie;
36  import javax.servlet.http.HttpServletRequest;
37  
38  import org.eclipse.jetty.websocket.api.UpgradeRequest;
39  import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig;
40  import org.eclipse.jetty.websocket.api.util.QuoteUtil;
41  import org.eclipse.jetty.websocket.api.util.WSURI;
42  
43  /**
44   * Servlet specific {@link UpgradeRequest} implementation.
45   */
46  public class ServletUpgradeRequest extends UpgradeRequest
47  {
48      private HttpServletRequest req;
49  
50      public ServletUpgradeRequest(HttpServletRequest request) throws URISyntaxException
51      {
52          super(WSURI.toWebsocket(request.getRequestURL(),request.getQueryString()));
53          this.req = request;
54  
55          // Copy Request Line Details
56          setMethod(request.getMethod());
57          setHttpVersion(request.getProtocol());
58  
59          // Copy parameters
60          Map<String, List<String>> pmap = new HashMap<>();
61          if (request.getParameterMap() != null)
62          {
63              for (Map.Entry<String, String[]> entry : request.getParameterMap().entrySet())
64              {
65                  pmap.put(entry.getKey(),Arrays.asList(entry.getValue()));
66              }
67          }
68          super.setParameterMap(pmap);
69  
70          // Copy Cookies
71          Cookie rcookies[] = request.getCookies();
72          if (rcookies != null)
73          {
74              List<HttpCookie> cookies = new ArrayList<>();
75              for (Cookie rcookie : rcookies)
76              {
77                  HttpCookie hcookie = new HttpCookie(rcookie.getName(),rcookie.getValue());
78                  // no point handling domain/path/expires/secure/httponly on client request cookies
79                  cookies.add(hcookie);
80              }
81              super.setCookies(cookies);
82          }
83  
84          // Copy Headers
85          Enumeration<String> headerNames = request.getHeaderNames();
86          while (headerNames.hasMoreElements())
87          {
88              String name = headerNames.nextElement();
89              List<String> values = Collections.list(request.getHeaders(name));
90              setHeader(name,values);
91          }
92  
93          // Parse Sub Protocols
94          Enumeration<String> protocols = request.getHeaders("Sec-WebSocket-Protocol");
95          List<String> subProtocols = new ArrayList<>();
96          String protocol = null;
97          while ((protocol == null) && (protocols != null) && protocols.hasMoreElements())
98          {
99              String candidate = protocols.nextElement();
100             for (String p : parseProtocols(candidate))
101             {
102                 subProtocols.add(p);
103             }
104         }
105         setSubProtocols(subProtocols);
106 
107         // Parse Extension Configurations
108         Enumeration<String> e = request.getHeaders("Sec-WebSocket-Extensions");
109         while (e.hasMoreElements())
110         {
111             Iterator<String> extTokenIter = QuoteUtil.splitAt(e.nextElement(),",");
112             while (extTokenIter.hasNext())
113             {
114                 String extToken = extTokenIter.next();
115                 ExtensionConfig config = ExtensionConfig.parse(extToken);
116                 addExtensions(config);
117             }
118         }
119     }
120 
121     public X509Certificate[] getCertificates()
122     {
123         return (X509Certificate[])req.getAttribute("javax.servlet.request.X509Certificate");
124     }
125 
126     /**
127      * Equivalent to {@link HttpServletRequest#getLocalAddr()}
128      * 
129      * @return the local address
130      */
131     public String getLocalAddress()
132     {
133         return req.getLocalAddr();
134     }
135 
136     /**
137      * Equivalent to {@link HttpServletRequest#getLocalName()}
138      * 
139      * @return the local host name
140      */
141     public String getLocalHostName()
142     {
143         return req.getLocalName();
144     }
145 
146     /**
147      * Equivalent to {@link HttpServletRequest#getLocalPort()}
148      * 
149      * @return the local port
150      */
151     public int getLocalPort()
152     {
153         return req.getLocalPort();
154     }
155 
156     /**
157      * Return a {@link InetSocketAddress} for the local socket.
158      * <p>
159      * Warning: this can cause a DNS lookup
160      * 
161      * @return the local socket address
162      */
163     public InetSocketAddress getLocalSocketAddress()
164     {
165         return new InetSocketAddress(req.getLocalAddr(),req.getLocalPort());
166     }
167 
168     public Principal getPrincipal()
169     {
170         return req.getUserPrincipal();
171     }
172 
173     /**
174      * Equivalent to {@link HttpServletRequest#getRemoteAddr()}
175      * 
176      * @return the remote address
177      */
178     public String getRemoteAddress()
179     {
180         return req.getRemoteAddr();
181     }
182 
183     /**
184      * Equivalent to {@link HttpServletRequest#getRemoteHost()}
185      * 
186      * @return the remote host name
187      */
188     public String getRemoteHostName()
189     {
190         return req.getRemoteHost();
191     }
192 
193     /**
194      * Equivalent to {@link HttpServletRequest#getRemotePort()}
195      * 
196      * @return the remote port
197      */
198     public int getRemotePort()
199     {
200         return req.getRemotePort();
201     }
202 
203     /**
204      * Return a {@link InetSocketAddress} for the remote socket.
205      * <p>
206      * Warning: this can cause a DNS lookup
207      * 
208      * @return the remote socket address
209      */
210     public InetSocketAddress getRemoteSocketAddress()
211     {
212         return new InetSocketAddress(req.getRemoteAddr(),req.getRemotePort());
213     }
214 
215     public Map<String, Object> getServletAttributes()
216     {
217         Map<String, Object> attributes = new HashMap<String, Object>();
218 
219         for (String name : Collections.list(req.getAttributeNames()))
220         {
221             attributes.put(name,req.getAttribute(name));
222         }
223 
224         return attributes;
225     }
226 
227     public Map<String, List<String>> getServletParameters()
228     {
229         Map<String, List<String>> parameters = new HashMap<String, List<String>>();
230 
231         for (String name : Collections.list(req.getParameterNames()))
232         {
233             parameters.put(name,Collections.unmodifiableList(Arrays.asList(req.getParameterValues(name))));
234         }
235 
236         return parameters;
237     }
238 
239     /**
240      * Return the HttpSession if it exists.
241      * <p>
242      * Note: this is equivalent to {@link HttpServletRequest#getSession()} and will not create a new HttpSession.
243      */
244     @Override
245     public Object getSession()
246     {
247         return this.req.getSession(false);
248     }
249 
250     protected String[] parseProtocols(String protocol)
251     {
252         if (protocol == null)
253         {
254             return new String[] {};
255         }
256         protocol = protocol.trim();
257         if ((protocol == null) || (protocol.length() == 0))
258         {
259             return new String[] {};
260         }
261         String[] passed = protocol.split("\\s*,\\s*");
262         String[] protocols = new String[passed.length];
263         System.arraycopy(passed,0,protocols,0,passed.length);
264         return protocols;
265     }
266 
267     public void setServletAttribute(String name, Object o)
268     {
269         this.req.setAttribute(name,o);
270     }
271 
272     public Object getServletAttribute(String name)
273     {
274         return req.getAttribute(name);
275     }
276 
277     public boolean isUserInRole(String role)
278     {
279         return req.isUserInRole(role);
280     }
281 
282     public String getRequestPath()
283     {
284         // Since this can be called from a filter, we need to be smart about determining the target request path
285         String contextPath = req.getContextPath();
286         String requestPath = req.getRequestURI();
287         if (requestPath.startsWith(contextPath))
288         {
289             requestPath = requestPath.substring(contextPath.length());
290         }
291 
292         return requestPath;
293     }
294 }