Read queryString on urls
org/apache/tomcat/embed/tomcat-embed-core/8.0.33/tomcat-embed-core-8.0.33-sources.jar! /org/apache/catalina/core/ApplicationDispatcher.java
private void doDispatch(ServletRequest request, ServletResponse response) throws ServletException, IOException
private void doForward(ServletRequest request, ServletResponse response)
throws ServletException, IOException
private void doInclude(ServletRequest request, ServletResponse response)
throws ServletException, IOException
Look at doDispatch here.
private void doDispatch(ServletRequest request, ServletResponse response)
throws ServletException, IOException {
// Set up to handle the specified request and response
State state = new State(request, response, false);
// Create a wrapped response to use for this request
wrapResponse(state);
ApplicationHttpRequest wrequest =
(ApplicationHttpRequest) wrapRequest(state);
if (queryString != null) {
wrequest.setQueryParams(queryString);
}
wrequest.setAttribute(Globals.DISPATCHER_TYPE_ATTR,
DispatcherType.ASYNC);
wrequest.setAttribute(Globals.DISPATCHER_REQUEST_PATH_ATTR,
getCombinedPath());
wrequest.setContextPath(context.getPath());
wrequest.setRequestURI(requestURI);
wrequest.setServletPath(servletPath);
wrequest.setPathInfo(pathInfo);
if (queryString != null) {
wrequest.setQueryString(queryString);
wrequest.setQueryParams(queryString);
}
invoke(state.outerRequest, state.outerResponse, state);
}
ApplicationDispatcher.doDispatch–>ApplicationHttpRequest.setQueryString –>ApplicationHttpRequest.parseParameters –>mergeParameters
private void mergeParameters() {
if ((queryParamString == null) || (queryParamString.length() < 1))
return;
// Parse the query string from the dispatch target
Parameters paramParser = new Parameters();
MessageBytes queryMB = MessageBytes.newInstance();
queryMB.setString(queryParamString);
String encoding = getCharacterEncoding();
// No need to process null value, as ISO-8859-1 is the default encoding
// in MessageBytes.toBytes().
if (encoding != null) {
try {
queryMB.setCharset(B2CConverter.getCharset(encoding));
} catch (UnsupportedEncodingException ignored) {
// Fall-back to ISO-8859-1
}
}
paramParser.setQuery(queryMB);
paramParser.setQueryStringEncoding(encoding);
paramParser.handleQueryParameters();
// Insert the additional parameters from the dispatch target
Enumeration<String> dispParamNames = paramParser.getParameterNames();
while (dispParamNames.hasMoreElements()) {
String dispParamName = dispParamNames.nextElement();
String[] dispParamValues = paramParser.getParameterValues(dispParamName);
String[] originalValues = parameters.get(dispParamName);
if (originalValues == null) {
parameters.put(dispParamName, dispParamValues);
continue;
}
parameters.put(dispParamName, mergeValues(dispParamValues, originalValues));
}
}
Read parameters of post and body
org/apache/tomcat/embed/tomcat-embed-core/8.0.33/tomcat-embed-core-8.0.33-sources.jar! /org/apache/catalina/connector/Request.java
/**
* Parse request parameters.
*/
protected void parseParameters() {
parametersParsed = true;
Parameters parameters = coyoteRequest.getParameters();
boolean success = false;
try {
// Set this every time in case limit has been changed via JMX
parameters.setLimit(getConnector().getMaxParameterCount());
// getCharacterEncoding() may have been overridden to search for
// hidden form field containing request encoding
String enc = getCharacterEncoding();
boolean useBodyEncodingForURI = connector.getUseBodyEncodingForURI();
if (enc != null) {
parameters.setEncoding(enc);
if (useBodyEncodingForURI) {
parameters.setQueryStringEncoding(enc);
}
} else {
parameters.setEncoding
(org.apache.coyote.Constants.DEFAULT_CHARACTER_ENCODING);
if (useBodyEncodingForURI) {
parameters.setQueryStringEncoding
(org.apache.coyote.Constants.DEFAULT_CHARACTER_ENCODING);
}
}
parameters.handleQueryParameters();
if (usingInputStream || usingReader) {
success = true;
return;
}
if( !getConnector().isParseBodyMethod(getMethod()) ) {
success = true;
return;
}
String contentType = getContentType();
if (contentType == null) {
contentType = "";
}
int semicolon = contentType.indexOf(';');
if (semicolon >= 0) {
contentType = contentType.substring(0, semicolon).trim();
} else {
contentType = contentType.trim();
}
if ("multipart/form-data".equals(contentType)) {
parseParts(false);
success = true;
return;
}
if (!("application/x-www-form-urlencoded".equals(contentType))) {
success = true;
return;
}
int len = getContentLength();
if (len > 0) {
int maxPostSize = connector.getMaxPostSize();
if ((maxPostSize >= 0) && (len > maxPostSize)) {
Context context = getContext();
if (context != null && context.getLogger().isDebugEnabled()) {
context.getLogger().debug(
sm.getString("coyoteRequest.postTooLarge"));
}
checkSwallowInput();
parameters.setParseFailedReason(FailReason.POST_TOO_LARGE);
return;
}
byte[] formData = null;
if (len < CACHED_POST_LEN) {
if (postData == null) {
postData = new byte[CACHED_POST_LEN];
}
formData = postData;
} else {
formData = new byte[len];
}
try {
if (readPostBody(formData, len) != len) {
parameters.setParseFailedReason(FailReason.REQUEST_BODY_INCOMPLETE);
return;
}
} catch (IOException e) {
// Client disconnect
Context context = getContext();
if (context != null && context.getLogger().isDebugEnabled()) {
context.getLogger().debug(
sm.getString("coyoteRequest.parseParameters"),
e);
}
parameters.setParseFailedReason(FailReason.CLIENT_DISCONNECT);
return;
}
parameters.processParameters(formData, 0, len);
} else if ("chunked".equalsIgnoreCase(
coyoteRequest.getHeader("transfer-encoding"))) {
byte[] formData = null;
try {
formData = readChunkedPostBody();
} catch (IllegalStateException ise) {
// chunkedPostTooLarge error
parameters.setParseFailedReason(FailReason.POST_TOO_LARGE);
Context context = getContext();
if (context != null && context.getLogger().isDebugEnabled()) {
context.getLogger().debug(
sm.getString("coyoteRequest.parseParameters"),
ise);
}
return;
} catch (IOException e) {
// Client disconnect
parameters.setParseFailedReason(FailReason.CLIENT_DISCONNECT);
Context context = getContext();
if (context != null && context.getLogger().isDebugEnabled()) {
context.getLogger().debug(
sm.getString("coyoteRequest.parseParameters"),
e);
}
return;
}
if (formData != null) {
parameters.processParameters(formData, 0, formData.length);
}
}
success = true;
} finally {
if (!success) {
parameters.setParseFailedReason(FailReason.UNKNOWN);
}
}
}
readPostBody
/**
* Read post body in an array.
*/
protected int readPostBody(byte body[], int len)
throws IOException {
int offset = 0;
do {
int inputLen = getStream().read(body, offset, len - offset);
if (inputLen <= 0) {
return offset;
}
offset += inputLen;
} while ((len - offset) > 0);
return len;
}
readChunkedPostBody
/**
* Read chunked post body.
*/
protected byte[] readChunkedPostBody() throws IOException {
ByteChunk body = new ByteChunk();
byte[] buffer = new byte[CACHED_POST_LEN];
int len = 0;
while (len > -1) {
len = getStream().read(buffer, 0, CACHED_POST_LEN);
if (connector.getMaxPostSize() >= 0 &&
(body.getLength() + len) > connector.getMaxPostSize()) {
// Too much data
checkSwallowInput();
throw new IllegalStateException(
sm.getString("coyoteRequest.chunkedPostTooLarge"));
}
if (len > 0) {
body.append(buffer, 0, len);
}
}
if (body.getLength() == 0) {
return null;
}
if (body.getLength() < body.getBuffer().length) {
int length = body.getLength();
byte[] result = new byte[length];
System.arraycopy(body.getBuffer(), 0, result, 0, length);
return result;
}
return body.getBuffer();
}
parameters.processParameters(formData, 0, formData.length);
–>addParameter
public void addParameter( String key, String value )
throws IllegalStateException {
if( key==null ) {
return;
}
parameterCount ++;
if (limit > -1 && parameterCount > limit) {
// Processing this parameter will push us over the limit. ISE is
// what Request.parseParts() uses for requests that are too big
setParseFailedReason(FailReason.TOO_MANY_PARAMETERS);
throw new IllegalStateException(sm.getString(
"parameters.maxCountFail", Integer.valueOf(limit)));
}
ArrayList<String> values = paramHashValues.get(key);
if (values == null) {
values = new ArrayList<>(1);
paramHashValues.put(key, values);
}
values.add(value);
}
Then call here
public Enumeration<String> getParameterNames() {
handleQueryParameters();
return Collections.enumeration(paramHashValues.keySet());
}
While Request’s getParameterNames delegate Parameters’ getParameterNames
public Enumeration<String> getParameterNames() {
if (!parametersParsed) {
parseParameters();
}
return coyoteRequest.getParameters().getParameterNames();
}
Finally, there is a unified merge process, see mergeParameters above.
UsingReader and usingInputStream flag bits
getReader
@Override
public BufferedReader getReader() throws IOException {
if (usingInputStream) {
throw new IllegalStateException
(sm.getString("coyoteRequest.getReader.ise"));
}
usingReader = true;
inputBuffer.checkConverter();
if (reader == null) {
reader = new CoyoteReader(inputBuffer);
}
return reader;
}
getInputStream
@Override
public ServletInputStream getInputStream() throws IOException {
if (usingReader) {
throw new IllegalStateException
(sm.getString("coyoteRequest.getInputStream.ise"));
}
usingInputStream = true;
if (inputStream == null) {
inputStream = new CoyoteInputStream(inputBuffer);
}
return inputStream;
}
The Servlet Request’s getinputstream () getreader () getparameter () uses either method when reading the parameters of the post method, and cannot read the parameters when calling the other two methods. GetParameter can be reused on a single thread, and there may be exceptions if it is multi-threaded, because the method relies on parametersParsed, the boolean parameter is not atomic.