Skip to content

Commit 24ecab3

Browse files
committed
Add test case for BZ 69442. Based on #779 by Chenjp
Also refactor references to application/x-www-form-urlencoded https://bz.apache.org/bugzilla/show_bug.cgi?id=69442
1 parent c73b37c commit 24ecab3

File tree

15 files changed

+110
-46
lines changed

15 files changed

+110
-46
lines changed

java/org/apache/catalina/Globals.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,4 +249,9 @@ public final class Globals {
249249
* Default domain for MBeans if none can be determined
250250
*/
251251
public static final String DEFAULT_MBEAN_DOMAIN = "Catalina";
252+
253+
254+
// ----------------------------------------- Specification related constants
255+
256+
public static final String CONTENT_TYPE_FORM_URL_ENCODING = "application/x-www-form-urlencoded";
252257
}

java/org/apache/catalina/authenticator/FormAuthenticator.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import jakarta.servlet.http.HttpServletResponse;
3030
import jakarta.servlet.http.HttpSession;
3131

32+
import org.apache.catalina.Globals;
3233
import org.apache.catalina.Realm;
3334
import org.apache.catalina.Session;
3435
import org.apache.catalina.connector.Request;
@@ -626,7 +627,7 @@ protected boolean restoreRequest(Request request, Session session) throws IOExce
626627
// If no content type specified, use default for POST
627628
String savedContentType = saved.getContentType();
628629
if (savedContentType == null && "POST".equalsIgnoreCase(method)) {
629-
savedContentType = "application/x-www-form-urlencoded";
630+
savedContentType = Globals.CONTENT_TYPE_FORM_URL_ENCODING;
630631
}
631632

632633
contentType.setString(savedContentType);

java/org/apache/catalina/connector/Request.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2910,7 +2910,7 @@ protected void parseParameters() {
29102910
return;
29112911
}
29122912

