blob: 3622b0765943493faefa19a72cc5a3e1f43f5380 [file] [log] [blame]
//
// ========================================================================
// Copyright (c) 1995-2015 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.websocket.servlet;
import java.net.HttpCookie;
import java.net.InetSocketAddress;
import java.net.URI;
import java.net.URISyntaxException;
import java.security.Principal;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.eclipse.jetty.websocket.api.UpgradeRequest;
import org.eclipse.jetty.websocket.api.WebSocketConstants;
import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig;
/**
* Servlet specific {@link UpgradeRequest} implementation.
*/
public class ServletUpgradeRequest implements UpgradeRequest
{
private static final String CANNOT_MODIFY_SERVLET_REQUEST = "Cannot modify Servlet Request";
private final URI requestURI;
private final UpgradeHttpServletRequest request;
private final boolean secure;
private List<HttpCookie> cookies;
private Map<String, List<String>> parameterMap;
private List<String> subprotocols;
public ServletUpgradeRequest(HttpServletRequest httpRequest) throws URISyntaxException
{
URI servletURI = URI.create(httpRequest.getRequestURL().toString());
this.secure = httpRequest.isSecure();
String scheme = secure ? "wss" : "ws";
String authority = servletURI.getAuthority();
String path = servletURI.getPath();
String query = httpRequest.getQueryString();
String fragment = null;
this.requestURI = new URI(scheme,authority,path,query,fragment);
this.request = new UpgradeHttpServletRequest(httpRequest);
}
@Override
public void addExtensions(ExtensionConfig... configs)
{
throw new UnsupportedOperationException(CANNOT_MODIFY_SERVLET_REQUEST);
}
@Override
public void addExtensions(String... configs)
{
throw new UnsupportedOperationException(CANNOT_MODIFY_SERVLET_REQUEST);
}
@Override
public void clearHeaders()
{
throw new UnsupportedOperationException(CANNOT_MODIFY_SERVLET_REQUEST);
}
public void complete()
{
request.complete();
}
public X509Certificate[] getCertificates()
{
return (X509Certificate[])request.getAttribute("javax.servlet.request.X509Certificate");
}
@Override
public List<HttpCookie> getCookies()
{
if(cookies == null)
{
Cookie[] requestCookies = request.getCookies();
if (requestCookies != null)
{
cookies = new ArrayList<>();
for (Cookie requestCookie : requestCookies)
{
HttpCookie cookie = new HttpCookie(requestCookie.getName(), requestCookie.getValue());
// No point handling domain/path/expires/secure/httponly on client request cookies
cookies.add(cookie);
}
}
}
return cookies;
}
@Override
public List<ExtensionConfig> getExtensions()
{
Enumeration<String> e = request.getHeaders("Sec-WebSocket-Extensions");
return ExtensionConfig.parseEnum(e);
}
@Override
public String getHeader(String name)
{
return request.getHeader(name);
}
@Override
public int getHeaderInt(String name)
{
String val = request.getHeader(name);
if (val == null)
{
return -1;
}
return Integer.parseInt(val);
}
@Override
public Map<String, List<String>> getHeaders()
{
return request.getHeaders();
}
@Override
public List<String> getHeaders(String name)
{
return request.getHeaders().get(name);
}
@Override
public String getHost()
{
return requestURI.getHost();
}
/**
* Return the underlying HttpServletRequest that existed at Upgrade time.
* <p>
* Note: many features of the HttpServletRequest are invalid when upgraded,
* especially ones that deal with body content, streams, readers, and responses.
*
* @return a limited version of the underlying HttpServletRequest
*/
public HttpServletRequest getHttpServletRequest()
{
return request;
}
@Override
public String getHttpVersion()
{
return request.getProtocol();
}
/**
* Equivalent to {@link HttpServletRequest#getLocalAddr()}
*
* @return the local address
*/
public String getLocalAddress()
{
return request.getLocalAddr();
}
/**
* Equivalent to {@link HttpServletRequest#getLocale()}
*
* @return the preferred <code>Locale</code> for the client
*/
public Locale getLocale()
{
return request.getLocale();
}
/**
* Equivalent to {@link HttpServletRequest#getLocales()}
*
* @return an Enumeration of preferred Locale objects
*/
public Enumeration<Locale> getLocales()
{
return request.getLocales();
}
/**
* Equivalent to {@link HttpServletRequest#getLocalName()}
*
* @return the local host name
*/
public String getLocalHostName()
{
return request.getLocalName();
}
/**
* Equivalent to {@link HttpServletRequest#getLocalPort()}
*
* @return the local port
*/
public int getLocalPort()
{
return request.getLocalPort();
}
/**
* Return a {@link InetSocketAddress} for the local socket.
* <p>
* Warning: this can cause a DNS lookup
*
* @return the local socket address
*/
public InetSocketAddress getLocalSocketAddress()
{
return new InetSocketAddress(getLocalAddress(), getLocalPort());
}
@Override
public String getMethod()
{
return request.getMethod();
}
@Override
public String getOrigin()
{
return getHeader("Origin");
}
@Override
public Map<String, List<String>> getParameterMap()
{
if (parameterMap == null)
{
Map<String, String[]> requestParams = request.getParameterMap();
if (requestParams != null)
{
parameterMap = new HashMap<>(requestParams.size());
for (Map.Entry<String, String[]> entry : requestParams.entrySet())
parameterMap.put(entry.getKey(),Arrays.asList(entry.getValue()));
}
}
return parameterMap;
}
/**
* @return the principal
* @deprecated use {@link #getUserPrincipal()} instead
*/
@Deprecated
public Principal getPrincipal()
{
return getUserPrincipal();
}
@Override
public String getProtocolVersion()
{
String version = request.getHeader(WebSocketConstants.SEC_WEBSOCKET_VERSION);
if(version == null)
{
return Integer.toString(WebSocketConstants.SPEC_VERSION);
}
return version;
}
@Override
public String getQueryString()
{
return requestURI.getQuery();
}
/**
* Equivalent to {@link HttpServletRequest#getRemoteAddr()}
*
* @return the remote address
*/
public String getRemoteAddress()
{
return request.getRemoteAddr();
}
/**
* Equivalent to {@link HttpServletRequest#getRemoteHost()}
*
* @return the remote host name
*/
public String getRemoteHostName()
{
return request.getRemoteHost();
}
/**
* Equivalent to {@link HttpServletRequest#getRemotePort()}
*
* @return the remote port
*/
public int getRemotePort()
{
return request.getRemotePort();
}
/**
* Return a {@link InetSocketAddress} for the remote socket.
* <p>
* Warning: this can cause a DNS lookup
*
* @return the remote socket address
*/
public InetSocketAddress getRemoteSocketAddress()
{
return new InetSocketAddress(getRemoteAddress(), getRemotePort());
}
public String getRequestPath()
{
// Since this can be called from a filter, we need to be smart about determining the target request path.
String contextPath = request.getContextPath();
String requestPath = request.getRequestURI();
if (requestPath.startsWith(contextPath))
requestPath = requestPath.substring(contextPath.length());
return requestPath;
}
@Override
public URI getRequestURI()
{
return requestURI;
}
public Object getServletAttribute(String name)
{
return request.getAttribute(name);
}
public Map<String, Object> getServletAttributes()
{
return request.getAttributes();
}
public Map<String, List<String>> getServletParameters()
{
return getParameterMap();
}
/**
* Return the HttpSession if it exists.
* <p>
* Note: this is equivalent to {@link HttpServletRequest#getSession(boolean)}
* and will not create a new HttpSession.
*/
@Override
public HttpSession getSession()
{
return request.getSession(false);
}
@Override
public List<String> getSubProtocols()
{
if (subprotocols == null)
{
Enumeration<String> requestProtocols = request.getHeaders("Sec-WebSocket-Protocol");
if (requestProtocols != null)
{
subprotocols = new ArrayList<>(2);
while (requestProtocols.hasMoreElements())
{
String candidate = requestProtocols.nextElement();
Collections.addAll(subprotocols,parseProtocols(candidate));
}
}
}
return subprotocols;
}
/**
* Equivalent to {@link HttpServletRequest#getUserPrincipal()}
*/
public Principal getUserPrincipal()
{
return request.getUserPrincipal();
}
@Override
public boolean hasSubProtocol(String test)
{
for (String protocol : getSubProtocols())
{
if (protocol.equalsIgnoreCase(test))
{
return true;
}
}
return false;
}
@Override
public boolean isOrigin(String test)
{
return test.equalsIgnoreCase(getOrigin());
}
@Override
public boolean isSecure()
{
return this.secure;
}
public boolean isUserInRole(String role)
{
return request.isUserInRole(role);
}
private String[] parseProtocols(String protocol)
{
if (protocol == null)
return new String[0];
protocol = protocol.trim();
if (protocol.length() == 0)
return new String[0];
return protocol.split("\\s*,\\s*");
}
@Override
public void setCookies(List<HttpCookie> cookies)
{
throw new UnsupportedOperationException(CANNOT_MODIFY_SERVLET_REQUEST);
}
@Override
public void setExtensions(List<ExtensionConfig> configs)
{
throw new UnsupportedOperationException(CANNOT_MODIFY_SERVLET_REQUEST);
}
@Override
public void setHeader(String name, List<String> values)
{
throw new UnsupportedOperationException(CANNOT_MODIFY_SERVLET_REQUEST);
}
@Override
public void setHeader(String name, String value)
{
throw new UnsupportedOperationException(CANNOT_MODIFY_SERVLET_REQUEST);
}
@Override
public void setHeaders(Map<String, List<String>> headers)
{
throw new UnsupportedOperationException(CANNOT_MODIFY_SERVLET_REQUEST);
}
@Override
public void setHttpVersion(String httpVersion)
{
throw new UnsupportedOperationException(CANNOT_MODIFY_SERVLET_REQUEST);
}
@Override
public void setMethod(String method)
{
throw new UnsupportedOperationException(CANNOT_MODIFY_SERVLET_REQUEST);
}
@Override
public void setRequestURI(URI uri)
{
throw new UnsupportedOperationException(CANNOT_MODIFY_SERVLET_REQUEST);
}
public void setServletAttribute(String name, Object value)
{
request.setAttribute(name, value);
}
@Override
public void setSession(Object session)
{
throw new UnsupportedOperationException(CANNOT_MODIFY_SERVLET_REQUEST);
}
@Override
public void setSubProtocols(List<String> subProtocols)
{
throw new UnsupportedOperationException(CANNOT_MODIFY_SERVLET_REQUEST);
}
@Override
public void setSubProtocols(String... protocols)
{
throw new UnsupportedOperationException(CANNOT_MODIFY_SERVLET_REQUEST);
}
}