2 // ========================================================================
3 // Copyright (c) 1995-2014 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;
43 import javax.servlet.AsyncContext;
44 import javax.servlet.AsyncListener;
45 import javax.servlet.DispatcherType;
46 import javax.servlet.MultipartConfigElement;
47 import javax.servlet.RequestDispatcher;
48 import javax.servlet.ServletContext;
49 import javax.servlet.ServletException;
50 import javax.servlet.ServletInputStream;
51 import javax.servlet.ServletRequest;
52 import javax.servlet.ServletRequestAttributeEvent;
53 import javax.servlet.ServletRequestAttributeListener;
54 import javax.servlet.ServletRequestEvent;
55 import javax.servlet.ServletRequestListener;
56 import javax.servlet.ServletResponse;
57 import javax.servlet.http.Cookie;
58 import javax.servlet.http.HttpServletRequest;
59 import javax.servlet.http.HttpServletResponse;
60 import javax.servlet.http.HttpSession;
61 import javax.servlet.http.HttpUpgradeHandler;
62 import javax.servlet.http.Part;
64 import org.eclipse.jetty.http.HttpCookie;
65 import org.eclipse.jetty.http.HttpFields;
66 import org.eclipse.jetty.http.HttpHeader;
67 import org.eclipse.jetty.http.HttpMethod;
68 import org.eclipse.jetty.http.HttpStatus;
69 import org.eclipse.jetty.http.HttpURI;
70 import org.eclipse.jetty.http.HttpVersion;
71 import org.eclipse.jetty.http.MimeTypes;
72 import org.eclipse.jetty.server.handler.ContextHandler;
73 import org.eclipse.jetty.server.handler.ContextHandler.Context;
74 import org.eclipse.jetty.server.session.AbstractSession;
75 import org.eclipse.jetty.util.Attributes;
76 import org.eclipse.jetty.util.AttributesMap;
77 import org.eclipse.jetty.util.IO;
78 import org.eclipse.jetty.util.MultiException;
79 import org.eclipse.jetty.util.MultiMap;
80 import org.eclipse.jetty.util.MultiPartInputStreamParser;
81 import org.eclipse.jetty.util.StringUtil;
82 import org.eclipse.jetty.util.URIUtil;
83 import org.eclipse.jetty.util.UrlEncoded;
84 import org.eclipse.jetty.util.log.Log;
85 import org.eclipse.jetty.util.log.Logger;
87 /* ------------------------------------------------------------ */
91 * Implements {@link javax.servlet.http.HttpServletRequest} from the <code>javax.servlet.http</code> package.
94 * 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
95 * request object to be as lightweight as possible and not actually implement any significant behavior. For example
98 * <li>The {@link Request#getContextPath()} method will return null, until the request has been passed to a {@link ContextHandler} which matches the
99 * {@link Request#getPathInfo()} with a context path and calls {@link Request#setContextPath(String)} as a result.</li>
101 * <li>the HTTP session methods will all return null sessions until such time as a request has been passed to a
102 * {@link org.eclipse.jetty.server.session.SessionHandler} which checks for session cookies and enables the ability to create new sessions.</li>
104 * <li>The {@link Request#getServletPath()} method will return null until the request has been passed to a <code>org.eclipse.jetty.servlet.ServletHandler</code>
105 * and the pathInfo matched against the servlet URL patterns and {@link Request#setServletPath(String)} called as a result.</li>
108 * A request instance is created for each connection accepted by the server and recycled for each HTTP request received via that connection.
109 * An effort is made to avoid reparsing headers and cookies that are likely to be the same for requests from the same connection.
112 * The form content that a request can process is limited to protect from Denial of Service attacks. The size in bytes is limited by
113 * {@link ContextHandler#getMaxFormContentSize()} or if there is no context then the "org.eclipse.jetty.server.Request.maxFormContentSize" {@link Server}
114 * attribute. The number of parameters keys is limited by {@link ContextHandler#getMaxFormKeys()} or if there is no context then the
115 * "org.eclipse.jetty.server.Request.maxFormKeys" {@link Server} attribute.
119 public class Request implements HttpServletRequest
121 public static final String __MULTIPART_CONFIG_ELEMENT = "org.eclipse.jetty.multipartConfig";
122 public static final String __MULTIPART_INPUT_STREAM = "org.eclipse.jetty.multiPartInputStream";
123 public static final String __MULTIPART_CONTEXT = "org.eclipse.jetty.multiPartContext";
125 private static final Logger LOG = Log.getLogger(Request.class);
126 private static final Collection<Locale> __defaultLocale = Collections.singleton(Locale.getDefault());
127 private static final int __NONE = 0, _STREAM = 1, __READER = 2;
129 private final HttpChannel<?> _channel;
130 private final HttpFields _fields=new HttpFields();
131 private final List<ServletRequestAttributeListener> _requestAttributeListeners=new ArrayList<>();
132 private final HttpInput<?> _input;
134 public static class MultiPartCleanerListener implements ServletRequestListener
137 public void requestDestroyed(ServletRequestEvent sre)
139 //Clean up any tmp files created by MultiPartInputStream
140 MultiPartInputStreamParser mpis = (MultiPartInputStreamParser)sre.getServletRequest().getAttribute(__MULTIPART_INPUT_STREAM);
143 ContextHandler.Context context = (ContextHandler.Context)sre.getServletRequest().getAttribute(__MULTIPART_CONTEXT);
145 //Only do the cleanup if we are exiting from the context in which a servlet parsed the multipart files
146 if (context == sre.getServletContext())
152 catch (MultiException e)
154 sre.getServletContext().log("Errors deleting multipart tmp files", e);
161 public void requestInitialized(ServletRequestEvent sre)
163 //nothing to do, multipart config set up by ServletHolder.handle()
170 private boolean _secure;
171 private boolean _asyncSupported = true;
172 private boolean _newContext;
173 private boolean _cookiesExtracted = false;
174 private boolean _handled = false;
175 private boolean _paramsExtracted;
176 private boolean _requestedSessionIdFromCookie = false;
177 private volatile Attributes _attributes;
178 private Authentication _authentication;
179 private String _characterEncoding;
180 private ContextHandler.Context _context;
181 private String _contextPath;
182 private CookieCutter _cookies;
183 private DispatcherType _dispatcherType;
184 private int _inputState = __NONE;
185 private HttpMethod _httpMethod;
186 private String _httpMethodString;
187 private MultiMap<String> _queryParameters;
188 private MultiMap<String> _contentParameters;
189 private MultiMap<String> _parameters;
190 private String _pathInfo;
192 private HttpVersion _httpVersion = HttpVersion.HTTP_1_1;
193 private String _queryEncoding;
194 private String _queryString;
195 private BufferedReader _reader;
196 private String _readerEncoding;
197 private InetSocketAddress _remote;
198 private String _requestedSessionId;
199 private String _requestURI;
200 private Map<Object, HttpSession> _savedNewSessions;
201 private String _scheme = URIUtil.HTTP;
202 private UserIdentity.Scope _scope;
203 private String _serverName;
204 private String _servletPath;
205 private HttpSession _session;
206 private SessionManager _sessionManager;
207 private long _timeStamp;
208 private HttpURI _uri;
209 private MultiPartInputStreamParser _multiPartInputStream; //if the request is a multi-part mime
210 private AsyncContextState _async;
212 /* ------------------------------------------------------------ */
213 public Request(HttpChannel<?> channel, HttpInput<?> input)
219 /* ------------------------------------------------------------ */
220 public HttpFields getHttpFields()
225 /* ------------------------------------------------------------ */
226 public HttpInput<?> getHttpInput()
231 /* ------------------------------------------------------------ */
232 public void addEventListener(final EventListener listener)
234 if (listener instanceof ServletRequestAttributeListener)
235 _requestAttributeListeners.add((ServletRequestAttributeListener)listener);
236 if (listener instanceof AsyncListener)
237 throw new IllegalArgumentException(listener.getClass().toString());
240 public void extractParameters()
242 if (_paramsExtracted)
245 _paramsExtracted = true;
247 // Extract query string parameters; these may be replaced by a forward()
248 // and may have already been extracted by mergeQueryParameters().
249 if (_queryParameters == null)
250 _queryParameters = extractQueryParameters();
252 // Extract content parameters; these cannot be replaced by a forward()
253 // once extracted and may have already been extracted by getParts() or
254 // by a processing happening after a form-based authentication.
255 if (_contentParameters == null)
256 _contentParameters = extractContentParameters();
258 _parameters = restoreParameters();
261 private MultiMap<String> extractQueryParameters()
263 MultiMap<String> result = new MultiMap<>();
264 if (_uri != null && _uri.hasQuery())
266 if (_queryEncoding == null)
268 _uri.decodeQueryTo(result);
274 _uri.decodeQueryTo(result, _queryEncoding);
276 catch (UnsupportedEncodingException e)
278 if (LOG.isDebugEnabled())
281 LOG.warn(e.toString());
288 private MultiMap<String> extractContentParameters()
290 MultiMap<String> result = new MultiMap<>();
292 String contentType = getContentType();
293 if (contentType != null && !contentType.isEmpty())
295 contentType = HttpFields.valueParameters(contentType, null);
296 int contentLength = getContentLength();
297 if (contentLength != 0)
299 if (MimeTypes.Type.FORM_ENCODED.is(contentType) && _inputState == __NONE &&
300 (HttpMethod.POST.is(getMethod()) || HttpMethod.PUT.is(getMethod())))
302 extractFormParameters(result);
304 else if (contentType.startsWith("multipart/form-data") &&
305 getAttribute(__MULTIPART_CONFIG_ELEMENT) != null &&
306 _multiPartInputStream == null)
308 extractMultipartParameters(result);
316 public void extractFormParameters(MultiMap<String> params)
320 int maxFormContentSize = -1;
321 int maxFormKeys = -1;
323 if (_context != null)
325 maxFormContentSize = _context.getContextHandler().getMaxFormContentSize();
326 maxFormKeys = _context.getContextHandler().getMaxFormKeys();
329 if (maxFormContentSize < 0)
331 Object obj = _channel.getServer().getAttribute("org.eclipse.jetty.server.Request.maxFormContentSize");
333 maxFormContentSize = 200000;
334 else if (obj instanceof Number)
336 Number size = (Number)obj;
337 maxFormContentSize = size.intValue();
339 else if (obj instanceof String)
341 maxFormContentSize = Integer.valueOf((String)obj);
347 Object obj = _channel.getServer().getAttribute("org.eclipse.jetty.server.Request.maxFormKeys");
350 else if (obj instanceof Number)
352 Number keys = (Number)obj;
353 maxFormKeys = keys.intValue();
355 else if (obj instanceof String)
357 maxFormKeys = Integer.valueOf((String)obj);
361 int contentLength = getContentLength();
362 if (contentLength > maxFormContentSize && maxFormContentSize > 0)
364 throw new IllegalStateException("Form too large: " + contentLength + " > " + maxFormContentSize);
366 InputStream in = getInputStream();
367 if (_input.isAsync())
368 throw new IllegalStateException("Cannot extract parameters with async IO");
370 UrlEncoded.decodeTo(in,params,getCharacterEncoding(),contentLength<0?maxFormContentSize:-1,maxFormKeys);
372 catch (IOException e)
374 if (LOG.isDebugEnabled())
377 LOG.warn(e.toString());
381 private void extractMultipartParameters(MultiMap<String> result)
387 catch (IOException | ServletException e)
389 if (LOG.isDebugEnabled())
392 LOG.warn(e.toString());
396 /* ------------------------------------------------------------ */
398 public AsyncContext getAsyncContext()
400 HttpChannelState state = getHttpChannelState();
401 if (_async==null || state.isInitial() && !state.isAsync())
402 throw new IllegalStateException(state.getStatusString());
407 /* ------------------------------------------------------------ */
408 public HttpChannelState getHttpChannelState()
410 return _channel.getState();
413 /* ------------------------------------------------------------ */
415 * Get Request Attribute.
416 * <p>Also supports jetty specific attributes to gain access to Jetty APIs:
418 * <dt>org.eclipse.jetty.server.Server</dt><dd>The Jetty Server instance</dd>
419 * <dt>org.eclipse.jetty.server.HttpChannel</dt><dd>The HttpChannel for this request</dd>
420 * <dt>org.eclipse.jetty.server.HttpConnection</dt><dd>The HttpConnection or null if another transport is used</dd>
422 * While these attributes may look like security problems, they are exposing nothing that is not already
423 * available via reflection from a Request instance.
425 * @see javax.servlet.ServletRequest#getAttribute(java.lang.String)
428 public Object getAttribute(String name)
430 if (name.startsWith("org.eclipse.jetty"))
432 if ("org.eclipse.jetty.server.Server".equals(name))
433 return _channel.getServer();
434 if ("org.eclipse.jetty.server.HttpChannel".equals(name))
436 if ("org.eclipse.jetty.server.HttpConnection".equals(name) &&
437 _channel.getHttpTransport() instanceof HttpConnection)
438 return _channel.getHttpTransport();
440 return (_attributes == null)?null:_attributes.getAttribute(name);
443 /* ------------------------------------------------------------ */
445 * @see javax.servlet.ServletRequest#getAttributeNames()
448 public Enumeration<String> getAttributeNames()
450 if (_attributes == null)
451 return Collections.enumeration(Collections.<String>emptyList());
453 return AttributesMap.getAttributeNamesCopy(_attributes);
456 /* ------------------------------------------------------------ */
459 public Attributes getAttributes()
461 if (_attributes == null)
462 _attributes = new AttributesMap();
466 /* ------------------------------------------------------------ */
468 * Get the authentication.
470 * @return the authentication
472 public Authentication getAuthentication()
474 return _authentication;
477 /* ------------------------------------------------------------ */
479 * @see javax.servlet.http.HttpServletRequest#getAuthType()
482 public String getAuthType()
484 if (_authentication instanceof Authentication.Deferred)
485 setAuthentication(((Authentication.Deferred)_authentication).authenticate(this));
487 if (_authentication instanceof Authentication.User)
488 return ((Authentication.User)_authentication).getAuthMethod();
492 /* ------------------------------------------------------------ */
494 * @see javax.servlet.ServletRequest#getCharacterEncoding()
497 public String getCharacterEncoding()
499 return _characterEncoding;
502 /* ------------------------------------------------------------ */
504 * @return Returns the connection.
506 public HttpChannel<?> getHttpChannel()
511 /* ------------------------------------------------------------ */
513 * @see javax.servlet.ServletRequest#getContentLength()
516 public int getContentLength()
518 return (int)_fields.getLongField(HttpHeader.CONTENT_LENGTH.toString());
521 /* ------------------------------------------------------------ */
523 * @see javax.servlet.ServletRequest.getContentLengthLong()
526 public long getContentLengthLong()
528 return _fields.getLongField(HttpHeader.CONTENT_LENGTH.toString());
531 /* ------------------------------------------------------------ */
532 public long getContentRead()
534 return _input.getContentRead();
537 /* ------------------------------------------------------------ */
539 * @see javax.servlet.ServletRequest#getContentType()
542 public String getContentType()
544 return _fields.getStringField(HttpHeader.CONTENT_TYPE);
547 /* ------------------------------------------------------------ */
549 * @return The current {@link Context context} used for this request, or <code>null</code> if {@link #setContext} has not yet been called.
551 public Context getContext()
556 /* ------------------------------------------------------------ */
558 * @see javax.servlet.http.HttpServletRequest#getContextPath()
561 public String getContextPath()
566 /* ------------------------------------------------------------ */
568 * @see javax.servlet.http.HttpServletRequest#getCookies()
571 public Cookie[] getCookies()
573 if (_cookiesExtracted)
575 if (_cookies == null || _cookies.getCookies().length == 0)
578 return _cookies.getCookies();
581 _cookiesExtracted = true;
583 Enumeration<?> enm = _fields.getValues(HttpHeader.COOKIE.toString());
588 if (_cookies == null)
589 _cookies = new CookieCutter();
591 while (enm.hasMoreElements())
593 String c = (String)enm.nextElement();
594 _cookies.addCookieField(c);
598 //Javadoc for Request.getCookies() stipulates null for no cookies
599 if (_cookies == null || _cookies.getCookies().length == 0)
602 return _cookies.getCookies();
605 /* ------------------------------------------------------------ */
607 * @see javax.servlet.http.HttpServletRequest#getDateHeader(java.lang.String)
610 public long getDateHeader(String name)
612 return _fields.getDateField(name);
615 /* ------------------------------------------------------------ */
617 public DispatcherType getDispatcherType()
619 return _dispatcherType;
622 /* ------------------------------------------------------------ */
624 * @see javax.servlet.http.HttpServletRequest#getHeader(java.lang.String)
627 public String getHeader(String name)
629 return _fields.getStringField(name);
632 /* ------------------------------------------------------------ */
634 * @see javax.servlet.http.HttpServletRequest#getHeaderNames()
637 public Enumeration<String> getHeaderNames()
639 return _fields.getFieldNames();
642 /* ------------------------------------------------------------ */
644 * @see javax.servlet.http.HttpServletRequest#getHeaders(java.lang.String)
647 public Enumeration<String> getHeaders(String name)
649 Enumeration<String> e = _fields.getValues(name);
651 return Collections.enumeration(Collections.<String>emptyList());
655 /* ------------------------------------------------------------ */
657 * @return Returns the inputState.
659 public int getInputState()
664 /* ------------------------------------------------------------ */
666 * @see javax.servlet.ServletRequest#getInputStream()
669 public ServletInputStream getInputStream() throws IOException
671 if (_inputState != __NONE && _inputState != _STREAM)
672 throw new IllegalStateException("READER");
673 _inputState = _STREAM;
675 if (_channel.isExpecting100Continue())
676 _channel.continue100(_input.available());
681 /* ------------------------------------------------------------ */
683 * @see javax.servlet.http.HttpServletRequest#getIntHeader(java.lang.String)
686 public int getIntHeader(String name)
688 return (int)_fields.getLongField(name);
692 /* ------------------------------------------------------------ */
694 * @see javax.servlet.ServletRequest#getLocale()
697 public Locale getLocale()
699 Enumeration<String> enm = _fields.getValues(HttpHeader.ACCEPT_LANGUAGE.toString(),HttpFields.__separators);
702 if (enm == null || !enm.hasMoreElements())
703 return Locale.getDefault();
705 // sort the list in quality order
706 List<?> acceptLanguage = HttpFields.qualityList(enm);
707 if (acceptLanguage.size() == 0)
708 return Locale.getDefault();
710 int size = acceptLanguage.size();
714 String language = (String)acceptLanguage.get(0);
715 language = HttpFields.valueParameters(language,null);
717 int dash = language.indexOf('-');
720 country = language.substring(dash + 1).trim();
721 language = language.substring(0,dash).trim();
723 return new Locale(language,country);
726 return Locale.getDefault();
729 /* ------------------------------------------------------------ */
731 * @see javax.servlet.ServletRequest#getLocales()
734 public Enumeration<Locale> getLocales()
737 Enumeration<String> enm = _fields.getValues(HttpHeader.ACCEPT_LANGUAGE.toString(),HttpFields.__separators);
740 if (enm == null || !enm.hasMoreElements())
741 return Collections.enumeration(__defaultLocale);
743 // sort the list in quality order
744 List<String> acceptLanguage = HttpFields.qualityList(enm);
746 if (acceptLanguage.size() == 0)
747 return Collections.enumeration(__defaultLocale);
749 List<Locale> langs = new ArrayList<>();
752 for (String language : acceptLanguage)
754 language = HttpFields.valueParameters(language, null);
756 int dash = language.indexOf('-');
759 country = language.substring(dash + 1).trim();
760 language = language.substring(0, dash).trim();
762 langs.add(new Locale(language, country));
765 if (langs.size() == 0)
766 return Collections.enumeration(__defaultLocale);
768 return Collections.enumeration(langs);
771 /* ------------------------------------------------------------ */
773 * @see javax.servlet.ServletRequest#getLocalAddr()
776 public String getLocalAddr()
778 InetSocketAddress local=_channel.getLocalAddress();
781 InetAddress address = local.getAddress();
783 return local.getHostString();
784 return address.getHostAddress();
787 /* ------------------------------------------------------------ */
789 * @see javax.servlet.ServletRequest#getLocalName()
792 public String getLocalName()
794 InetSocketAddress local=_channel.getLocalAddress();
795 return local.getHostString();
798 /* ------------------------------------------------------------ */
800 * @see javax.servlet.ServletRequest#getLocalPort()
803 public int getLocalPort()
805 InetSocketAddress local=_channel.getLocalAddress();
806 return local.getPort();
809 /* ------------------------------------------------------------ */
811 * @see javax.servlet.http.HttpServletRequest#getMethod()
814 public String getMethod()
816 return _httpMethodString;
819 /* ------------------------------------------------------------ */
821 * @see javax.servlet.ServletRequest#getParameter(java.lang.String)
824 public String getParameter(String name)
826 if (!_paramsExtracted)
828 if (_parameters == null)
829 _parameters = restoreParameters();
830 return _parameters.getValue(name,0);
833 /* ------------------------------------------------------------ */
835 * @see javax.servlet.ServletRequest#getParameterMap()
838 public Map<String, String[]> getParameterMap()
840 if (!_paramsExtracted)
842 if (_parameters == null)
843 _parameters = restoreParameters();
844 return Collections.unmodifiableMap(_parameters.toStringArrayMap());
847 /* ------------------------------------------------------------ */
849 * @see javax.servlet.ServletRequest#getParameterNames()
852 public Enumeration<String> getParameterNames()
854 if (!_paramsExtracted)
856 if (_parameters == null)
857 _parameters = restoreParameters();
858 return Collections.enumeration(_parameters.keySet());
861 /* ------------------------------------------------------------ */
863 * @see javax.servlet.ServletRequest#getParameterValues(java.lang.String)
866 public String[] getParameterValues(String name)
868 if (!_paramsExtracted)
870 if (_parameters == null)
871 _parameters = restoreParameters();
872 List<String> vals = _parameters.getValues(name);
875 return vals.toArray(new String[vals.size()]);
878 private MultiMap<String> restoreParameters()
880 MultiMap<String> result = new MultiMap<>();
881 if (_queryParameters == null)
882 _queryParameters = extractQueryParameters();
883 result.addAllValues(_queryParameters);
884 result.addAllValues(_contentParameters);
888 public MultiMap<String> getQueryParameters()
890 return _queryParameters;
893 public void setQueryParameters(MultiMap<String> queryParameters)
895 _queryParameters = queryParameters;
898 public void setContentParameters(MultiMap<String> contentParameters)
900 _contentParameters = contentParameters;
903 public void resetParameters()
908 /* ------------------------------------------------------------ */
910 * @see javax.servlet.http.HttpServletRequest#getPathInfo()
913 public String getPathInfo()
918 /* ------------------------------------------------------------ */
920 * @see javax.servlet.http.HttpServletRequest#getPathTranslated()
923 public String getPathTranslated()
925 if (_pathInfo == null || _context == null)
927 return _context.getRealPath(_pathInfo);
930 /* ------------------------------------------------------------ */
932 * @see javax.servlet.ServletRequest#getProtocol()
935 public String getProtocol()
937 return _httpVersion.toString();
940 /* ------------------------------------------------------------ */
942 * @see javax.servlet.ServletRequest#getProtocol()
944 public HttpVersion getHttpVersion()
949 /* ------------------------------------------------------------ */
950 public String getQueryEncoding()
952 return _queryEncoding;
955 /* ------------------------------------------------------------ */
957 * @see javax.servlet.http.HttpServletRequest#getQueryString()
960 public String getQueryString()
962 if (_queryString == null && _uri != null)
964 if (_queryEncoding == null)
965 _queryString = _uri.getQuery();
967 _queryString = _uri.getQuery(_queryEncoding);
972 /* ------------------------------------------------------------ */
974 * @see javax.servlet.ServletRequest#getReader()
977 public BufferedReader getReader() throws IOException
979 if (_inputState != __NONE && _inputState != __READER)
980 throw new IllegalStateException("STREAMED");
982 if (_inputState == __READER)
985 String encoding = getCharacterEncoding();
986 if (encoding == null)
987 encoding = StringUtil.__ISO_8859_1;
989 if (_reader == null || !encoding.equalsIgnoreCase(_readerEncoding))
991 final ServletInputStream in = getInputStream();
992 _readerEncoding = encoding;
993 _reader = new BufferedReader(new InputStreamReader(in,encoding))
996 public void close() throws IOException
1002 _inputState = __READER;
1006 /* ------------------------------------------------------------ */
1008 * @see javax.servlet.ServletRequest#getRealPath(java.lang.String)
1011 public String getRealPath(String path)
1013 if (_context == null)
1015 return _context.getRealPath(path);
1018 /* ------------------------------------------------------------ */
1020 * Access the underlying Remote {@link InetSocketAddress} for this request.
1022 * @return the remote {@link InetSocketAddress} for this request, or null if the request has no remote (see {@link ServletRequest#getRemoteAddr()} for
1023 * conditions that result in no remote address)
1025 public InetSocketAddress getRemoteInetSocketAddress()
1027 InetSocketAddress remote = _remote;
1029 remote = _channel.getRemoteAddress();
1034 /* ------------------------------------------------------------ */
1036 * @see javax.servlet.ServletRequest#getRemoteAddr()
1039 public String getRemoteAddr()
1041 InetSocketAddress remote=_remote;
1043 remote=_channel.getRemoteAddress();
1048 InetAddress address = remote.getAddress();
1050 return remote.getHostString();
1052 return address.getHostAddress();
1055 /* ------------------------------------------------------------ */
1057 * @see javax.servlet.ServletRequest#getRemoteHost()
1060 public String getRemoteHost()
1062 InetSocketAddress remote=_remote;
1064 remote=_channel.getRemoteAddress();
1065 return remote==null?"":remote.getHostString();
1068 /* ------------------------------------------------------------ */
1070 * @see javax.servlet.ServletRequest#getRemotePort()
1073 public int getRemotePort()
1075 InetSocketAddress remote=_remote;
1077 remote=_channel.getRemoteAddress();
1078 return remote==null?0:remote.getPort();
1081 /* ------------------------------------------------------------ */
1083 * @see javax.servlet.http.HttpServletRequest#getRemoteUser()
1086 public String getRemoteUser()
1088 Principal p = getUserPrincipal();
1094 /* ------------------------------------------------------------ */
1096 * @see javax.servlet.ServletRequest#getRequestDispatcher(java.lang.String)
1099 public RequestDispatcher getRequestDispatcher(String path)
1101 if (path == null || _context == null)
1104 // handle relative path
1105 if (!path.startsWith("/"))
1107 String relTo = URIUtil.addPaths(_servletPath,_pathInfo);
1108 int slash = relTo.lastIndexOf("/");
1110 relTo = relTo.substring(0,slash + 1);
1113 path = URIUtil.addPaths(relTo,path);
1116 return _context.getRequestDispatcher(path);
1119 /* ------------------------------------------------------------ */
1121 * @see javax.servlet.http.HttpServletRequest#getRequestedSessionId()
1124 public String getRequestedSessionId()
1126 return _requestedSessionId;
1129 /* ------------------------------------------------------------ */
1131 * @see javax.servlet.http.HttpServletRequest#getRequestURI()
1134 public String getRequestURI()
1136 if (_requestURI == null && _uri != null)
1137 _requestURI = _uri.getPathAndParam();
1141 /* ------------------------------------------------------------ */
1143 * @see javax.servlet.http.HttpServletRequest#getRequestURL()
1146 public StringBuffer getRequestURL()
1148 final StringBuffer url = new StringBuffer(128);
1149 URIUtil.appendSchemeHostPort(url,getScheme(),getServerName(),getServerPort());
1150 url.append(getRequestURI());
1154 /* ------------------------------------------------------------ */
1155 public Response getResponse()
1157 return _channel.getResponse();
1160 /* ------------------------------------------------------------ */
1162 * 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
1165 * 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.
1167 * This method is useful for creating redirect messages and for reporting errors.
1169 * @return "scheme://host:port"
1171 public StringBuilder getRootURL()
1173 StringBuilder url = new StringBuilder(128);
1174 URIUtil.appendSchemeHostPort(url,getScheme(),getServerName(),getServerPort());
1178 /* ------------------------------------------------------------ */
1180 * @see javax.servlet.ServletRequest#getScheme()
1183 public String getScheme()
1188 /* ------------------------------------------------------------ */
1190 * @see javax.servlet.ServletRequest#getServerName()
1193 public String getServerName()
1195 // Return already determined host
1196 if (_serverName != null)
1200 throw new IllegalStateException("No uri");
1202 // Return host from absolute URI
1203 _serverName = _uri.getHost();
1204 if (_serverName != null)
1206 _port = _uri.getPort();
1210 // Return host from header field
1211 String hostPort = _fields.getStringField(HttpHeader.HOST);
1214 if (hostPort != null)
1216 int len=hostPort.length();
1217 loop: for (int i = len; i-- > 0;)
1219 char c2 = (char)(0xff & hostPort.charAt(i));
1229 _port = StringUtil.toInt(hostPort.substring(i+1));
1231 catch (NumberFormatException e)
1234 _serverName=hostPort;
1241 if (hostPort.charAt(0)=='[')
1243 if (hostPort.charAt(len-1)!=']')
1245 LOG.warn("Bad IPv6 "+hostPort);
1246 _serverName=hostPort;
1250 _serverName = hostPort.substring(1,len-1);
1252 else if (len==hostPort.length())
1253 _serverName=hostPort;
1255 _serverName = hostPort.substring(0,len);
1260 // Return host from connection
1261 if (_channel != null)
1263 _serverName = getLocalName();
1264 _port = getLocalPort();
1265 if (_serverName != null && !StringUtil.ALL_INTERFACES.equals(_serverName))
1269 // Return the local host
1272 _serverName = InetAddress.getLocalHost().getHostAddress();
1274 catch (java.net.UnknownHostException e)
1281 /* ------------------------------------------------------------ */
1283 * @see javax.servlet.ServletRequest#getServerPort()
1286 public int getServerPort()
1290 if (_serverName == null)
1295 if (_serverName != null && _uri != null)
1296 _port = _uri.getPort();
1299 InetSocketAddress local = _channel.getLocalAddress();
1300 _port = local == null?0:local.getPort();
1307 if (getScheme().equalsIgnoreCase(URIUtil.HTTPS))
1314 /* ------------------------------------------------------------ */
1316 public ServletContext getServletContext()
1321 /* ------------------------------------------------------------ */
1324 public String getServletName()
1327 return _scope.getName();
1331 /* ------------------------------------------------------------ */
1333 * @see javax.servlet.http.HttpServletRequest#getServletPath()
1336 public String getServletPath()
1338 if (_servletPath == null)
1340 return _servletPath;
1343 /* ------------------------------------------------------------ */
1344 public ServletResponse getServletResponse()
1346 return _channel.getResponse();
1349 /* ------------------------------------------------------------ */
1351 * Add @override when 3.1 api is available
1353 public String changeSessionId()
1355 HttpSession session = getSession(false);
1356 if (session == null)
1357 throw new IllegalStateException("No session");
1359 if (session instanceof AbstractSession)
1361 AbstractSession abstractSession = ((AbstractSession)session);
1362 abstractSession.renewId(this);
1363 if (getRemoteUser() != null)
1364 abstractSession.setAttribute(AbstractSession.SESSION_KNOWN_ONLY_TO_AUTHENTICATED, Boolean.TRUE);
1365 if (abstractSession.isIdChanged())
1366 _channel.getResponse().addCookie(_sessionManager.getSessionCookie(abstractSession, getContextPath(), isSecure()));
1369 return session.getId();
1372 /* ------------------------------------------------------------ */
1374 * @see javax.servlet.http.HttpServletRequest#getSession()
1377 public HttpSession getSession()
1379 return getSession(true);
1382 /* ------------------------------------------------------------ */
1384 * @see javax.servlet.http.HttpServletRequest#getSession(boolean)
1387 public HttpSession getSession(boolean create)
1389 if (_session != null)
1391 if (_sessionManager != null && !_sessionManager.isValid(_session))
1400 if (getResponse().isCommitted())
1401 throw new IllegalStateException("Response is committed");
1403 if (_sessionManager == null)
1404 throw new IllegalStateException("No SessionManager");
1406 _session = _sessionManager.newHttpSession(this);
1407 HttpCookie cookie = _sessionManager.getSessionCookie(_session,getContextPath(),isSecure());
1409 _channel.getResponse().addCookie(cookie);
1414 /* ------------------------------------------------------------ */
1416 * @return Returns the sessionManager.
1418 public SessionManager getSessionManager()
1420 return _sessionManager;
1423 /* ------------------------------------------------------------ */
1425 * Get Request TimeStamp
1427 * @return The time that the request was received.
1429 public long getTimeStamp()
1434 /* ------------------------------------------------------------ */
1436 * @return Returns the uri.
1438 public HttpURI getUri()
1443 /* ------------------------------------------------------------ */
1444 public UserIdentity getUserIdentity()
1446 if (_authentication instanceof Authentication.Deferred)
1447 setAuthentication(((Authentication.Deferred)_authentication).authenticate(this));
1449 if (_authentication instanceof Authentication.User)
1450 return ((Authentication.User)_authentication).getUserIdentity();
1454 /* ------------------------------------------------------------ */
1456 * @return The resolved user Identity, which may be null if the {@link Authentication} is not {@link Authentication.User} (eg.
1457 * {@link Authentication.Deferred}).
1459 public UserIdentity getResolvedUserIdentity()
1461 if (_authentication instanceof Authentication.User)
1462 return ((Authentication.User)_authentication).getUserIdentity();
1466 /* ------------------------------------------------------------ */
1467 public UserIdentity.Scope getUserIdentityScope()
1472 /* ------------------------------------------------------------ */
1474 * @see javax.servlet.http.HttpServletRequest#getUserPrincipal()
1477 public Principal getUserPrincipal()
1479 if (_authentication instanceof Authentication.Deferred)
1480 setAuthentication(((Authentication.Deferred)_authentication).authenticate(this));
1482 if (_authentication instanceof Authentication.User)
1484 UserIdentity user = ((Authentication.User)_authentication).getUserIdentity();
1485 return user.getUserPrincipal();
1492 /* ------------------------------------------------------------ */
1493 public boolean isHandled()
1499 public boolean isAsyncStarted()
1501 return getHttpChannelState().isAsyncStarted();
1505 /* ------------------------------------------------------------ */
1507 public boolean isAsyncSupported()
1509 return _asyncSupported;
1512 /* ------------------------------------------------------------ */
1514 * @see javax.servlet.http.HttpServletRequest#isRequestedSessionIdFromCookie()
1517 public boolean isRequestedSessionIdFromCookie()
1519 return _requestedSessionId != null && _requestedSessionIdFromCookie;
1522 /* ------------------------------------------------------------ */
1524 * @see javax.servlet.http.HttpServletRequest#isRequestedSessionIdFromUrl()
1527 public boolean isRequestedSessionIdFromUrl()
1529 return _requestedSessionId != null && !_requestedSessionIdFromCookie;
1532 /* ------------------------------------------------------------ */
1534 * @see javax.servlet.http.HttpServletRequest#isRequestedSessionIdFromURL()
1537 public boolean isRequestedSessionIdFromURL()
1539 return _requestedSessionId != null && !_requestedSessionIdFromCookie;
1542 /* ------------------------------------------------------------ */
1544 * @see javax.servlet.http.HttpServletRequest#isRequestedSessionIdValid()
1547 public boolean isRequestedSessionIdValid()
1549 if (_requestedSessionId == null)
1552 HttpSession session = getSession(false);
1553 return (session != null && _sessionManager.getSessionIdManager().getClusterId(_requestedSessionId).equals(_sessionManager.getClusterId(session)));
1556 /* ------------------------------------------------------------ */
1558 * @see javax.servlet.ServletRequest#isSecure()
1561 public boolean isSecure()
1566 /* ------------------------------------------------------------ */
1567 public void setSecure(boolean secure)
1572 /* ------------------------------------------------------------ */
1574 * @see javax.servlet.http.HttpServletRequest#isUserInRole(java.lang.String)
1577 public boolean isUserInRole(String role)
1579 if (_authentication instanceof Authentication.Deferred)
1580 setAuthentication(((Authentication.Deferred)_authentication).authenticate(this));
1582 if (_authentication instanceof Authentication.User)
1583 return ((Authentication.User)_authentication).isUserInRole(_scope,role);
1587 /* ------------------------------------------------------------ */
1588 public HttpSession recoverNewSession(Object key)
1590 if (_savedNewSessions == null)
1592 return _savedNewSessions.get(key);
1595 /* ------------------------------------------------------------ */
1596 protected void recycle()
1598 if (_context != null)
1599 throw new IllegalStateException("Request in context!");
1601 if (_inputState == __READER)
1605 int r = _reader.read();
1616 _dispatcherType=null;
1617 setAuthentication(Authentication.NOT_CHECKED);
1618 getHttpChannelState().recycle();
1622 _asyncSupported = true;
1624 if (_attributes != null)
1625 _attributes.clearAttributes();
1626 _characterEncoding = null;
1627 _contextPath = null;
1628 if (_cookies != null)
1630 _cookiesExtracted = false;
1635 _httpMethodString = null;
1638 _httpVersion = HttpVersion.HTTP_1_1;
1639 _queryEncoding = null;
1640 _queryString = null;
1641 _requestedSessionId = null;
1642 _requestedSessionIdFromCookie = false;
1645 _sessionManager = null;
1648 _scheme = URIUtil.HTTP;
1649 _servletPath = null;
1652 _queryParameters = null;
1653 _contentParameters = null;
1655 _paramsExtracted = false;
1656 _inputState = __NONE;
1658 if (_savedNewSessions != null)
1659 _savedNewSessions.clear();
1660 _savedNewSessions=null;
1661 _multiPartInputStream = null;
1667 /* ------------------------------------------------------------ */
1669 * @see javax.servlet.ServletRequest#removeAttribute(java.lang.String)
1672 public void removeAttribute(String name)
1674 Object old_value = _attributes == null?null:_attributes.getAttribute(name);
1676 if (_attributes != null)
1677 _attributes.removeAttribute(name);
1679 if (old_value != null && !_requestAttributeListeners.isEmpty())
1681 final ServletRequestAttributeEvent event = new ServletRequestAttributeEvent(_context,this,name,old_value);
1682 for (ServletRequestAttributeListener listener : _requestAttributeListeners)
1683 listener.attributeRemoved(event);
1687 /* ------------------------------------------------------------ */
1688 public void removeEventListener(final EventListener listener)
1690 _requestAttributeListeners.remove(listener);
1693 /* ------------------------------------------------------------ */
1694 public void saveNewSession(Object key, HttpSession session)
1696 if (_savedNewSessions == null)
1697 _savedNewSessions = new HashMap<>();
1698 _savedNewSessions.put(key,session);
1701 /* ------------------------------------------------------------ */
1702 public void setAsyncSupported(boolean supported)
1704 _asyncSupported = supported;
1707 /* ------------------------------------------------------------ */
1709 * 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
1710 * {@link #setQueryEncoding}.
1712 * @see javax.servlet.ServletRequest#setAttribute(java.lang.String, java.lang.Object)
1715 public void setAttribute(String name, Object value)
1717 Object old_value = _attributes == null?null:_attributes.getAttribute(name);
1719 if ("org.eclipse.jetty.server.Request.queryEncoding".equals(name))
1720 setQueryEncoding(value == null?null:value.toString());
1721 else if ("org.eclipse.jetty.server.sendContent".equals(name))
1722 LOG.warn("Deprecated: org.eclipse.jetty.server.sendContent");
1724 if (_attributes == null)
1725 _attributes = new AttributesMap();
1726 _attributes.setAttribute(name,value);
1728 if (!_requestAttributeListeners.isEmpty())
1730 final ServletRequestAttributeEvent event = new ServletRequestAttributeEvent(_context,this,name,old_value == null?value:old_value);
1731 for (ServletRequestAttributeListener l : _requestAttributeListeners)
1733 if (old_value == null)
1734 l.attributeAdded(event);
1735 else if (value == null)
1736 l.attributeRemoved(event);
1738 l.attributeReplaced(event);
1743 /* ------------------------------------------------------------ */
1746 public void setAttributes(Attributes attributes)
1748 _attributes = attributes;
1751 /* ------------------------------------------------------------ */
1753 /* ------------------------------------------------------------ */
1755 * Set the authentication.
1757 * @param authentication
1758 * the authentication to set
1760 public void setAuthentication(Authentication authentication)
1762 _authentication = authentication;
1765 /* ------------------------------------------------------------ */
1767 * @see javax.servlet.ServletRequest#setCharacterEncoding(java.lang.String)
1770 public void setCharacterEncoding(String encoding) throws UnsupportedEncodingException
1772 if (_inputState != __NONE)
1775 _characterEncoding = encoding;
1777 // check encoding is supported
1778 if (!StringUtil.isUTF8(encoding))
1782 Charset.forName(encoding);
1784 catch (UnsupportedCharsetException e)
1786 throw new UnsupportedEncodingException(e.getMessage());
1791 /* ------------------------------------------------------------ */
1793 * @see javax.servlet.ServletRequest#setCharacterEncoding(java.lang.String)
1795 public void setCharacterEncodingUnchecked(String encoding)
1797 _characterEncoding = encoding;
1800 /* ------------------------------------------------------------ */
1802 * @see javax.servlet.ServletRequest#getContentType()
1804 public void setContentType(String contentType)
1806 _fields.put(HttpHeader.CONTENT_TYPE,contentType);
1810 /* ------------------------------------------------------------ */
1812 * Set request context
1817 public void setContext(Context context)
1819 _newContext = _context != context;
1823 /* ------------------------------------------------------------ */
1825 * @return True if this is the first call of {@link #takeNewContext()} since the last
1826 * {@link #setContext(org.eclipse.jetty.server.handler.ContextHandler.Context)} call.
1828 public boolean takeNewContext()
1830 boolean nc = _newContext;
1831 _newContext = false;
1835 /* ------------------------------------------------------------ */
1837 * Sets the "context path" for this request
1839 * @see HttpServletRequest#getContextPath()
1841 public void setContextPath(String contextPath)
1843 _contextPath = contextPath;
1846 /* ------------------------------------------------------------ */
1849 * The cookies to set.
1851 public void setCookies(Cookie[] cookies)
1853 if (_cookies == null)
1854 _cookies = new CookieCutter();
1855 _cookies.setCookies(cookies);
1858 /* ------------------------------------------------------------ */
1859 public void setDispatcherType(DispatcherType type)
1861 _dispatcherType = type;
1864 /* ------------------------------------------------------------ */
1865 public void setHandled(boolean h)
1868 Response r=getResponse();
1869 if (_handled && r.getStatus()==0)
1873 /* ------------------------------------------------------------ */
1876 * The method to set.
1878 public void setMethod(HttpMethod httpMethod, String method)
1880 _httpMethod=httpMethod;
1881 _httpMethodString = method;
1884 /* ------------------------------------------------------------ */
1885 public boolean isHead()
1887 return HttpMethod.HEAD==_httpMethod;
1890 /* ------------------------------------------------------------ */
1893 * The pathInfo to set.
1895 public void setPathInfo(String pathInfo)
1897 _pathInfo = pathInfo;
1900 /* ------------------------------------------------------------ */
1903 * The protocol to set.
1905 public void setHttpVersion(HttpVersion version)
1907 _httpVersion = version;
1910 /* ------------------------------------------------------------ */
1912 * 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
1913 * getParameter methods.
1915 * The request attribute "org.eclipse.jetty.server.server.Request.queryEncoding" may be set as an alternate method of calling setQueryEncoding.
1917 * @param queryEncoding
1919 public void setQueryEncoding(String queryEncoding)
1921 _queryEncoding = queryEncoding;
1922 _queryString = null;
1925 /* ------------------------------------------------------------ */
1927 * @param queryString
1928 * The queryString to set.
1930 public void setQueryString(String queryString)
1932 _queryString = queryString;
1933 _queryEncoding = null; //assume utf-8
1936 /* ------------------------------------------------------------ */
1939 * The address to set.
1941 public void setRemoteAddr(InetSocketAddress addr)
1946 /* ------------------------------------------------------------ */
1948 * @param requestedSessionId
1949 * The requestedSessionId to set.
1951 public void setRequestedSessionId(String requestedSessionId)
1953 _requestedSessionId = requestedSessionId;
1956 /* ------------------------------------------------------------ */
1958 * @param requestedSessionIdCookie
1959 * The requestedSessionIdCookie to set.
1961 public void setRequestedSessionIdFromCookie(boolean requestedSessionIdCookie)
1963 _requestedSessionIdFromCookie = requestedSessionIdCookie;
1966 /* ------------------------------------------------------------ */
1969 * The requestURI to set.
1971 public void setRequestURI(String requestURI)
1973 _requestURI = requestURI;
1976 /* ------------------------------------------------------------ */
1979 * The scheme to set.
1981 public void setScheme(String scheme)
1986 /* ------------------------------------------------------------ */
1991 public void setServerName(String host)
1996 /* ------------------------------------------------------------ */
2001 public void setServerPort(int port)
2006 /* ------------------------------------------------------------ */
2008 * @param servletPath
2009 * The servletPath to set.
2011 public void setServletPath(String servletPath)
2013 _servletPath = servletPath;
2016 /* ------------------------------------------------------------ */
2019 * The session to set.
2021 public void setSession(HttpSession session)
2026 /* ------------------------------------------------------------ */
2028 * @param sessionManager
2029 * The sessionManager to set.
2031 public void setSessionManager(SessionManager sessionManager)
2033 _sessionManager = sessionManager;
2036 /* ------------------------------------------------------------ */
2037 public void setTimeStamp(long ts)
2042 /* ------------------------------------------------------------ */
2047 public void setUri(HttpURI uri)
2052 /* ------------------------------------------------------------ */
2053 public void setUserIdentityScope(UserIdentity.Scope scope)
2058 /* ------------------------------------------------------------ */
2060 public AsyncContext startAsync() throws IllegalStateException
2062 if (!_asyncSupported)
2063 throw new IllegalStateException("!asyncSupported");
2064 HttpChannelState state = getHttpChannelState();
2066 _async=new AsyncContextState(state);
2067 AsyncContextEvent event = new AsyncContextEvent(_context,_async,state,this,this,getResponse());
2068 state.startAsync(event);
2072 /* ------------------------------------------------------------ */
2074 public AsyncContext startAsync(ServletRequest servletRequest, ServletResponse servletResponse) throws IllegalStateException
2076 if (!_asyncSupported)
2077 throw new IllegalStateException("!asyncSupported");
2078 HttpChannelState state = getHttpChannelState();
2080 _async=new AsyncContextState(state);
2081 AsyncContextEvent event = new AsyncContextEvent(_context,_async,state,this,servletRequest,servletResponse);
2082 event.setDispatchContext(getServletContext());
2083 event.setDispatchPath(URIUtil.addPaths(getServletPath(),getPathInfo()));
2084 state.startAsync(event);
2088 /* ------------------------------------------------------------ */
2090 public String toString()
2092 return (_handled?"[":"(") + getMethod() + " " + _uri + (_handled?"]@":")@") + hashCode() + " " + super.toString();
2095 /* ------------------------------------------------------------ */
2097 public boolean authenticate(HttpServletResponse response) throws IOException, ServletException
2099 if (_authentication instanceof Authentication.Deferred)
2101 setAuthentication(((Authentication.Deferred)_authentication).authenticate(this,response));
2102 return !(_authentication instanceof Authentication.ResponseSent);
2104 response.sendError(HttpStatus.UNAUTHORIZED_401);
2108 /* ------------------------------------------------------------ */
2110 public Part getPart(String name) throws IOException, ServletException
2114 return _multiPartInputStream.getPart(name);
2117 /* ------------------------------------------------------------ */
2119 public Collection<Part> getParts() throws IOException, ServletException
2121 if (getContentType() == null || !getContentType().startsWith("multipart/form-data"))
2122 throw new ServletException("Content-Type != multipart/form-data");
2123 return getParts(null);
2126 private Collection<Part> getParts(MultiMap<String> params) throws IOException, ServletException
2128 if (_multiPartInputStream == null)
2129 _multiPartInputStream = (MultiPartInputStreamParser)getAttribute(__MULTIPART_INPUT_STREAM);
2131 if (_multiPartInputStream == null)
2133 MultipartConfigElement config = (MultipartConfigElement)getAttribute(__MULTIPART_CONFIG_ELEMENT);
2136 throw new IllegalStateException("No multipart config for servlet");
2138 _multiPartInputStream = new MultiPartInputStreamParser(getInputStream(),
2139 getContentType(), config,
2140 (_context != null?(File)_context.getAttribute("javax.servlet.context.tempdir"):null));
2142 setAttribute(__MULTIPART_INPUT_STREAM, _multiPartInputStream);
2143 setAttribute(__MULTIPART_CONTEXT, _context);
2144 Collection<Part> parts = _multiPartInputStream.getParts(); //causes parsing
2145 ByteArrayOutputStream os = null;
2148 MultiPartInputStreamParser.MultiPart mp = (MultiPartInputStreamParser.MultiPart)p;
2149 if (mp.getContentDispositionFilename() == null)
2151 // Servlet Spec 3.0 pg 23, parts without filename must be put into params.
2152 String charset = null;
2153 if (mp.getContentType() != null)
2154 charset = MimeTypes.getCharsetFromContentType(mp.getContentType());
2156 try (InputStream is = mp.getInputStream())
2159 os = new ByteArrayOutputStream();
2161 String content=new String(os.toByteArray(),charset==null?StandardCharsets.UTF_8:Charset.forName(charset));
2162 if (_contentParameters == null)
2163 _contentParameters = params == null ? new MultiMap<String>() : params;
2164 _contentParameters.add(mp.getName(), content);
2171 return _multiPartInputStream.getParts();
2174 /* ------------------------------------------------------------ */
2176 public void login(String username, String password) throws ServletException
2178 if (_authentication instanceof Authentication.Deferred)
2180 _authentication=((Authentication.Deferred)_authentication).login(username,password,this);
2181 if (_authentication == null)
2182 throw new Authentication.Failed("Authentication failed for username '"+username+"'");
2186 throw new Authentication.Failed("Authenticated failed for username '"+username+"'. Already authenticated as "+_authentication);
2190 /* ------------------------------------------------------------ */
2192 public void logout() throws ServletException
2194 if (_authentication instanceof Authentication.User)
2195 ((Authentication.User)_authentication).logout();
2196 _authentication=Authentication.UNAUTHENTICATED;
2199 public void mergeQueryParameters(String newQuery, boolean updateQueryString)
2201 MultiMap<String> newQueryParams = new MultiMap<>();
2202 // Have to assume ENCODING because we can't know otherwise.
2203 UrlEncoded.decodeTo(newQuery, newQueryParams, UrlEncoded.ENCODING, -1);
2205 MultiMap<String> oldQueryParams = _queryParameters;
2206 if (oldQueryParams == null && _queryString != null)
2208 oldQueryParams = new MultiMap<>();
2209 UrlEncoded.decodeTo(_queryString, oldQueryParams, getQueryEncoding(), -1);
2212 MultiMap<String> mergedQueryParams = newQueryParams;
2213 if (oldQueryParams != null)
2215 // Parameters values are accumulated.
2216 mergedQueryParams = new MultiMap<>(newQueryParams);
2217 mergedQueryParams.addAllValues(oldQueryParams);
2220 setQueryParameters(mergedQueryParams);
2223 if (updateQueryString)
2225 // Build the new merged query string, parameters in the
2226 // new query string hide parameters in the old query string.
2227 StringBuilder mergedQuery = new StringBuilder(newQuery);
2228 for (Map.Entry<String, List<String>> entry : mergedQueryParams.entrySet())
2230 if (newQueryParams.containsKey(entry.getKey()))
2232 for (String value : entry.getValue())
2233 mergedQuery.append("&").append(entry.getKey()).append("=").append(value);
2236 setQueryString(mergedQuery.toString());
2241 * @see javax.servlet.http.HttpServletRequest#upgrade(java.lang.Class)
2244 public <T extends HttpUpgradeHandler> T upgrade(Class<T> handlerClass) throws IOException, ServletException
2246 if (getContext() == null)
2247 throw new ServletException ("Unable to instantiate "+handlerClass);
2251 //Instantiate an instance and inject it
2252 T h = getContext().createInstance(handlerClass);
2254 //TODO handle the rest of the upgrade process
2260 if (e instanceof ServletException)
2261 throw (ServletException)e;
2262 throw new ServletException(e);