2913-
if (!("application/x-www-form-urlencoded".equals(mediaType))) {
2913+
if (!(Globals.CONTENT_TYPE_FORM_URL_ENCODING.equals(mediaType))) {
29142914
success = true;
29152915
return;
29162916
}

java/org/apache/catalina/filters/CorsFilter.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import jakarta.servlet.http.HttpServletRequest;
3636
import jakarta.servlet.http.HttpServletResponse;
3737

38+
import org.apache.catalina.Globals;
3839
import org.apache.juli.logging.Log;
3940
import org.apache.juli.logging.LogFactory;
4041
import org.apache.tomcat.util.http.RequestUtil;
@@ -908,7 +909,7 @@ protected enum CORSRequestType {
908909
* @see <a href="http://www.w3.org/TR/cors/#terminology" >http://www.w3.org/TR/cors/#terminology</a>
909910
*/
910911
public static final Collection<String> SIMPLE_HTTP_REQUEST_CONTENT_TYPE_VALUES = Collections.unmodifiableSet(
911-
new HashSet<>(Arrays.asList("application/x-www-form-urlencoded", "multipart/form-data", "text/plain")));
912+
new HashSet<>(Arrays.asList(Globals.CONTENT_TYPE_FORM_URL_ENCODING, "multipart/form-data", "text/plain")));
912913

913914
// ------------------------------------------------ Configuration Defaults
914915
/**

test/org/apache/catalina/authenticator/TestFormAuthenticatorA.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -467,9 +467,7 @@ protected void doResourceRequest(String method, boolean isFullQualUri,
467467
if (requestTail == null) {
468468
requestTail = "role=bar";
469469
}
470-
requestHead.append(
471-
"Content-Type: application/x-www-form-urlencoded")
472-
.append(CRLF);
470+
requestHead.append(SimpleHttpClient.HTTP_HEADER_CONTENT_TYPE_FORM_URL_ENCODING);
473471
// calculate post data length
474472
String len = Integer.toString(requestTail.length());
475473
requestHead.append("Content-length: ").append(len).append(CRLF);

test/org/apache/catalina/authenticator/TestFormAuthenticatorB.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -359,9 +359,7 @@ protected void doResourceRequest(String method, boolean isFullQualUri,
359359
if (requestTail == null) {
360360
requestTail = "role=bar";
361361
}
362-
requestHead.append(
363-
"Content-Type: application/x-www-form-urlencoded")
364-
.append(CRLF);
362+
requestHead.append(SimpleHttpClient.HTTP_HEADER_CONTENT_TYPE_FORM_URL_ENCODING);
365363
// calculate post data length
366364
String len = Integer.toString(requestTail.length());
367365
requestHead.append("Content-length: ").append(len).append(CRLF);

test/org/apache/catalina/authenticator/TestFormAuthenticatorC.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -361,9 +361,7 @@ protected void doResourceRequest(String method, boolean isFullQualUri,
361361
if (requestTail == null) {
362362
requestTail = "role=bar";
363363
}
364-
requestHead.append(
365-
"Content-Type: application/x-www-form-urlencoded")
366-
.append(CRLF);
364+
requestHead.append(SimpleHttpClient.HTTP_HEADER_CONTENT_TYPE_FORM_URL_ENCODING);
367365
// calculate post data length
368366
String len = Integer.toString(requestTail.length());
369367
requestHead.append("Content-length: ").append(len).append(CRLF);

test/org/apache/catalina/connector/TestRequest.java

Lines changed: 68 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
import org.junit.Test;
4646

4747
import org.apache.catalina.Context;
48+
import org.apache.catalina.Globals;
4849
import org.apache.catalina.authenticator.BasicAuthenticator;
4950
import org.apache.catalina.filters.FailedRequestFilter;
5051
import org.apache.catalina.startup.SimpleHttpClient;
@@ -54,6 +55,7 @@
5455
import org.apache.tomcat.unittest.TesterRequest;
5556
import org.apache.tomcat.util.buf.ByteChunk;
5657
import org.apache.tomcat.util.buf.EncodedSolidusHandling;
58+
import org.apache.tomcat.util.buf.StringUtils;
5759
import org.apache.tomcat.util.descriptor.web.FilterDef;
5860
import org.apache.tomcat.util.descriptor.web.FilterMap;
5961
import org.apache.tomcat.util.descriptor.web.LoginConfig;
@@ -208,7 +210,7 @@ private Exception doRequest(int postLimit, boolean ucChunkedHead) {
208210
request[0] =
209211
"POST http://localhost:8080/test HTTP/1.1" + CRLF +
210212
"Host: localhost:8080" + CRLF +
211-
"content-type: application/x-www-form-urlencoded" + CRLF +
213+
SimpleHttpClient.HTTP_HEADER_CONTENT_TYPE_FORM_URL_ENCODING +
212214
"Transfer-Encoding: CHUNKED" + CRLF +
213215
"Connection: close" + CRLF +
214216
CRLF +
@@ -218,7 +220,7 @@ private Exception doRequest(int postLimit, boolean ucChunkedHead) {
218220
request[0] =
219221
"POST http://localhost:8080/test HTTP/1.1" + CRLF +
220222
"Host: localhost:8080" + CRLF +
221-
"content-type: application/x-www-form-urlencoded" + CRLF +
223+
SimpleHttpClient.HTTP_HEADER_CONTENT_TYPE_FORM_URL_ENCODING +
222224
"Transfer-Encoding: chunked" + CRLF +
223225
"Connection: close" + CRLF +
224226
CRLF +
@@ -420,7 +422,7 @@ public void testBug48692() {
420422
// Make sure POST works properly
421423
//
422424
// POST with separate GET and POST parameters
423-
client.doRequest("POST", "foo=bar", "application/x-www-form-urlencoded", "bar=baz", true);
425+
client.doRequest("POST", "foo=bar", Globals.CONTENT_TYPE_FORM_URL_ENCODING, "bar=baz", true);
424426

425427
Assert.assertTrue("Non-200 response for POST request",
426428
client.isResponse200());
@@ -431,7 +433,7 @@ public void testBug48692() {
431433
client.reset();
432434

433435
// POST with overlapping GET and POST parameters
434-
client.doRequest("POST", "foo=bar&bar=foo", "application/x-www-form-urlencoded", "bar=baz&foo=baz", true);
436+
client.doRequest("POST", "foo=bar&bar=foo", Globals.CONTENT_TYPE_FORM_URL_ENCODING, "bar=baz&foo=baz", true);
435437

436438
Assert.assertTrue("Non-200 response for POST request",
437439
client.isResponse200());
@@ -442,7 +444,7 @@ public void testBug48692() {
442444
client.reset();
443445

444446
// PUT without POST-style parsing
445-
client.doRequest("PUT", "foo=bar&bar=foo", "application/x-www-form-urlencoded", "bar=baz&foo=baz", false);
447+
client.doRequest("PUT", "foo=bar&bar=foo", Globals.CONTENT_TYPE_FORM_URL_ENCODING, "bar=baz&foo=baz", false);
446448

447449
Assert.assertTrue("Non-200 response for PUT/noparse request",
448450
client.isResponse200());
@@ -453,7 +455,7 @@ public void testBug48692() {
453455
client.reset();
454456

455457
// PUT with POST-style parsing
456-
client.doRequest("PUT", "foo=bar&bar=foo", "application/x-www-form-urlencoded", "bar=baz&foo=baz", true);
458+
client.doRequest("PUT", "foo=bar&bar=foo", Globals.CONTENT_TYPE_FORM_URL_ENCODING, "bar=baz&foo=baz", true);
457459

458460
Assert.assertTrue("Non-200 response for PUT request",
459461
client.isResponse200());
@@ -462,14 +464,6 @@ public void testBug48692() {
462464
client.getResponseBody());
463465

464466
client.reset();
465-
466-
/*
467-
private Exception doRequest(String method,
468-
String queryString,
469-
String contentType,
470-
String requestBody,
471-
boolean allowBody) {
472-
*/
473467
}
474468

