2 // ========================================================================
3 // Copyright (c) 1995-2016 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.
9 // The Eclipse Public License is available at
10 // http://www.eclipse.org/legal/epl-v10.html
12 // The Apache License v2.0 is available at
13 // http://www.opensource.org/licenses/apache2.0.php
15 // You may elect to redistribute this code under either of these licenses.
16 // ========================================================================
19 package org.eclipse.jetty.server;
21 import java.io.BufferedReader;
22 import java.io.ByteArrayOutputStream;
24 import java.io.IOException;
25 import java.io.InputStream;
26 import java.io.InputStreamReader;
27 import java.io.UnsupportedEncodingException;
28 import java.net.InetAddress;
29 import java.net.InetSocketAddress;
30 import java.nio.charset.Charset;
31 import java.nio.charset.StandardCharsets;
32 import java.nio.charset.UnsupportedCharsetException;
33 import java.security.Principal;
34 import java.util.ArrayList;
35 import java.util.Collection;
36 import java.util.Collections;
37 import java.util.Enumeration;
38 import java.util.EventListener;
39 import java.util.HashMap;
40 import java.util.List;
41 import java.util.Locale;
44 import javax.servlet.AsyncContext;
45 import javax.servlet.AsyncListener;
46 import javax.servlet.DispatcherType;
47 import javax.servlet.MultipartConfigElement;
48 import javax.servlet.RequestDispatcher;
49 import javax.servlet.ServletContext;
50 import javax.servlet.ServletException;
51 import javax.servlet.ServletInputStream;
52 import javax.servlet.ServletRequest;
53 import javax.servlet.ServletRequestAttributeEvent;
54 import javax.servlet.ServletRequestAttributeListener;
55 import javax.servlet.ServletRequestEvent;
56 import javax.servlet.ServletRequestListener;
57 import javax.servlet.ServletResponse;
58 import javax.servlet.http.Cookie;
59 import javax.servlet.http.HttpServletRequest;
60 import javax.servlet.http.HttpServletResponse;
61 import javax.servlet.http.HttpSession;
62 import javax.servlet.http.HttpUpgradeHandler;
63 import javax.servlet.http.Part;
65 import org.eclipse.jetty.http.HttpCookie;
66 import org.eclipse.jetty.http.HttpFields;
67 import org.eclipse.jetty.http.HttpHeader;
68 import org.eclipse.jetty.http.HttpMethod;
69 import org.eclipse.jetty.http.HttpStatus;
70 import org.eclipse.jetty.http.HttpURI;
71 import org.eclipse.jetty.http.HttpVersion;
72 import org.eclipse.jetty.http.MimeTypes;
73 import org.eclipse.jetty.server.handler.ContextHandler;
74 import org.eclipse.jetty.server.handler.ContextHandler.Context;
75 import org.eclipse.jetty.server.session.AbstractSession;
76 import org.eclipse.jetty.util.Attributes;
77 import org.eclipse.jetty.util.AttributesMap;
78 import org.eclipse.jetty.util.IO;
79 import org.eclipse.jetty.util.MultiException;
80 import org.eclipse.jetty.util.MultiMap;
81 import org.eclipse.jetty.util.MultiPartInputStreamParser;
82 import org.eclipse.jetty.util.StringUtil;
83 import org.eclipse.jetty.util.URIUtil;
84 import org.eclipse.jetty.util.UrlEncoded;
85 import org.eclipse.jetty.util.log.Log;
86 import org.eclipse.jetty.util.log.Logger;
88 /* ------------------------------------------------------------ */
92 * Implements {@link javax.servlet.http.HttpServletRequest} from the <code>javax.servlet.http</code> package.
95 * The standard interface of mostly getters, is extended with setters so that the request is mutable by the handlers that it is passed to. This allows the
96 * request object to be as lightweight as possible and not actually implement any significant behavior. For example
99 * <li>The {@link Request#getContextPath()} method will return null, until the request has been passed to a {@link ContextHandler} which matches the
100 * {@link Request#getPathInfo()} with a context path and calls {@link Request#setContextPath(String)} as a result.</li>
102 * <li>the HTTP session methods will all return null sessions until such time as a request has been passed to a
103 * {@link org.eclipse.jetty.server.session.SessionHandler} which checks for session cookies and enables the ability to create new sessions.</li>
105 * <li>The {@link Request#getServletPath()} method will return null until the request has been passed to a <code>org.eclipse.jetty.servlet.ServletHandler</code>
106 * and the pathInfo matched against the servlet URL patterns and {@link Request#setServletPath(String)} called as a result.</li>
109 * A request instance is created for each connection accepted by the server and recycled for each HTTP request received via that connection.
110 * An effort is made to avoid reparsing headers and cookies that are likely to be the same for requests from the same connection.
113 * The form content that a request can process is limited to protect from Denial of Service attacks. The size in bytes is limited by
114 * {@link ContextHandler#getMaxFormContentSize()} or if there is no context then the "org.eclipse.jetty.server.Request.maxFormContentSize" {@link Server}
115 * attribute. The number of parameters keys is limited by {@link ContextHandler#getMaxFormKeys()} or if there is no context then the
116 * "org.eclipse.jetty.server.Request.maxFormKeys" {@link Server} attribute.
120 public class Request implements HttpServletRequest
122 public static final String __MULTIPART_CONFIG_ELEMENT = "org.eclipse.jetty.multipartConfig";
123 public static final String __MULTIPART_INPUT_STREAM = "org.eclipse.jetty.multiPartInputStream";
124 public static final String __MULTIPART_CONTEXT = "org.eclipse.jetty.multiPartContext";
126 private static final Logger LOG = Log.getLogger(Request.class);
127 private static final Collection<Locale> __defaultLocale = Collections.singleton(Locale.getDefault());
128 private static final int __NONE = 0, _STREAM = 1, __READER = 2;
130 private final HttpChannel<?> _channel;
131 private final HttpFields _fields=new HttpFields();
132 private final List<ServletRequestAttributeListener> _requestAttributeListeners=new ArrayList<>();
133 private final HttpInput<?> _input;
135 public static class MultiPartCleanerListener implements ServletRequestListener
138 public void requestDestroyed(ServletRequestEvent sre)
140 //Clean up any tmp files created by MultiPartInputStream
141 MultiPartInputStreamParser mpis = (MultiPartInputStreamParser)sre.getServletRequest().getAttribute(__MULTIPART_INPUT_STREAM);
144 ContextHandler.Context context = (ContextHandler.Context)sre.getServletRequest().getAttribute(__MULTIPART_CONTEXT);
146 //Only do the cleanup if we are exiting from the context in which a servlet parsed the multipart files
147 if (context == sre.getServletContext())
153 catch (MultiException e)
155 sre.getServletContext().log("Errors deleting multipart tmp files", e);
162 public void requestInitialized(ServletRequestEvent sre)
164 //nothing to do, multipart config set up by ServletHolder.handle()
171 private boolean _secure;
172 private boolean _asyncSupported = true;
173 private boolean _newContext;
174 private boolean _cookiesExtracted = false;
175 private boolean _handled = false;
176 private boolean _paramsExtracted;
177 private boolean _requestedSessionIdFromCookie = false;
178 private volatile Attributes _attributes;
179 private Authentication _authentication;
180 private String _characterEncoding;
181 private ContextHandler.Context _context;
182 private String _contextPath;
183 private CookieCutter _cookies;
184 private DispatcherType _dispatcherType;
185 private int _inputState = __NONE;
186 private HttpMethod _httpMethod;
187 private String _httpMethodString;
188 private MultiMap<String> _queryParameters;
189 private MultiMap<String> _contentParameters;
190 private MultiMap<String> _parameters;
191 private String _pathInfo;
193 private HttpVersion _httpVersion = HttpVersion.HTTP_1_1;
194 private String _queryEncoding;
195 private String _queryString;
196 private BufferedReader _reader;
197 private String _readerEncoding;
198 private InetSocketAddress _remote;
199 private String _requestedSessionId;
200 private String _requestURI;
201 private Map<Object, HttpSession> _savedNewSessions;
202 private String _scheme = URIUtil.HTTP;
203 private UserIdentity.Scope _scope;
204 private String _serverName;
205 private String _servletPath;
206 private HttpSession _session;
207 private SessionManager _sessionManager;
208 private long _timeStamp;
209 private HttpURI _uri;
210 private MultiPartInputStreamParser _multiPartInputStream; //if the request is a multi-part mime
211 private AsyncContextState _async;
213 /* ------------------------------------------------------------ */
214 public Request(HttpChannel<?> channel, HttpInput<?> input)
220 /* ------------------------------------------------------------ */
221 public HttpFields getHttpFields()
226 /* ------------------------------------------------------------ */
227 public HttpInput<?> getHttpInput()
232 /* ------------------------------------------------------------ */
233 public void addEventListener(final EventListener listener)
235 if (listener instanceof ServletRequestAttributeListener)
236 _requestAttributeListeners.add((ServletRequestAttributeListener)listener);
237 if (listener instanceof AsyncListener)
238 throw new IllegalArgumentException(listener.getClass().toString());
241 public void extractParameters()
243 if (_paramsExtracted)
246 _paramsExtracted = true;
248 // Extract query string parameters; these may be replaced by a forward()
249 // and may have already been extracted by mergeQueryParameters().
250 if (_queryParameters == null)
251 _queryParameters = extractQueryParameters();
253 // Extract content parameters; these cannot be replaced by a forward()
254 // once extracted and may have already been extracted by getParts() or
255 // by a processing happening after a form-based authentication.
256 if (_contentParameters == null)
257 _contentParameters = extractContentParameters();
259 _parameters = restoreParameters();
262 private MultiMap<String> extractQueryParameters()
264 MultiMap<String> result = new MultiMap<>();
265 if (_uri != null && _uri.hasQuery())
267 if (_queryEncoding == null)
269 _uri.decodeQueryTo(result);
275 _uri.decodeQueryTo(result, _queryEncoding);
277 catch (UnsupportedEncodingException e)
279 if (LOG.isDebugEnabled())
282 LOG.warn(e.toString());
289 private MultiMap<String> extractContentParameters()
291 MultiMap<String> result = new MultiMap<>();
293 String contentType = getContentType();
294 if (contentType != null && !contentType.isEmpty())
296 contentType = HttpFields.valueParameters(contentType, null);
297 int contentLength = getContentLength();
298 if (contentLength != 0)
300 if (MimeTypes.Type.FORM_ENCODED.is(contentType) && _inputState == __NONE &&
301 (HttpMethod.POST.is(getMethod()) || HttpMethod.PUT.is(getMethod())))
303 extractFormParameters(result);
305 else if (contentType.startsWith("multipart/form-data") &&
306 getAttribute(__MULTIPART_CONFIG_ELEMENT) != null &&
307 _multiPartInputStream == null)
309 extractMultipartParameters(result);
317 public void extractFormParameters(MultiMap<String> params)
321 int maxFormContentSize = -1;
322 int maxFormKeys = -1;
324 if (_context != null)
326 maxFormContentSize = _context.getContextHandler().getMaxFormContentSize();
327 maxFormKeys = _context.getContextHandler().getMaxFormKeys();
330 if (maxFormContentSize < 0)
332 Object obj = _channel.getServer().getAttribute("org.eclipse.jetty.server.Request.maxFormContentSize");
334 maxFormContentSize = 200000;
335 else if (obj instanceof Number)
337 Number size = (Number)obj;
338 maxFormContentSize = size.intValue();
340 else if (obj instanceof String)
342 maxFormContentSize = Integer.valueOf((String)obj);
348 Object obj = _channel.getServer().getAttribute("org.eclipse.jetty.server.Request.maxFormKeys");
351 else if (obj instanceof Number)
353 Number keys = (Number)obj;
354 maxFormKeys = keys.intValue();
356 else if (obj instanceof String)
358 maxFormKeys = Integer.valueOf((String)obj);
362 int contentLength = getContentLength();
363 if (contentLength > maxFormContentSize && maxFormContentSize > 0)
365 throw new IllegalStateException("Form too large: " + contentLength + " > " + maxFormContentSize);
367 InputStream in = getInputStream();
368 if (_input.isAsync())
369 throw new IllegalStateException("Cannot extract parameters with async IO");
371 UrlEncoded.decodeTo(in,params,getCharacterEncoding(),contentLength<0?maxFormContentSize:-1,maxFormKeys);
373 catch (IOException e)
375 if (LOG.isDebugEnabled())
378 LOG.warn(e.toString());
382 private void extractMultipartParameters(MultiMap<String> result)
388 catch (IOException | ServletException e)
391 throw new RuntimeException(e);
395 /* ------------------------------------------------------------ */
397 public AsyncContext getAsyncContext()
399 HttpChannelState state = getHttpChannelState();
400 if (_async==null || !state.isAsyncStarted())
401 throw new IllegalStateException(state.getStatusString());
406 /* ------------------------------------------------------------ */
407 public HttpChannelState getHttpChannelState()
409 return _channel.getState();
412 /* ------------------------------------------------------------ */
414 * Get Request Attribute.
415 * <p>Also supports jetty specific attributes to gain access to Jetty APIs:
417 * <dt>org.eclipse.jetty.server.Server</dt><dd>The Jetty Server instance</dd>
418 * <dt>org.eclipse.jetty.server.HttpChannel</dt><dd>The HttpChannel for this request</dd>
419 * <dt>org.eclipse.jetty.server.HttpConnection</dt><dd>The HttpConnection or null if another transport is used</dd>
421 * While these attributes may look like security problems, they are exposing nothing that is not already
422 * available via reflection from a Request instance.
424 * @see javax.servlet.ServletRequest#getAttribute(java.lang.String)
427 public Object getAttribute(String name)
429 if (name.startsWith("org.eclipse.jetty"))
431 if ("org.eclipse.jetty.server.Server".equals(name))
432 return _channel.getServer();
433 if ("org.eclipse.jetty.server.HttpChannel".equals(name))
435 if ("org.eclipse.jetty.server.HttpConnection".equals(name) &&
436 _channel.getHttpTransport() instanceof HttpConnection)
437 return _channel.getHttpTransport();
439 return (_attributes == null)?null:_attributes.getAttribute(name);
442 /* ------------------------------------------------------------ */
444 * @see javax.servlet.ServletRequest#getAttributeNames()
447 public Enumeration<String> getAttributeNames()
449 if (_attributes == null)
450 return Collections.enumeration(Collections.<String>emptyList());
452 return AttributesMap.getAttributeNamesCopy(_attributes);
455 /* ------------------------------------------------------------ */
458 public Attributes getAttributes()
460 if (_attributes == null)
461 _attributes = new AttributesMap();
465 /* ------------------------------------------------------------ */
467 * Get the authentication.
469 * @return the authentication
471 public Authentication getAuthentication()
473 return _authentication;
476 /* ------------------------------------------------------------ */
478 * @see javax.servlet.http.HttpServletRequest#getAuthType()
481 public String getAuthType()
483 if (_authentication instanceof Authentication.Deferred)
484 setAuthentication(((Authentication.Deferred)_authentication).authenticate(this));
486 if (_authentication instanceof Authentication.User)
487 return ((Authentication.User)_authentication).getAuthMethod();
491 /* ------------------------------------------------------------ */
493 * @see javax.servlet.ServletRequest#getCharacterEncoding()
496 public String getCharacterEncoding()
498 return _characterEncoding;
501 /* ------------------------------------------------------------ */
503 * @return Returns the connection.
505 public HttpChannel<?> getHttpChannel()
510 /* ------------------------------------------------------------ */
512 * @see javax.servlet.ServletRequest#getContentLength()
515 public int getContentLength()
517 return (int)_fields.getLongField(HttpHeader.CONTENT_LENGTH.toString());
520 /* ------------------------------------------------------------ */
522 * @see javax.servlet.ServletRequest.getContentLengthLong()
525 public long getContentLengthLong()
527 return _fields.getLongField(HttpHeader.CONTENT_LENGTH.toString());
530 /* ------------------------------------------------------------ */
531 public long getContentRead()
533 return _input.getContentRead();
536 /* ------------------------------------------------------------ */
538 * @see javax.servlet.ServletRequest#getContentType()
541 public String getContentType()
543 return _fields.getStringField(HttpHeader.CONTENT_TYPE);
546 /* ------------------------------------------------------------ */
548 * @return The current {@link Context context} used for this request, or <code>null</code> if {@link #setContext} has not yet been called.
550 public Context getContext()
555 /* ------------------------------------------------------------ */
557 * @see javax.servlet.http.HttpServletRequest#getContextPath()
560 public String getContextPath()
565 /* ------------------------------------------------------------ */
567 * @see javax.servlet.http.HttpServletRequest#getCookies()
570 public Cookie[] getCookies()
572 if (_cookiesExtracted)
574 if (_cookies == null || _cookies.getCookies().length == 0)
577 return _cookies.getCookies();
580 _cookiesExtracted = true;
582 Enumeration<?> enm = _fields.getValues(HttpHeader.COOKIE.toString());
587 if (_cookies == null)
588 _cookies = new CookieCutter();
590 while (enm.hasMoreElements())
592 String c = (String)enm.nextElement();
593 _cookies.addCookieField(c);
597 //Javadoc for Request.getCookies() stipulates null for no cookies
598 if (_cookies == null || _cookies.getCookies().length == 0)
601 return _cookies.getCookies();
604 /* ------------------------------------------------------------ */
606 * @see javax.servlet.http.HttpServletRequest#getDateHeader(java.lang.String)
609 public long getDateHeader(String name)
611 return _fields.getDateField(name);
614 /* ------------------------------------------------------------ */
616 public DispatcherType getDispatcherType()
618 return _dispatcherType;
621 /* ------------------------------------------------------------ */
623 * @see javax.servlet.http.HttpServletRequest#getHeader(java.lang.String)
626 public String getHeader(String name)
628 return _fields.getStringField(name);
631 /* ------------------------------------------------------------ */
633 * @see javax.servlet.http.HttpServletRequest#getHeaderNames()
636 public Enumeration<String> getHeaderNames()
638 return _fields.getFieldNames();
641 /* ------------------------------------------------------------ */
643 * @see javax.servlet.http.HttpServletRequest#getHeaders(java.lang.String)
646 public Enumeration<String> getHeaders(String name)
648 Enumeration<String> e = _fields.getValues(name);
650 return Collections.enumeration(Collections.<String>emptyList());
654 /* ------------------------------------------------------------ */
656 * @return Returns the inputState.
658 public int getInputState()
663 /* ------------------------------------------------------------ */
665 * @see javax.servlet.ServletRequest#getInputStream()
668 public ServletInputStream getInputStream() throws IOException
670 if (_inputState != __NONE && _inputState != _STREAM)
671 throw new IllegalStateException("READER");
672 _inputState = _STREAM;
674 if (_channel.isExpecting100Continue())
675 _channel.continue100(_input.available());
680 /* ------------------------------------------------------------ */
682 * @see javax.servlet.http.HttpServletRequest#getIntHeader(java.lang.String)
685 public int getIntHeader(String name)
687 return (int)_fields.getLongField(name);
691 /* ------------------------------------------------------------ */
693 * @see javax.servlet.ServletRequest#getLocale()
696 public Locale getLocale()
698 Enumeration<String> enm = _fields.getValues(HttpHeader.ACCEPT_LANGUAGE.toString(),HttpFields.__separators);
701 if (enm == null || !enm.hasMoreElements())
702 return Locale.getDefault();
704 // sort the list in quality order
705 List<?> acceptLanguage = HttpFields.qualityList(enm);
706 if (acceptLanguage.size() == 0)
707 return Locale.getDefault();
709 int size = acceptLanguage.size();
713 String language = (String)acceptLanguage.get(0);
714 language = HttpFields.valueParameters(language,null);
716 int dash = language.indexOf('-');
719 country = language.substring(dash + 1).trim();
720 language = language.substring(0,dash).trim();
722 return new Locale(language,country);
725 return Locale.getDefault();
728 /* ------------------------------------------------------------ */
730 * @see javax.servlet.ServletRequest#getLocales()
733 public Enumeration<Locale> getLocales()
736 Enumeration<String> enm = _fields.getValues(HttpHeader.ACCEPT_LANGUAGE.toString(),HttpFields.__separators);
739 if (enm == null || !enm.hasMoreElements())
740 return Collections.enumeration(__defaultLocale);
742 // sort the list in quality order
743 List<String> acceptLanguage = HttpFields.qualityList(enm);
745 if (acceptLanguage.size() == 0)
746 return Collections.enumeration(__defaultLocale);
748 List<Locale> langs = new ArrayList<>();
751 for (String language : acceptLanguage)
753 language = HttpFields.valueParameters(language, null);
755 int dash = language.indexOf('-');
758 country = language.substring(dash + 1).trim();
759 language = language.substring(0, dash).trim();
761 langs.add(new Locale(language, country));
764 if (langs.size() == 0)
765 return Collections.enumeration(__defaultLocale);
767 return Collections.enumeration(langs);
770 /* ------------------------------------------------------------ */
772 * @see javax.servlet.ServletRequest#getLocalAddr()
775 public String getLocalAddr()
777 InetSocketAddress local=_channel.getLocalAddress();
780 InetAddress address = local.getAddress();
782 return local.getHostString();
783 return address.getHostAddress();
786 /* ------------------------------------------------------------ */
788 * @see javax.servlet.ServletRequest#getLocalName()
791 public String getLocalName()
793 InetSocketAddress local=_channel.getLocalAddress();
794 return local.getHostString();
797 /* ------------------------------------------------------------ */
799 * @see javax.servlet.ServletRequest#getLocalPort()
802 public int getLocalPort()
804 InetSocketAddress local=_channel.getLocalAddress();
805 return local.getPort();
808 /* ------------------------------------------------------------ */
810 * @see javax.servlet.http.HttpServletRequest#getMethod()
813 public String getMethod()
815 return _httpMethodString;
818 /* ------------------------------------------------------------ */
820 * @see javax.servlet.ServletRequest#getParameter(java.lang.String)
823 public String getParameter(String name)
825 if (!_paramsExtracted)
827 if (_parameters == null)
828 _parameters = restoreParameters();
829 return _parameters.getValue(name,0);
832 /* ------------------------------------------------------------ */
834 * @see javax.servlet.ServletRequest#getParameterMap()
837 public Map<String, String[]> getParameterMap()
839 if (!_paramsExtracted)
841 if (_parameters == null)
842 _parameters = restoreParameters();
843 return Collections.unmodifiableMap(_parameters.toStringArrayMap());
846 /* ------------------------------------------------------------ */
848 * @see javax.servlet.ServletRequest#getParameterNames()
851 public Enumeration<String> getParameterNames()
853 if (!_paramsExtracted)
855 if (_parameters == null)
856 _parameters = restoreParameters();
857 return Collections.enumeration(_parameters.keySet());
860 /* ------------------------------------------------------------ */
862 * @see javax.servlet.ServletRequest#getParameterValues(java.lang.String)
865 public String[] getParameterValues(String name)
867 if (!_paramsExtracted)
869 if (_parameters == null)
870 _parameters = restoreParameters();
871 List<String> vals = _parameters.getValues(name);
874 return vals.toArray(new String[vals.size()]);
877 private MultiMap<String> restoreParameters()
879 MultiMap<String> result = new MultiMap<>();
880 if (_queryParameters == null)
881 _queryParameters = extractQueryParameters();
882 result.addAllValues(_queryParameters);
883 result.addAllValues(_contentParameters);
887 public MultiMap<String> getQueryParameters()
889 return _queryParameters;
892 public void setQueryParameters(MultiMap<String> queryParameters)
894 _queryParameters = queryParameters;
897 public void setContentParameters(MultiMap<String> contentParameters)
899 _contentParameters = contentParameters;
902 public void resetParameters()
907 /* ------------------------------------------------------------ */
909 * @see javax.servlet.http.HttpServletRequest#getPathInfo()
912 public String getPathInfo()
917 /* ------------------------------------------------------------ */
919 * @see javax.servlet.http.HttpServletRequest#getPathTranslated()
922 public String getPathTranslated()
924 if (_pathInfo == null || _context == null)
926 return _context.getRealPath(_pathInfo);
929 /* ------------------------------------------------------------ */
931 * @see javax.servlet.ServletRequest#getProtocol()
934 public String getProtocol()
936 return _httpVersion.toString();
939 /* ------------------------------------------------------------ */
941 * @see javax.servlet.ServletRequest#getProtocol()
943 public HttpVersion getHttpVersion()
948 /* ------------------------------------------------------------ */
949 public String getQueryEncoding()
951 return _queryEncoding;
954 /* ------------------------------------------------------------ */
956 * @see javax.servlet.http.HttpServletRequest#getQueryString()
959 public String getQueryString()
961 if (_queryString == null && _uri != null)
963 if (_queryEncoding == null)
964 _queryString = _uri.getQuery();
966 _queryString = _uri.getQuery(_queryEncoding);
971 /* ------------------------------------------------------------ */
973 * @see javax.servlet.ServletRequest#getReader()
976 public BufferedReader getReader() throws IOException
978 if (_inputState != __NONE && _inputState != __READER)
979 throw new IllegalStateException("STREAMED");
981 if (_inputState == __READER)
984 String encoding = getCharacterEncoding();
985 if (encoding == null)
986 encoding = StringUtil.__ISO_8859_1;
988 if (_reader == null || !encoding.equalsIgnoreCase(_readerEncoding))
990 final ServletInputStream in = getInputStream();
991 _readerEncoding = encoding;
992 _reader = new BufferedReader(new InputStreamReader(in,encoding))
995 public void close() throws IOException
1001 _inputState = __READER;
1005 /* ------------------------------------------------------------ */
1007 * @see javax.servlet.ServletRequest#getRealPath(java.lang.String)
1010 public String getRealPath(String path)
1012 if (_context == null)
1014 return _context.getRealPath(path);
1017 /* ------------------------------------------------------------ */
1019 * Access the underlying Remote {@link InetSocketAddress} for this request.
1021 * @return the remote {@link InetSocketAddress} for this request, or null if the request has no remote (see {@link ServletRequest#getRemoteAddr()} for
1022 * conditions that result in no remote address)
1024 public InetSocketAddress getRemoteInetSocketAddress()
1026 InetSocketAddress remote = _remote;
1028 remote = _channel.getRemoteAddress();
1033 /* ------------------------------------------------------------ */
1035 * @see javax.servlet.ServletRequest#getRemoteAddr()
1038 public String getRemoteAddr()
1040 InetSocketAddress remote=_remote;
1042 remote=_channel.getRemoteAddress();
1047 InetAddress address = remote.getAddress();
1049 return remote.getHostString();
1051 return address.getHostAddress();
1054 /* ------------------------------------------------------------ */
1056 * @see javax.servlet.ServletRequest#getRemoteHost()
1059 public String getRemoteHost()
1061 InetSocketAddress remote=_remote;
1063 remote=_channel.getRemoteAddress();
1064 return remote==null?"":remote.getHostString();
1067 /* ------------------------------------------------------------ */
1069 * @see javax.servlet.ServletRequest#getRemotePort()
1072 public int getRemotePort()
1074 InetSocketAddress remote=_remote;
1076 remote=_channel.getRemoteAddress();
1077 return remote==null?0:remote.getPort();
1080 /* ------------------------------------------------------------ */
1082 * @see javax.servlet.http.HttpServletRequest#getRemoteUser()
1085 public String getRemoteUser()
1087 Principal p = getUserPrincipal();
1093 /* ------------------------------------------------------------ */
1095 * @see javax.servlet.ServletRequest#getRequestDispatcher(java.lang.String)
1098 public RequestDispatcher getRequestDispatcher(String path)
1100 if (path == null || _context == null)
1103 // handle relative path
1104 if (!path.startsWith("/"))
1106 String relTo = URIUtil.addPaths(_servletPath,_pathInfo);
1107 int slash = relTo.lastIndexOf("/");
1109 relTo = relTo.substring(0,slash + 1);
1112 path = URIUtil.addPaths(relTo,path);
1115 return _context.getRequestDispatcher(path);
1118 /* ------------------------------------------------------------ */
1120 * @see javax.servlet.http.HttpServletRequest#getRequestedSessionId()
1123 public String getRequestedSessionId()
1125 return _requestedSessionId;
1128 /* ------------------------------------------------------------ */
1130 * @see javax.servlet.http.HttpServletRequest#getRequestURI()
1133 public String getRequestURI()
1135 if (_requestURI == null && _uri != null)
1136 _requestURI = _uri.getPathAndParam();
1140 /* ------------------------------------------------------------ */
1142 * @see javax.servlet.http.HttpServletRequest#getRequestURL()
1145 public StringBuffer getRequestURL()
1147 final StringBuffer url = new StringBuffer(128);
1148 URIUtil.appendSchemeHostPort(url,getScheme(),getServerName(),getServerPort());
1149 url.append(getRequestURI());
1153 /* ------------------------------------------------------------ */
1154 public Response getResponse()
1156 return _channel.getResponse();
1159 /* ------------------------------------------------------------ */
1161 * Reconstructs the URL the client used to make the request. The returned URL contains a protocol, server name, port number, and, but it does not include a
1164 * Because this method returns a <code>StringBuffer</code>, not a string, you can modify the URL easily, for example, to append path and query parameters.
1166 * This method is useful for creating redirect messages and for reporting errors.
1168 * @return "scheme://host:port"
1170 public StringBuilder getRootURL()
1172 StringBuilder url = new StringBuilder(128);
1173 URIUtil.appendSchemeHostPort(url,getScheme(),getServerName(),getServerPort());
1177 /* ------------------------------------------------------------ */
1179 * @see javax.servlet.ServletRequest#getScheme()
1182 public String getScheme()
1187 /* ------------------------------------------------------------ */
1189 * @see javax.servlet.ServletRequest#getServerName()
1192 public String getServerName()
1194 // Return already determined host
1195 if (_serverName != null)
1199 throw new IllegalStateException("No uri");
1201 // Return host from absolute URI
1202 _serverName = _uri.getHost();
1203 if (_serverName != null)
1205 _port = _uri.getPort();
1209 // Return host from header field
1210 String hostPort = _fields.getStringField(HttpHeader.HOST);
1213 if (hostPort != null)
1215 int len=hostPort.length();
1216 loop: for (int i = len; i-- > 0;)
1218 char c2 = (char)(0xff & hostPort.charAt(i));
1228 _port = StringUtil.toInt(hostPort.substring(i+1));
1230 catch (NumberFormatException e)
1233 _serverName=hostPort;
1240 if (hostPort.charAt(0)=='[')
1242 if (hostPort.charAt(len-1)!=']')
1244 LOG.warn("Bad IPv6 "+hostPort);
1245 _serverName=hostPort;
1249 _serverName = hostPort.substring(0,len);
1251 else if (len==hostPort.length())
1252 _serverName=hostPort;
1254 _serverName = hostPort.substring(0,len);
1259 // Return host from connection
1260 if (_channel != null)
1262 _serverName = getLocalName();
1263 _port = getLocalPort();
1264 if (_serverName != null && !StringUtil.ALL_INTERFACES.equals(_serverName))
1268 // Return the local host
1271 _serverName = InetAddress.getLocalHost().getHostAddress();
1273 catch (java.net.UnknownHostException e)
1280 /* ------------------------------------------------------------ */
1282 * @see javax.servlet.ServletRequest#getServerPort()
1285 public int getServerPort()
1289 if (_serverName == null)
1294 if (_serverName != null && _uri != null)
1295 _port = _uri.getPort();
1298 InetSocketAddress local = _channel.getLocalAddress();
1299 _port = local == null?0:local.getPort();
1306 if (getScheme().equalsIgnoreCase(URIUtil.HTTPS))
1313 /* ------------------------------------------------------------ */
1315 public ServletContext getServletContext()
1320 /* ------------------------------------------------------------ */
1323 public String getServletName()
1326 return _scope.getName();
1330 /* ------------------------------------------------------------ */
1332 * @see javax.servlet.http.HttpServletRequest#getServletPath()
1335 public String getServletPath()
1337 if (_servletPath == null)
1339 return _servletPath;
1342 /* ------------------------------------------------------------ */
1343 public ServletResponse getServletResponse()
1345 return _channel.getResponse();
1348 /* ------------------------------------------------------------ */
1350 * Add @override when 3.1 api is available
1352 public String changeSessionId()
1354 HttpSession session = getSession(false);
1355 if (session == null)
1356 throw new IllegalStateException("No session");
1358 if (session instanceof AbstractSession)
1360 AbstractSession abstractSession = ((AbstractSession)session);
1361 abstractSession.renewId(this);
1362 if (getRemoteUser() != null)
1363 abstractSession.setAttribute(AbstractSession.SESSION_KNOWN_ONLY_TO_AUTHENTICATED, Boolean.TRUE);
1364 if (abstractSession.isIdChanged())
1365 _channel.getResponse().addCookie(_sessionManager.getSessionCookie(abstractSession, getContextPath(), isSecure()));
1368 return session.getId();
1371 /* ------------------------------------------------------------ */
1373 * @see javax.servlet.http.HttpServletRequest#getSession()
1376 public HttpSession getSession()
1378 return getSession(true);
1381 /* ------------------------------------------------------------ */
1383 * @see javax.servlet.http.HttpServletRequest#getSession(boolean)
1386 public HttpSession getSession(boolean create)
1388 if (_session != null)
1390 if (_sessionManager != null && !_sessionManager.isValid(_session))
1399 if (getResponse().isCommitted())
1400 throw new IllegalStateException("Response is committed");
1402 if (_sessionManager == null)
1403 throw new IllegalStateException("No SessionManager");
1405 _session = _sessionManager.newHttpSession(this);
1406 HttpCookie cookie = _sessionManager.getSessionCookie(_session,getContextPath(),isSecure());
1408 _channel.getResponse().addCookie(cookie);
1413 /* ------------------------------------------------------------ */
1415 * @return Returns the sessionManager.
1417 public SessionManager getSessionManager()
1419 return _sessionManager;
1422 /* ------------------------------------------------------------ */
1424 * Get Request TimeStamp
1426 * @return The time that the request was received.
1428 public long getTimeStamp()
1433 /* ------------------------------------------------------------ */
1435 * @return Returns the uri.
1437 public HttpURI getUri()
1442 /* ------------------------------------------------------------ */
1443 public UserIdentity getUserIdentity()
1445 if (_authentication instanceof Authentication.Deferred)
1446 setAuthentication(((Authentication.Deferred)_authentication).authenticate(this));
1448 if (_authentication instanceof Authentication.User)
1449 return ((Authentication.User)_authentication).getUserIdentity();
1453 /* ------------------------------------------------------------ */
1455 * @return The resolved user Identity, which may be null if the {@link Authentication} is not {@link Authentication.User} (eg.
1456 * {@link Authentication.Deferred}).
1458 public UserIdentity getResolvedUserIdentity()
1460 if (_authentication instanceof Authentication.User)
1461 return ((Authentication.User)_authentication).getUserIdentity();
1465 /* ------------------------------------------------------------ */
1466 public UserIdentity.Scope getUserIdentityScope()
1471 /* ------------------------------------------------------------ */
1473 * @see javax.servlet.http.HttpServletRequest#getUserPrincipal()
1476 public Principal getUserPrincipal()
1478 if (_authentication instanceof Authentication.Deferred)
1479 setAuthentication(((Authentication.Deferred)_authentication).authenticate(this));
1481 if (_authentication instanceof Authentication.User)
1483 UserIdentity user = ((Authentication.User)_authentication).getUserIdentity();
1484 return user.getUserPrincipal();
1491 /* ------------------------------------------------------------ */
1492 public boolean isHandled()
1498 public boolean isAsyncStarted()
1500 return getHttpChannelState().isAsyncStarted();
1504 /* ------------------------------------------------------------ */
1506 public boolean isAsyncSupported()
1508 return _asyncSupported;
1511 /* ------------------------------------------------------------ */
1513 * @see javax.servlet.http.HttpServletRequest#isRequestedSessionIdFromCookie()
1516 public boolean isRequestedSessionIdFromCookie()
1518 return _requestedSessionId != null && _requestedSessionIdFromCookie;
1521 /* ------------------------------------------------------------ */
1523 * @see javax.servlet.http.HttpServletRequest#isRequestedSessionIdFromUrl()
1526 public boolean isRequestedSessionIdFromUrl()
1528 return _requestedSessionId != null && !_requestedSessionIdFromCookie;
1531 /* ------------------------------------------------------------ */
1533 * @see javax.servlet.http.HttpServletRequest#isRequestedSessionIdFromURL()
1536 public boolean isRequestedSessionIdFromURL()
1538 return _requestedSessionId != null && !_requestedSessionIdFromCookie;
1541 /* ------------------------------------------------------------ */
1543 * @see javax.servlet.http.HttpServletRequest#isRequestedSessionIdValid()
1546 public boolean isRequestedSessionIdValid()
1548 if (_requestedSessionId == null)
1551 HttpSession session = getSession(false);
1552 return (session != null && _sessionManager.getSessionIdManager().getClusterId(_requestedSessionId).equals(_sessionManager.getClusterId(session)));
1555 /* ------------------------------------------------------------ */
1557 * @see javax.servlet.ServletRequest#isSecure()
1560 public boolean isSecure()
1565 /* ------------------------------------------------------------ */
1566 public void setSecure(boolean secure)
1571 /* ------------------------------------------------------------ */
1573 * @see javax.servlet.http.HttpServletRequest#isUserInRole(java.lang.String)
1576 public boolean isUserInRole(String role)
1578 if (_authentication instanceof Authentication.Deferred)
1579 setAuthentication(((Authentication.Deferred)_authentication).authenticate(this));
1581 if (_authentication instanceof Authentication.User)
1582 return ((Authentication.User)_authentication).isUserInRole(_scope,role);
1586 /* ------------------------------------------------------------ */
1587 public HttpSession recoverNewSession(Object key)
1589 if (_savedNewSessions == null)
1591 return _savedNewSessions.get(key);
1594 /* ------------------------------------------------------------ */
1595 protected void recycle()
1597 if (_context != null)
1598 throw new IllegalStateException("Request in context!");
1600 if (_inputState == __READER)
1604 int r = _reader.read();
1615 _dispatcherType=null;
1616 setAuthentication(Authentication.NOT_CHECKED);
1617 getHttpChannelState().recycle();
1621 _asyncSupported = true;
1623 if (_attributes != null)
1624 _attributes.clearAttributes();
1625 _characterEncoding = null;
1626 _contextPath = null;
1627 if (_cookies != null)
1629 _cookiesExtracted = false;
1634 _httpMethodString = null;
1637 _httpVersion = HttpVersion.HTTP_1_1;
1638 _queryEncoding = null;
1639 _queryString = null;
1640 _requestedSessionId = null;
1641 _requestedSessionIdFromCookie = false;
1644 _sessionManager = null;
1647 _scheme = URIUtil.HTTP;
1648 _servletPath = null;
1651 _queryParameters = null;
1652 _contentParameters = null;
1654 _paramsExtracted = false;
1655 _inputState = __NONE;
1657 if (_savedNewSessions != null)
1658 _savedNewSessions.clear();
1659 _savedNewSessions=null;
1660 _multiPartInputStream = null;
1666 /* ------------------------------------------------------------ */
1668 * @see javax.servlet.ServletRequest#removeAttribute(java.lang.String)
1671 public void removeAttribute(String name)
1673 Object old_value = _attributes == null?null:_attributes.getAttribute(name);
1675 if (_attributes != null)
1676 _attributes.removeAttribute(name);
1678 if (old_value != null && !_requestAttributeListeners.isEmpty())
1680 final ServletRequestAttributeEvent event = new ServletRequestAttributeEvent(_context,this,name,old_value);
1681 for (ServletRequestAttributeListener listener : _requestAttributeListeners)
1682 listener.attributeRemoved(event);
1686 /* ------------------------------------------------------------ */
1687 public void removeEventListener(final EventListener listener)
1689 _requestAttributeListeners.remove(listener);
1692 /* ------------------------------------------------------------ */
1693 public void saveNewSession(Object key, HttpSession session)
1695 if (_savedNewSessions == null)
1696 _savedNewSessions = new HashMap<>();
1697 _savedNewSessions.put(key,session);
1700 /* ------------------------------------------------------------ */
1701 public void setAsyncSupported(boolean supported)
1703 _asyncSupported = supported;
1706 /* ------------------------------------------------------------ */
1708 * Set a request attribute. if the attribute name is "org.eclipse.jetty.server.server.Request.queryEncoding" then the value is also passed in a call to
1709 * {@link #setQueryEncoding}.
1711 * @see javax.servlet.ServletRequest#setAttribute(java.lang.String, java.lang.Object)
1714 public void setAttribute(String name, Object value)
1716 Object old_value = _attributes == null?null:_attributes.getAttribute(name);
1718 if ("org.eclipse.jetty.server.Request.queryEncoding".equals(name))
1719 setQueryEncoding(value == null?null:value.toString());
1720 else if ("org.eclipse.jetty.server.sendContent".equals(name))
1721 LOG.warn("Deprecated: org.eclipse.jetty.server.sendContent");
1723 if (_attributes == null)
1724 _attributes = new AttributesMap();
1725 _attributes.setAttribute(name,value);
1727 if (!_requestAttributeListeners.isEmpty())
1729 final ServletRequestAttributeEvent event = new ServletRequestAttributeEvent(_context,this,name,old_value == null?value:old_value);
1730 for (ServletRequestAttributeListener l : _requestAttributeListeners)
1732 if (old_value == null)
1733 l.attributeAdded(event);
1734 else if (value == null)
1735 l.attributeRemoved(event);
1737 l.attributeReplaced(event);
1742 /* ------------------------------------------------------------ */
1745 public void setAttributes(Attributes attributes)
1747 _attributes = attributes;
1750 /* ------------------------------------------------------------ */
1752 /* ------------------------------------------------------------ */
1754 * Set the authentication.
1756 * @param authentication
1757 * the authentication to set
1759 public void setAuthentication(Authentication authentication)
1761 _authentication = authentication;
1764 /* ------------------------------------------------------------ */
1766 * @see javax.servlet.ServletRequest#setCharacterEncoding(java.lang.String)
1769 public void setCharacterEncoding(String encoding) throws UnsupportedEncodingException
1771 if (_inputState != __NONE)
1774 _characterEncoding = encoding;
1776 // check encoding is supported
1777 if (!StringUtil.isUTF8(encoding))
1781 Charset.forName(encoding);
1783 catch (UnsupportedCharsetException e)
1785 throw new UnsupportedEncodingException(e.getMessage());
1790 /* ------------------------------------------------------------ */
1792 * @see javax.servlet.ServletRequest#setCharacterEncoding(java.lang.String)
1794 public void setCharacterEncodingUnchecked(String encoding)
1796 _characterEncoding = encoding;
1799 /* ------------------------------------------------------------ */
1801 * @see javax.servlet.ServletRequest#getContentType()
1803 public void setContentType(String contentType)
1805 _fields.put(HttpHeader.CONTENT_TYPE,contentType);
1809 /* ------------------------------------------------------------ */
1811 * Set request context
1816 public void setContext(Context context)
1818 _newContext = _context != context;
1822 /* ------------------------------------------------------------ */
1824 * @return True if this is the first call of {@link #takeNewContext()} since the last
1825 * {@link #setContext(org.eclipse.jetty.server.handler.ContextHandler.Context)} call.
1827 public boolean takeNewContext()
1829 boolean nc = _newContext;
1830 _newContext = false;
1834 /* ------------------------------------------------------------ */
1836 * Sets the "context path" for this request
1838 * @see HttpServletRequest#getContextPath()
1840 public void setContextPath(String contextPath)
1842 _contextPath = contextPath;
1845 /* ------------------------------------------------------------ */
1848 * The cookies to set.
1850 public void setCookies(Cookie[] cookies)
1852 if (_cookies == null)
1853 _cookies = new CookieCutter();
1854 _cookies.setCookies(cookies);
1857 /* ------------------------------------------------------------ */
1858 public void setDispatcherType(DispatcherType type)
1860 _dispatcherType = type;
1863 /* ------------------------------------------------------------ */
1864 public void setHandled(boolean h)
1869 /* ------------------------------------------------------------ */
1872 * The method to set.
1874 public void setMethod(HttpMethod httpMethod, String method)
1876 _httpMethod=httpMethod;
1877 _httpMethodString = method;
1880 /* ------------------------------------------------------------ */
1881 public boolean isHead()
1883 return HttpMethod.HEAD==_httpMethod;
1886 /* ------------------------------------------------------------ */
1889 * The pathInfo to set.
1891 public void setPathInfo(String pathInfo)
1893 _pathInfo = pathInfo;
1896 /* ------------------------------------------------------------ */
1899 * The protocol to set.
1901 public void setHttpVersion(HttpVersion version)
1903 _httpVersion = version;
1906 /* ------------------------------------------------------------ */
1908 * Set the character encoding used for the query string. This call will effect the return of getQueryString and getParamaters. It must be called before any
1909 * getParameter methods.
1911 * The request attribute "org.eclipse.jetty.server.server.Request.queryEncoding" may be set as an alternate method of calling setQueryEncoding.
1913 * @param queryEncoding
1915 public void setQueryEncoding(String queryEncoding)
1917 _queryEncoding = queryEncoding;
1918 _queryString = null;
1921 /* ------------------------------------------------------------ */
1923 * @param queryString
1924 * The queryString to set.
1926 public void setQueryString(String queryString)
1928 _queryString = queryString;
1929 _queryEncoding = null; //assume utf-8
1932 /* ------------------------------------------------------------ */
1935 * The address to set.
1937 public void setRemoteAddr(InetSocketAddress addr)
1942 /* ------------------------------------------------------------ */
1944 * @param requestedSessionId
1945 * The requestedSessionId to set.
1947 public void setRequestedSessionId(String requestedSessionId)
1949 _requestedSessionId = requestedSessionId;
1952 /* ------------------------------------------------------------ */
1954 * @param requestedSessionIdCookie
1955 * The requestedSessionIdCookie to set.
1957 public void setRequestedSessionIdFromCookie(boolean requestedSessionIdCookie)
1959 _requestedSessionIdFromCookie = requestedSessionIdCookie;
1962 /* ------------------------------------------------------------ */
1965 * The requestURI to set.
1967 public void setRequestURI(String requestURI)
1969 _requestURI = requestURI;
1972 /* ------------------------------------------------------------ */
1975 * The scheme to set.
1977 public void setScheme(String scheme)
1982 /* ------------------------------------------------------------ */
1987 public void setServerName(String host)
1992 /* ------------------------------------------------------------ */
1997 public void setServerPort(int port)
2002 /* ------------------------------------------------------------ */
2004 * @param servletPath
2005 * The servletPath to set.
2007 public void setServletPath(String servletPath)
2009 _servletPath = servletPath;
2012 /* ------------------------------------------------------------ */
2015 * The session to set.
2017 public void setSession(HttpSession session)
2022 /* ------------------------------------------------------------ */
2024 * @param sessionManager
2025 * The sessionManager to set.
2027 public void setSessionManager(SessionManager sessionManager)
2029 _sessionManager = sessionManager;
2032 /* ------------------------------------------------------------ */
2033 public void setTimeStamp(long ts)
2038 /* ------------------------------------------------------------ */
2043 public void setUri(HttpURI uri)
2048 /* ------------------------------------------------------------ */
2049 public void setUserIdentityScope(UserIdentity.Scope scope)
2054 /* ------------------------------------------------------------ */
2056 public AsyncContext startAsync() throws IllegalStateException
2058 if (!_asyncSupported)
2059 throw new IllegalStateException("!asyncSupported");
2060 HttpChannelState state = getHttpChannelState();
2062 _async=new AsyncContextState(state);
2063 AsyncContextEvent event = new AsyncContextEvent(_context,_async,state,this,this,getResponse());
2064 state.startAsync(event);
2068 /* ------------------------------------------------------------ */
2070 public AsyncContext startAsync(ServletRequest servletRequest, ServletResponse servletResponse) throws IllegalStateException
2072 if (!_asyncSupported)
2073 throw new IllegalStateException("!asyncSupported");
2074 HttpChannelState state = getHttpChannelState();
2076 _async=new AsyncContextState(state);
2077 AsyncContextEvent event = new AsyncContextEvent(_context,_async,state,this,servletRequest,servletResponse);
2078 event.setDispatchContext(getServletContext());
2079 event.setDispatchPath(URIUtil.addPaths(getServletPath(),getPathInfo()));
2080 state.startAsync(event);
2084 /* ------------------------------------------------------------ */
2086 public String toString()
2088 return String.format("%s%s%s %s%s@%x",
2089 getClass().getSimpleName(),
2090 _handled ? "[" : "(",
2093 _handled ? "]" : ")",
2097 /* ------------------------------------------------------------ */
2099 public boolean authenticate(HttpServletResponse response) throws IOException, ServletException
2101 if (_authentication instanceof Authentication.Deferred)
2103 setAuthentication(((Authentication.Deferred)_authentication).authenticate(this,response));
2104 return !(_authentication instanceof Authentication.ResponseSent);
2106 response.sendError(HttpStatus.UNAUTHORIZED_401);
2110 /* ------------------------------------------------------------ */
2112 public Part getPart(String name) throws IOException, ServletException
2116 return _multiPartInputStream.getPart(name);
2119 /* ------------------------------------------------------------ */
2121 public Collection<Part> getParts() throws IOException, ServletException
2123 if (getContentType() == null || !getContentType().startsWith("multipart/form-data"))
2124 throw new ServletException("Content-Type != multipart/form-data");
2125 return getParts(null);
2128 private Collection<Part> getParts(MultiMap<String> params) throws IOException, ServletException
2130 if (_multiPartInputStream == null)
2131 _multiPartInputStream = (MultiPartInputStreamParser)getAttribute(__MULTIPART_INPUT_STREAM);
2133 if (_multiPartInputStream == null)
2135 MultipartConfigElement config = (MultipartConfigElement)getAttribute(__MULTIPART_CONFIG_ELEMENT);
2138 throw new IllegalStateException("No multipart config for servlet");
2140 _multiPartInputStream = new MultiPartInputStreamParser(getInputStream(),
2141 getContentType(), config,
2142 (_context != null?(File)_context.getAttribute("javax.servlet.context.tempdir"):null));
2144 setAttribute(__MULTIPART_INPUT_STREAM, _multiPartInputStream);
2145 setAttribute(__MULTIPART_CONTEXT, _context);
2146 Collection<Part> parts = _multiPartInputStream.getParts(); //causes parsing
2147 ByteArrayOutputStream os = null;
2150 MultiPartInputStreamParser.MultiPart mp = (MultiPartInputStreamParser.MultiPart)p;
2151 if (mp.getContentDispositionFilename() == null)
2153 // Servlet Spec 3.0 pg 23, parts without filename must be put into params.
2154 String charset = null;
2155 if (mp.getContentType() != null)
2156 charset = MimeTypes.getCharsetFromContentType(mp.getContentType());
2158 try (InputStream is = mp.getInputStream())
2161 os = new ByteArrayOutputStream();
2163 String content=new String(os.toByteArray(),charset==null?StandardCharsets.UTF_8:Charset.forName(charset));
2164 if (_contentParameters == null)
2165 _contentParameters = params == null ? new MultiMap<String>() : params;
2166 _contentParameters.add(mp.getName(), content);
2173 return _multiPartInputStream.getParts();
2176 /* ------------------------------------------------------------ */
2178 public void login(String username, String password) throws ServletException
2180 if (_authentication instanceof Authentication.Deferred)
2182 _authentication=((Authentication.Deferred)_authentication).login(username,password,this);
2183 if (_authentication == null)
2184 throw new Authentication.Failed("Authentication failed for username '"+username+"'");
2188 throw new Authentication.Failed("Authenticated failed for username '"+username+"'. Already authenticated as "+_authentication);
2192 /* ------------------------------------------------------------ */
2194 public void logout() throws ServletException
2196 if (_authentication instanceof Authentication.User)
2197 ((Authentication.User)_authentication).logout();
2198 _authentication=Authentication.UNAUTHENTICATED;
2201 public void mergeQueryParameters(String newQuery, boolean updateQueryString)
2203 MultiMap<String> newQueryParams = new MultiMap<>();
2204 // Have to assume ENCODING because we can't know otherwise.
2205 UrlEncoded.decodeTo(newQuery, newQueryParams, UrlEncoded.ENCODING, -1);
2207 MultiMap<String> oldQueryParams = _queryParameters;
2208 if (oldQueryParams == null && _queryString != null)
2210 oldQueryParams = new MultiMap<>();
2211 UrlEncoded.decodeTo(_queryString, oldQueryParams, getQueryEncoding(), -1);
2214 MultiMap<String> mergedQueryParams = newQueryParams;
2215 if (oldQueryParams != null)
2217 // Parameters values are accumulated.
2218 mergedQueryParams = new MultiMap<>(newQueryParams);
2219 mergedQueryParams.addAllValues(oldQueryParams);
2222 setQueryParameters(mergedQueryParams);
2225 if (updateQueryString)
2227 // Build the new merged query string, parameters in the
2228 // new query string hide parameters in the old query string.
2229 StringBuilder mergedQuery = new StringBuilder(newQuery);
2230 for (Map.Entry<String, List<String>> entry : mergedQueryParams.entrySet())
2232 if (newQueryParams.containsKey(entry.getKey()))
2234 for (String value : entry.getValue())
2235 mergedQuery.append("&").append(entry.getKey()).append("=").append(value);
2238 setQueryString(mergedQuery.toString());
2243 * @see javax.servlet.http.HttpServletRequest#upgrade(java.lang.Class)
2246 public <T extends HttpUpgradeHandler> T upgrade(Class<T> handlerClass) throws IOException, ServletException
2248 if (getContext() == null)
2249 throw new ServletException ("Unable to instantiate "+handlerClass);
2253 //Instantiate an instance and inject it
2254 T h = getContext().createInstance(handlerClass);
2256 //TODO handle the rest of the upgrade process
2262 if (e instanceof ServletException)
2263 throw (ServletException)e;
2264 throw new ServletException(e);