475469
@Test
@@ -963,4 +957,64 @@ protected void doPost(HttpServletRequest req, HttpServletResponse resp)
963957
req.getReader();
964958
}
965959
}
960+
961+
962+
/*
963+
* https://bz.apache.org/bugzilla/show_bug.cgi?id=69442
964+
*/
965+
@Test
966+
public void testTestParameterMediaTypeLowerCase() throws Exception {
967+
// toLowerCase() is unnecessary but keep it in case the constant is changed in the future
968+
doTestParameterMediaTypeCase(Globals.CONTENT_TYPE_FORM_URL_ENCODING.toLowerCase(Locale.ENGLISH));
969+
}
970+
971+
972+
/*
973+
* https://bz.apache.org/bugzilla/show_bug.cgi?id=69442
974+
*/
975+
@Test
976+
public void testTestParameterMediaTypeUpperCase() throws Exception {
977+
doTestParameterMediaTypeCase(Globals.CONTENT_TYPE_FORM_URL_ENCODING.toUpperCase(Locale.ENGLISH));
978+
}
979+
980+
981+
private void doTestParameterMediaTypeCase(String contentType) throws Exception {
982+
// Setup Tomcat instance
983+
Tomcat tomcat = getTomcatInstance();
984+
985+
// No file system docBase required
986+
Context ctx = getProgrammaticRootContext();
987+
988+
Tomcat.addServlet(ctx, "servlet", new Bug69442Servlet());
989+
ctx.addServletMappingDecoded("/", "servlet");
990+
991+
tomcat.start();
992+
993+
ByteChunk bc = new ByteChunk();
994+
Map<String,List<String>> reqHeaders = new HashMap<>();
995+
reqHeaders.put("Content-Type", Arrays.asList(contentType));
996+
postUrl("a=b&c=d".getBytes(), "http://localhost:" + getPort() + "/", bc, reqHeaders, null);
997+
String responseBody = bc.toString();
998+
Assert.assertTrue(responseBody, responseBody.contains("a=b"));
999+
Assert.assertTrue(responseBody, responseBody.contains("c=d"));
1000+
}
1001+
1002+
1003+
private static class Bug69442Servlet extends HttpServlet {
1004+
1005+
private static final long serialVersionUID = 1L;
1006+
1007+
@Override
1008+
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
1009+
resp.setContentType("text/plain");
1010+
resp.setCharacterEncoding(StandardCharsets.UTF_8.name());
1011+
PrintWriter pw = resp.getWriter();
1012+
Enumeration<String> names = req.getParameterNames();
1013+
while (names.hasMoreElements()) {
1014+
String name = names.nextElement();
1015+
String[] values = req.getParameterValues(name);
1016+
pw.println(name + "=" + StringUtils.join(values));
1017+
}
1018+
}
1019+
}
9661020
}

test/org/apache/catalina/startup/ExpectationClient.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ public void doRequestHeaders() throws Exception {
2828
requestHeaders.append("POST /echo HTTP/1.1").append(CRLF);
2929
requestHeaders.append("Host: localhost").append(CRLF);
3030
requestHeaders.append("Expect: 100-continue").append(CRLF);
31-
requestHeaders.append("Content-Type: application/x-www-form-urlencoded").append(CRLF);
31+
requestHeaders.append(SimpleHttpClient.HTTP_HEADER_CONTENT_TYPE_FORM_URL_ENCODING);
3232
String len = Integer.toString(BODY.length());
3333
requestHeaders.append("Content-length: ").append(len).append(CRLF);
3434
requestHeaders.append(CRLF);

test/org/apache/catalina/startup/SimpleHttpClient.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@
3737

3838
import org.junit.Assert;
3939

40+
import org.apache.catalina.Globals;
41+
4042
/**
4143
* Simple client for unit testing. It isn't robust, it isn't secure and
4244
* should not be used as the basis for production code. Its only purpose
@@ -50,6 +52,9 @@ public abstract class SimpleHttpClient {
5052
public static final String LF = "\n";
5153
public static final String CRLF = CR + LF;
5254

55+
public static final String HTTP_HEADER_CONTENT_TYPE_FORM_URL_ENCODING =
56+
"Content-Type: " + Globals.CONTENT_TYPE_FORM_URL_ENCODING + CRLF;
57+
5358
public static final String INFO_100 = "HTTP/1.1 100 ";
5459
public static final String OK_200 = "HTTP/1.1 200 ";
5560
public static final String CREATED_201 = "HTTP/1.1 201 ";

0 commit comments

Comments
 (0)