ttomcat-1778514358873.zip-extract/apache-tomcat-11.0.18-src/test/org/apache/catalina/valves/rewrite/TestRewriteValve.java

Path
ttomcat-1778514358873.zip-extract/apache-tomcat-11.0.18-src/test/org/apache/catalina/valves/rewrite/TestRewriteValve.java
Status
scanned
Type
file
Name
TestRewriteValve.java
Extension
.java
Programming language
Java
Mime type
text/plain
File type
ASCII text, with CRLF line terminators
Tag

      
    
Rootfs path

      
    
Size
41959 (41.0 KB)
MD5
4f29ddbca90cb8c2b783b127da90688d
SHA1
6d9f482e374b70bd119df4ef732e1f2268390b36
SHA256
c558c5ecd2794e15e208f536d4b0c08318789fa1ad112fc668654715d70591c3
SHA512

      
    
SHA1_git
a5d17aba5cb533cc3d34d57899c76874ef0b739f
Is binary

      
    
Is text
True
Is archive

      
    
Is media

      
    
Is legal

      
    
Is manifest

      
    
Is readme

      
    
Is top level

      
    
Is key file

      
    
TestRewriteValve.java | 41.0 KB |

/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.catalina.valves.rewrite; import java.io.File; import java.io.IOException; import java.io.PrintWriter; import java.net.HttpURLConnection; import java.net.URLDecoder; import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import jakarta.servlet.ServletException; import jakarta.servlet.http.Cookie; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import org.junit.Assert; import org.junit.Test; import org.apache.catalina.Context; import org.apache.catalina.connector.Request; import org.apache.catalina.connector.Response; import org.apache.catalina.servlets.DefaultServlet; import org.apache.catalina.startup.TesterServlet; import org.apache.catalina.startup.Tomcat; import org.apache.catalina.startup.TomcatBaseTest; import org.apache.catalina.valves.ValveBase; import org.apache.tomcat.util.buf.ByteChunk; import org.apache.tomcat.util.http.Method; /* * Implementation note: * * A number of these tests involve the rewrite valve returning an HTTP Location * header that include un-encoded UTF-8 bytes. How the HTTP client handles these * depends on the default character encoding configured for the JVM running the * test. The tests expect the client to be configured with UTF-8 as the default * encoding. Use of any other encoding is likely to lead to test failures. */ public class TestRewriteValve extends TomcatBaseTest { @Test public void testNoRewrite() throws Exception { doTestRewrite("", "/a/%255A", "/a/%255A"); } @Test public void testBackslashPercentSign() throws Exception { doTestRewrite("RewriteRule ^(.*) /a/\\%5A", "/", "/a/%5A"); } @Test public void testNoopRewrite() throws Exception { doTestRewrite("RewriteRule ^(.*) $1", "/a/%255A", "/a/%255A"); } @Test public void testNoopValveSkipRewrite() throws Exception { doTestRewrite("RewriteRule ^(.*) $1 [VS]", "/a/%255A", "/a/%255A", null, null, true); } @Test public void testPathRewrite() throws Exception { doTestRewrite("RewriteRule ^/b(.*) /a$1", "/b/%255A", "/a/%255A"); } @Test public void testNonNormalizedPathRewrite() throws Exception { doTestRewrite("RewriteRule ^/b/(.*) /b/../a/$1", "/b/%255A", "/b/../a/%255A"); } // BZ 57863 @Test public void testRewriteMap01() throws Exception { doTestRewrite("RewriteMap mapa org.apache.catalina.valves.rewrite.TesterRewriteMapA " + "RewriteRule /b/(.*).html$ /c/${mapa:$1}", "/b/a.html", "/c/aa"); } @Test public void testRewriteMap02() throws Exception { doTestRewrite("RewriteMap mapa org.apache.catalina.valves.rewrite.TesterRewriteMapA " + "RewriteRule /b/(.*).html$ /c/${mapa:$1|dd}", "/b/x.html", "/c/dd"); } // BZ 62667 @Test public void testRewriteMap03() throws Exception { doTestRewrite("RewriteMap mapa org.apache.catalina.valves.rewrite.TesterRewriteMapA " + "RewriteRule /b/(.*).html$ /c/${mapa:$1|d$1d}", "/b/x.html", "/c/dxd"); } @Test public void testRewriteMap04() throws Exception { doTestRewrite("RewriteMap mapa org.apache.catalina.valves.rewrite.TesterRewriteMapA " + "RewriteRule /b/(.*).html$ /c/${mapa:a$1|dd}", "/b/a.html", "/c/aaaa"); } @Test public void testRewriteMap05() throws Exception { doTestRewrite("RewriteMap mapa org.apache.catalina.valves.rewrite.TesterRewriteMapA " + "RewriteRule /b/.* /c/${mapa:a}", "/b/a.html", "/c/aa"); } @Test public void testRewriteMap06() throws Exception { doTestRewrite("RewriteMap mapa org.apache.catalina.valves.rewrite.TesterRewriteMapA " + "RewriteRule /b/.* /c/${mapa:${mapa:a}}", "/b/a.html", "/c/aaaa"); } @Test public void testRewriteMap07() throws Exception { doTestRewrite("RewriteMap mapa org.apache.catalina.valves.rewrite.TesterRewriteMapA foo bar " + "RewriteRule /b/.* /c/${mapa:${mapa:a}}", "/b/a.html", "/c/aaaa"); } @Test public void testRewriteMap08() throws Exception { doTestRewrite("RewriteMap lc int:tolower " + "RewriteRule ^(.*) ${lc:$1}", "/C/AaA", "/c/aaa"); } @Test public void testRewriteMap09() throws Exception { doTestRewrite("RewriteMap lc int:toupper " + "RewriteRule ^(.*) ${lc:$1}", "/w/aAa", "/W/AAA"); } @Test public void testRewriteMap10() throws Exception { doTestRewrite("RewriteMap lc int:escape " + "RewriteRule ^(.*) ${lc:$1}", "/c/a%20aa", "/c/a%20aa"); } @Test public void testRewriteMap11() throws Exception { doTestRewrite("RewriteMap lc int:unescape " + "RewriteRule ^(.*) ${lc:$1}", "/c/a%2520aa", "/c/a%20aa"); } private static String getTestConfDirectory() { File f = new File("test/conf"); return f.getAbsolutePath() + File.separator; } @Test public void testRewriteMap12() throws Exception { doTestRewrite("RewriteMap mapb txt:" + getTestConfDirectory() + "TesterRewriteMapB.txt " + "RewriteRule /b/(.*).html$ /c/${mapb:$1}", "/b/a.html", "/c/aa"); } @Test public void testRewriteMap13() throws Exception { doTestRewrite("RewriteMap mapb txt:" + getTestConfDirectory() + "TesterRewriteMapB.txt " + "RewriteRule /b/(.*).html$ /c/${mapb:$1|dd}", "/b/x.html", "/c/dd"); } // BZ 62667 @Test public void testRewriteMap14() throws Exception { doTestRewrite("RewriteMap mapb txt:" + getTestConfDirectory() + "TesterRewriteMapB.txt " + "RewriteRule /b/(.*).html$ /c/${mapb:$1|d$1d}", "/b/x.html", "/c/dxd"); } @Test public void testRewriteMap15() throws Exception { doTestRewrite("RewriteMap mapb txt:" + getTestConfDirectory() + "TesterRewriteMapB.txt " + "RewriteRule /b/(.*).html$ /c/${mapb:a$1|dd}", "/b/a.html", "/c/aaaa"); } @Test public void testRewriteMap16() throws Exception { doTestRewrite("RewriteMap mapb txt:" + getTestConfDirectory() + "TesterRewriteMapB.txt " + "RewriteRule /b/.* /c/${mapb:a}", "/b/a.html", "/c/aa"); } @Test public void testRewriteMap17() throws Exception { doTestRewrite("RewriteMap mapb txt:" + getTestConfDirectory() + "TesterRewriteMapB.txt " + "RewriteRule /b/.* /c/${mapb:${mapb:a}}", "/b/a.html", "/c/aaaa"); } @Test public void testRewriteMap18() throws Exception { doTestRewrite("RewriteMap mapb txt:" + getTestConfDirectory() + "TesterRewriteMapB.txt " + "RewriteRule /b/.* /c/${mapb:${mapb:a}}", "/b/a.html", "/c/aaaa"); } @Test(expected = IllegalArgumentException.class) public void testRewriteMap19() throws Exception { doTestRewrite("RewriteMap mapb txt:" + getTestConfDirectory() + "TesterRewriteMapB.txt first " + "RewriteRule /b/(.*).html$ /c/${mapb:$1}", "/b/aa.html", "/c/aaaa"); } @Test(expected = IllegalArgumentException.class) public void testRewriteMap20() throws Exception { doTestRewrite("RewriteMap mapb txt:" + getTestConfDirectory() + "TesterRewriteMapB.txt first second " + "RewriteRule /b/(.*).html$ /c/${mapb:$1}", "/b/aa.html", "/c/aaaa"); } @Test public void testRewriteMap21() throws Exception { doTestRewrite("RewriteMap mapb rnd:" + getTestConfDirectory() + "TesterRewriteMapC.txt " + "RewriteRule /b/(.*).html$ /c/${mapb:$1}", "/b/a.html", "/c/aa"); } // This test should succeed 50% of the runs as it depends on a random choice public void testRewriteMap22() throws Exception { doTestRewrite("RewriteMap mapb rnd:" + getTestConfDirectory() + "TesterRewriteMapC.txt " + "RewriteRule /b/(.*).html$ /c/${mapb:$1}", "/b/b.html", "/c/bb"); } @Test public void testRewriteMap23() throws Exception { doTestRewrite("RewriteMap mapb rnd:" + getTestConfDirectory() + "TesterRewriteMapC.txt " + "RewriteRule /b/(.*).html$ /c/${mapb:$1}", "/b/aa.html", "/c/aaaa"); } @Test(expected = IllegalArgumentException.class) public void testRewriteMap24() throws Exception { doTestRewrite("RewriteMap mapb rnd:" + getTestConfDirectory() + "TesterRewriteMapC.txt first " + "RewriteRule /b/(.*).html$ /c/${mapb:$1}", "/b/aa.html", "/c/aaaa"); } @Test(expected = IllegalArgumentException.class) public void testRewriteMap25() throws Exception { doTestRewrite("RewriteMap mapb rnd:" + getTestConfDirectory() + "TesterRewriteMapC.txt first second " + "RewriteRule /b/(.*).html$ /c/${mapb:$1}", "/b/aa.html", "/c/aaaa"); } @Test public void testRewriteServerVar() throws Exception { doTestRewrite("RewriteRule /b/(.*).html$ /c%{SERVLET_PATH}", "/b/x.html", "/c/b/x.html"); } @Test public void testRewriteEnvVarAndServerVar() throws Exception { System.setProperty("some_variable", "something"); doTestRewrite("RewriteRule /b/(.*).html$ /c/%{ENV:some_variable}%{SERVLET_PATH}", "/b/x.html", "/c/something/b/x.html"); } @Test public void testRewriteServerVarAndEnvVar() throws Exception { System.setProperty("some_variable", "something"); doTestRewrite("RewriteRule /b/(.*).html$ /c%{SERVLET_PATH}/%{ENV:some_variable}", "/b/x.html", "/c/b/x.html/something"); } @Test public void testRewriteMissingCurlyBraceOnVar() throws Exception { try { doTestRewrite("RewriteRule /b/(.*).html$ /c%_{SERVLET_PATH}", "/b/x.html", "/c"); Assert.fail("IAE expected."); } catch (IllegalArgumentException e) { // expected as %_{ is invalid } } @Test public void testRewriteMissingCurlyBraceOnMapper() throws Exception { try { doTestRewrite("RewriteRule /b/(.*).html$ /c$_{SERVLET_PATH}", "/b/x.html", "/c"); Assert.fail("IAE expected."); } catch (IllegalArgumentException e) { // expected as $_{ is invalid } } // https://bz.apache.org/bugzilla/show_bug.cgi?id=60013 public void testRewriteWithEncoding02() throws Exception { doTestRewrite("RewriteRule ^/b/(.*)$ /c/?param=$1 [L]", "/b/%E5%9C%A8%E7%BA%BF%E6%B5%8B%E8%AF%95", "/c/", "param=\u5728\u7EBF\u6D4B\u8BD5"); } @Test public void testNonAsciiPath() throws Exception { doTestRewrite("RewriteRule ^/b/(.*) /c/$1", "/b/%E5%9C%A8%E7%BA%BF%E6%B5%8B%E8%AF%95", "/c/%E5%9C%A8%E7%BA%BF%E6%B5%8B%E8%AF%95"); } @Test public void testNonAsciiPathRedirect() throws Exception { doTestRewrite("RewriteRule ^/b/(.*) /c/$1 [R]", "/b/%E5%9C%A8%E7%BA%BF%E6%B5%8B%E8%AF%95", "/c/%E5%9C%A8%E7%BA%BF%E6%B5%8B%E8%AF%95"); } @Test public void testQueryStringTargetOnly() throws Exception { doTestRewrite("RewriteRule ^/b/(.*) /c/$1?je=2", "/b/id=1", "/c/id=1", "je=2"); } @Test public void testQueryStringTargetOnlyQSA() throws Exception { doTestRewrite("RewriteRule ^/b/(.*) /c/$1?je=2 [QSA]", "/b/id=1", "/c/id=1", "je=2"); } @Test public void testQueryStringTargetOnlyQSD() throws Exception { doTestRewrite("RewriteRule ^/b/(.*) /c/$1?je=2 [QSD]", "/b/id=1", "/c/id=1", "je=2"); } @Test public void testQueryStringTargetOnlyQSAQSD() throws Exception { doTestRewrite("RewriteRule ^/b/(.*) /c/$1?je=2 [QSA,QSD]", "/b/id=1", "/c/id=1", "je=2"); } @Test public void testQueryStringTargetOnlyQS() throws Exception { doTestRewrite("RewriteRule ^/b/(.*) /c?$1", "/b/id=1", "/c", "id=1"); } @Test public void testQueryStringTargetOnlyQSAQS() throws Exception { doTestRewrite("RewriteRule ^/b/(.*) /c?$1 [QSA]", "/b/id=1", "/c", "id=1"); } @Test public void testQueryStringTargetOnlyQSDQS() throws Exception { doTestRewrite("RewriteRule ^/b/(.*) /c?$1 [QSD]", "/b/id=1", "/c", "id=1"); } @Test public void testQueryStringTargetOnlyQSAQSDQS() throws Exception { doTestRewrite("RewriteRule ^/b/(.*) /c?$1 [QSA,QSD]", "/b/id=1", "/c", "id=1"); } @Test public void testQueryStringSourceOnly() throws Exception { doTestRewrite("RewriteRule ^/b/(.*) /c/$1", "/b/d?id=1", "/c/d", "id=1"); } @Test public void testQueryStringSourceOnlyQSA() throws Exception { doTestRewrite("RewriteRule ^/b/(.*) /c/$1 [QSA]", "/b/d?id=1", "/c/d", "id=1"); } @Test public void testQueryStringSourceOnlyQSD() throws Exception { doTestRewrite("RewriteRule ^/b/(.*) /c/$1 [QSD]", "/b/d?id=1", "/c/d", null); } @Test public void testQueryStringSourceOnlyQSAQSD() throws Exception { doTestRewrite("RewriteRule ^/b/(.*) /c/$1 [QSA,QSD]", "/b/d?id=1", "/c/d", null); } @Test public void testQueryStringSourceAndTarget() throws Exception { doTestRewrite("RewriteRule ^/b/(.*) /c/$1?id=1", "/b/d?je=2", "/c/d", "id=1"); } @Test public void testQueryStringSourceAndTargetQSA() throws Exception { doTestRewrite("RewriteRule ^/b/(.*) /c/$1?id=1 [QSA]", "/b/d?je=2", "/c/d", "id=1&je=2"); } @Test public void testQueryStringSourceAndTargetQSD() throws Exception { doTestRewrite("RewriteRule ^/b/(.*) /c/$1?id=1 [QSD]", "/b/d?je=2", "/c/d", "id=1"); } @Test public void testQueryStringSourceAndTargetQSAQSD() throws Exception { doTestRewrite("RewriteRule ^/b/(.*) /c/$1?id=1 [QSA,QSD]", "/b/d?je=2", "/c/d", "id=1"); } @Test public void testQueryStringEncoded01() throws Exception { doTestRewrite("RewriteCond %{QUERY_STRING} a=(.*) RewriteRule ^/b.*$ /%1 [QSD]", "/b?a=c", "/c", null); } @Test public void testQueryStringEncoded02() throws Exception { doTestRewrite("RewriteCond %{QUERY_STRING} a=(.*) RewriteRule ^/b.*$ /z/%1 [QSD]", "/b?a=%2e%2e%2fc%2faAbB", "/z/%2e%2e%2fc%2faAbB", null); } @Test public void testQueryStringRemove() throws Exception { doTestRewrite("RewriteRule ^/b/(.*) /c/$1?", "/b/d?id=1", "/c/d", null); } @Test public void testQueryStringRemove02() throws Exception { doTestRewrite("RewriteRule ^/b/(.*) /c/$1 [QSD]", "/b/d?id=1", "/c/d", null); } @Test public void testQueryStringRemoveInvalid() throws Exception { doTestRewrite("RewriteRule ^/b/(.*) /c/$1?", "/b/d?=1", "/c/d", null); } @Test public void testQueryStringRemoveInvalid02() throws Exception { doTestRewrite("RewriteRule ^/b/(.*) /c/$1 [QSD]", "/b/d?=1", "/c/d", null); } @Test public void testNonAsciiQueryString() throws Exception { doTestRewrite("RewriteRule ^/b/(.*) /c?$1", "/b/id=%E5%9C%A8%E7%BA%BF%E6%B5%8B%E8%AF%95", "/c", "id=%E5%9C%A8%E7%BA%BF%E6%B5%8B%E8%AF%95"); } @Test public void testNonAsciiQueryStringAndPath() throws Exception { doTestRewrite("RewriteRule ^/b/(.*)/(.*) /c/$1?$2", "/b/%E5%9C%A8%E7%BA%BF/id=%E6%B5%8B%E8%AF%95", "/c/%E5%9C%A8%E7%BA%BF", "id=%E6%B5%8B%E8%AF%95"); } @Test public void testNonAsciiQueryStringAndRedirect() throws Exception { doTestRewrite("RewriteRule ^/b/(.*) /c?$1 [R]", "/b/id=%E5%9C%A8%E7%BA%BF%E6%B5%8B%E8%AF%95", "/c", "id=%E5%9C%A8%E7%BA%BF%E6%B5%8B%E8%AF%95"); } @Test public void testNonAsciiQueryStringAndPathAndRedirect() throws Exception { doTestRewrite("RewriteRule ^/b/(.*)/(.*) /c/$1?$2 [R]", "/b/%E5%9C%A8%E7%BA%BF/id=%E6%B5%8B%E8%AF%95", "/c/%E5%9C%A8%E7%BA%BF", "id=%E6%B5%8B%E8%AF%95"); } @Test public void testNonAsciiQueryStringWithB() throws Exception { doTestRewrite("RewriteRule ^/b/(.*)/id=(.*) /c?filename=$1&id=$2 [B]", "/b/file01/id=%E5%9C%A8%E7%BA%BF%E6%B5%8B%E8%AF%95", "/c", "filename=file01&id=%E5%9C%A8%E7%BA%BF%E6%B5%8B%E8%AF%95"); } @Test public void testNonAsciiQueryStringAndPathAndRedirectWithB() throws Exception { // Note the double encoding of the result (httpd produces the same result) doTestRewrite("RewriteRule ^/b/(.*)/(.*)/id=(.*) /c/$1?filename=$2&id=$3 [B,R]", "/b/%E5%9C%A8%E7%BA%BF/file01/id=%E6%B5%8B%E8%AF%95", "/c/%E5%9C%A8%E7%BA%BF", "filename=file01&id=%E6%B5%8B%E8%AF%95"); } @Test public void testUtf8WithBothQsFlagsNone() throws Exception { // Note %C2%A1 == \u00A1 doTestRewrite("RewriteRule ^/b/(.*)/(.*) /c/\u00A1$1?$2", "/b/%C2%A1/id=%C2%A1?di=%C2%AE", "/c/%C2%A1%C2%A1", "id=%C2%A1"); } @Test public void testUtf8WithBothQsFlagsB() throws Exception { // Note %C2%A1 == \u00A1 doTestRewrite("RewriteRule ^/b/(.*)/(.*) /c/\u00A1$1?$2 [B]", "/b/%C2%A1/id=%C2%A1?di=%C2%AE", "/c/%C2%A1%C2%A1", "id=%C2%A1"); } @Test public void testUtf8WithBothQsFlagsR() throws Exception { // Note %C2%A1 == \u00A1 doTestRewrite("RewriteRule ^/b/(.*)/(.*) /c/\u00A1$1?$2 [R]", "/b/%C2%A1/id=%C2%A1?di=%C2%AE", "/c/%C2%A1%C2%A1", "id=%C2%A1"); } @Test public void testUtf8WithBothQsFlagsRB() throws Exception { // Note %C2%A1 == \u00A1 doTestRewrite("RewriteRule ^/b/(.*)/(.*) /c/\u00A1$1?$2 [R,B]", "/b/%C2%A1/id=%C2%A1?di=%C2%AE", "/c/%C2%A1%C2%A1", "id=%C2%A1"); } @Test public void testUtf8WithBothQsFlagsRNE() throws Exception { // Note %C2%A1 == \u00A1 // Failing to escape the redirect means UTF-8 bytes in the Location // header which will be treated as if they are ISO-8859-1 doTestRewrite("RewriteRule ^/b/(.*)/(.*) /c/\u00A1$1?$2 [R,NE]", "/b/%C2%A1/id=%C2%A1?di=%C2%AE", null); } @Test public void testUtf8WithBothQsFlagsRBNE() throws Exception { // Note %C2%A1 == \u00A1 // Failing to escape the redirect means UTF-8 bytes in the Location // header which will be treated as if they are ISO-8859-1 doTestRewrite("RewriteRule ^/b/(.*)/(.*) /c/\u00A1$1?$2 [R,B,NE]", "/b/%C2%A1/id=%C2%A1?di=%C2%AE", null); } @Test public void testUtf8WithBothQsFlagsBQSA() throws Exception { // Note %C2%A1 == \u00A1 doTestRewrite("RewriteRule ^/b/(.*)/(.*) /c/\u00A1$1?$2 [B,QSA]", "/b/%C2%A1/id=%C2%A1?di=%C2%AE", "/c/%C2%A1%C2%A1", "id=%C2%A1&di=%C2%AE"); } @Test public void testUtf8WithBothQsFlagsRQSA() throws Exception { // Note %C2%A1 == \u00A1 doTestRewrite("RewriteRule ^/b/(.*)/(.*) /c/\u00A1$1?$2 [R,QSA]", "/b/%C2%A1/id=%C2%A1?di=%C2%AE", "/c/%C2%A1%C2%A1", "id=%C2%A1&di=%C2%AE"); } @Test public void testUtf8WithBothQsFlagsRBQSA() throws Exception { // Note %C2%A1 == \u00A1 doTestRewrite("RewriteRule ^/b/(.*)/(.*) /c/\u00A1$1?$2 [R,B,QSA]", "/b/%C2%A1/id=%C2%A1?di=%C2%AE", "/c/%C2%A1%C2%A1", "id=%C2%A1&di=%C2%AE"); } @Test public void testUtf8WithBothQsFlagsRNEQSA() throws Exception { // Note %C2%A1 == \u00A1 // Failing to escape the redirect means UTF-8 bytes in the Location // header which will be treated as if they are ISO-8859-1 doTestRewrite("RewriteRule ^/b/(.*)/(.*) /c/\u00A1$1?$2 [R,NE,QSA]", "/b/%C2%A1/id=%C2%A1?di=%C2%AE", null); } @Test public void testUtf8WithBothQsFlagsRBNEQSA() throws Exception { // Note %C2%A1 == \u00A1 // Failing to escape the redirect means UTF-8 bytes in the Location // header which will be treated as if they are ISO-8859-1 doTestRewrite("RewriteRule ^/b/(.*)/(.*) /c/\u00A1$1?$2 [R,B,NE,QSA]", "/b/%C2%A1/id=%C2%A1?di=%C2%AE", null); } @Test public void testUtf8WithOriginalQsFlagsNone() throws Exception { // Note %C2%A1 == \u00A1 doTestRewrite("RewriteRule ^/b/(.*) /c/\u00A1$1", "/b/%C2%A1?id=%C2%A1", "/c/%C2%A1%C2%A1", "id=%C2%A1"); } @Test public void testUtf8WithOriginalQsFlagsB() throws Exception { // Note %C2%A1 == \u00A1 doTestRewrite("RewriteRule ^/b/(.*) /c/\u00A1$1 [B]", "/b/%C2%A1?id=%C2%A1", "/c/%C2%A1%C2%A1", "id=%C2%A1"); } @Test public void testUtf8WithOriginalQsFlagsR() throws Exception { // Note %C2%A1 == \u00A1 doTestRewrite("RewriteRule ^/b/(.*) /c/\u00A1$1 [R]", "/b/%C2%A1?id=%C2%A1", "/c/%C2%A1%C2%A1", "id=%C2%A1"); } @Test public void testUtf8WithOriginalQsFlagsRB() throws Exception { // Note %C2%A1 == \u00A1 doTestRewrite("RewriteRule ^/b/(.*) /c/\u00A1$1 [R,B]", "/b/%C2%A1?id=%C2%A1", "/c/%C2%A1%C2%A1", "id=%C2%A1"); } @Test public void testUtf8WithOriginalQsFlagsRNE() throws Exception { // Note %C2%A1 == \u00A1 // Failing to escape the redirect means UTF-8 bytes in the Location // header which will be treated as if they are ISO-8859-1 doTestRewrite("RewriteRule ^/b/(.*) /c/\u00A1$1 [R,NE]", "/b/%C2%A1?id=%C2%A1", null); } @Test public void testUtf8WithOriginalQsFlagsRBNE() throws Exception { // Note %C2%A1 == \u00A1 // Failing to escape the redirect means UTF-8 bytes in the Location // header which will be treated as if they are ISO-8859-1 doTestRewrite("RewriteRule ^/b/(.*) /c/\u00A1$1 [R,B,NE]", "/b/%C2%A1?id=%C2%A1", null); } @Test public void testUtf8WithRewriteQsFlagsNone() throws Exception { // Note %C2%A1 == \u00A1 doTestRewrite("RewriteRule ^/b/(.*)/(.*) /c/\u00A1$1?$2", "/b/%C2%A1/id=%C2%A1", "/c/%C2%A1%C2%A1", "id=%C2%A1"); } @Test public void testUtf8WithRewriteQsFlagsB() throws Exception { // Note %C2%A1 == \u00A1 doTestRewrite("RewriteRule ^/b/(.*)/(.*) /c/\u00A1$1?$2 [B]", "/b/%C2%A1/id=%C2%A1", "/c/%C2%A1%C2%A1", "id=%C2%A1"); } @Test public void testUtf8WithRewriteQsFlagsR() throws Exception { // Note %C2%A1 == \u00A1 doTestRewrite("RewriteRule ^/b/(.*)/(.*) /c/\u00A1$1?$2 [R]", "/b/%C2%A1/id=%C2%A1", "/c/%C2%A1%C2%A1", "id=%C2%A1"); } @Test public void testUtf8WithBothQsFlagsQSA() throws Exception { // Note %C2%A1 == \u00A1 doTestRewrite("RewriteRule ^/b/(.*)/(.*) /c/\u00A1$1?$2 [QSA]", "/b/%C2%A1/id=%C2%A1?di=%C2%AE", "/c/%C2%A1%C2%A1", "id=%C2%A1&di=%C2%AE"); } @Test public void testUtf8WithRewriteQsFlagsRB() throws Exception { // Note %C2%A1 == \u00A1 doTestRewrite("RewriteRule ^/b/(.*)/(.*) /c/\u00A1$1?$2 [R,B]", "/b/%C2%A1/id=%C2%A1", "/c/%C2%A1%C2%A1", "id=%C2%A1"); } @Test public void testUtf8WithRewriteQsFlagsRNE() throws Exception { // Note %C2%A1 == \u00A1 // Failing to escape the redirect means UTF-8 bytes in the Location // header which will be treated as if they are ISO-8859-1 doTestRewrite("RewriteRule ^/b/(.*)/(.*) /c/\u00A1$1?$2 [R,NE]", "/b/%C2%A1/id=%C2%A1", null); } @Test public void testUtf8WithRewriteQsFlagsRBNE() throws Exception { // Note %C2%A1 == \u00A1 // Failing to escape the redirect means UTF-8 bytes in the Location // header which will be treated as if they are ISO-8859-1 doTestRewrite("RewriteRule ^/b/(.*)/(.*) /c/\u00A1$1?$2 [R,B,NE]", "/b/%C2%A1/id=%C2%A1", null); } @Test public void testUtf8WithRewriteQsFlagsQSA() throws Exception { // Note %C2%A1 == \u00A1 doTestRewrite("RewriteRule ^/b/(.*)/(.*) /c/\u00A1$1?$2 [QSA]", "/b/%C2%A1/id=%C2%A1", "/c/%C2%A1%C2%A1", "id=%C2%A1"); } @Test public void testUtf8FlagsNone() throws Exception { // Note %C2%A1 == \u00A1 doTestRewrite("RewriteRule ^/b/(.*) /c/\u00A1$1", "/b/%C2%A1", "/c/%C2%A1%C2%A1"); } @Test public void testUtf8FlagsB() throws Exception { // Note %C2%A1 == \u00A1 doTestRewrite("RewriteRule ^/b/(.*) /c/\u00A1$1 [B]", "/b/%C2%A1", "/c/%C2%A1%C2%A1"); } @Test public void testUtf8FlagsR() throws Exception { // Note %C2%A1 == \u00A1 doTestRewrite("RewriteRule ^/b/(.*) /c/\u00A1$1 [R]", "/b/%C2%A1", "/c/%C2%A1%C2%A1"); } @Test public void testUtf8FlagsRB() throws Exception { // Note %C2%A1 == \u00A1 doTestRewrite("RewriteRule ^/b/(.*) /c/\u00A1$1 [R,B]", "/b/%C2%A1", "/c/%C2%A1%C2%A1"); } @Test public void testUtf8FlagsRNE() throws Exception { // Note %C2%A1 == \u00A1 // Failing to escape the redirect means UTF-8 bytes in the Location // header which will be treated as if they are ISO-8859-1 doTestRewrite("RewriteRule ^/b/(.*) /c/\u00A1$1 [R,NE]", "/b/%C2%A1", null); } @Test public void testUtf8FlagsRBNE() throws Exception { // Note %C2%A1 == \u00A1 // Failing to escape the redirect means UTF-8 bytes in the Location // header which will be treated as if they are ISO-8859-1 doTestRewrite("RewriteRule ^/b/(.*) /c/\u00A1$1 [R,B,NE]", "/b/%C2%A1", null); } @Test public void testFlagsNC() throws Exception { // https://bz.apache.org/bugzilla/show_bug.cgi?id=60116 doTestRewrite("RewriteCond %{QUERY_STRING} a=([a-z]*) [NC] " + "RewriteRule .* - [E=X-Test:%1]", "/c?a=aAa", "/c", "a=aAa", "aAa"); } @Test public void testRewriteEmptyHeader() throws Exception { // Disable the following of redirects for this test only boolean originalValue = HttpURLConnection.getFollowRedirects(); HttpURLConnection.setFollowRedirects(false); try { Map<String, List<String>> resHead = new HashMap<>(); Map<String, List<String>> reqHead = new HashMap<>(); reqHead.put("\"\"", Arrays.asList(new String[]{"Test"})); doTestRewriteEx("RewriteCond %{HTTP:} .+ RewriteRule .* - [F]", "", null, null, null, false, resHead, reqHead); } finally { HttpURLConnection.setFollowRedirects(originalValue); } } @Test public void testHostRewrite() throws Exception { // Based on report from users list that ':' was encoded and breaking // the redirect doTestRewrite("RewriteRule ^/b(.*) http://%{HTTP_HOST}:%{SERVER_PORT}/a$1 [R]", "/b/%255A", "/a/%255A"); } @Test public void testDefaultRedirect() throws Exception { doTestRedirect("RewriteRule ^/from/a$ /to/b [R]", "/redirect/from/a", "/redirect/to/b", 302); } @Test public void testTempRedirect() throws Exception { doTestRedirect("RewriteRule ^/from/a$ /to/b [R=temp]", "/redirect/from/a", "/redirect/to/b", 302); } @Test public void testPermanentRedirect() throws Exception { // Disable the following of redirects for this test only boolean originalValue = HttpURLConnection.getFollowRedirects(); HttpURLConnection.setFollowRedirects(false); try { doTestRedirect("RewriteRule ^/from/a$ /to/b [R=permanent]", "/redirect/from/a", "/redirect/to/b", 301); } finally { HttpURLConnection.setFollowRedirects(originalValue); } } @Test public void testSeeotherRedirect() throws Exception { // Disable the following of redirects for this test only boolean originalValue = HttpURLConnection.getFollowRedirects(); HttpURLConnection.setFollowRedirects(false); try { doTestRedirect("RewriteRule ^/from/a$ /to/b [R=seeother]", "/redirect/from/a", "/redirect/to/b", 303); } finally { HttpURLConnection.setFollowRedirects(originalValue); } } @Test public void test307Redirect() throws Exception { // Disable the following of redirects for this test only boolean originalValue = HttpURLConnection.getFollowRedirects(); HttpURLConnection.setFollowRedirects(false); try { doTestRedirect("RewriteRule ^/from/a$ /to/b [R=307]", "/redirect/from/a", "/redirect/to/b", 307); } finally { HttpURLConnection.setFollowRedirects(originalValue); } } @Test public void testBackReferenceRewrite() throws Exception { doTestRewrite("RewriteRule ^/b/(rest)?$ /c/$1", "/b/rest", "/c/rest"); } @Test public void testEmptyBackReferenceRewrite() throws Exception { doTestRewrite("RewriteRule ^/b/(rest)?$ /c/$1", "/b/", "/c/"); } @Test public void testNegativePattern01() throws Exception { doTestRewrite("RewriteRule !^/b/.* /c/", "/b", "/c/"); } @Test public void testNegativePattern02() throws Exception { doTestRewrite("RewriteRule !^/b/.* /c/", "/d/e/f", "/c/"); } @Test public void testNegativePattern03() throws Exception { doTestRewrite("RewriteRule !^/c/.* /b/", "/c/", "/c/"); } @Test public void testNegativePattern04() throws Exception { doTestRewrite("RewriteRule !^/c/.* /b/", "/c/d", "/c/d"); } @Test public void testMultiLine001() throws Exception { doTestRewrite("RewriteRule /dummy /anotherDummy [L] RewriteRule ^/a /c [L]", "/a", "/c"); } @Test public void testMultiLine002() throws Exception { doTestRewrite("RewriteRule /dummy /a RewriteRule /a /c [L]", "/dummy", "/c"); } private void doTestRewrite(String config, String request, String expectedURI) throws Exception { doTestRewrite(config, request, expectedURI, null); } private void doTestRewrite(String config, String request, String expectedURI, String expectedQueryString) throws Exception { doTestRewrite(config, request, expectedURI, expectedQueryString, null); } private void doTestRewrite(String config, String request, String expectedURI, String expectedQueryString, String expectedAttributeValue) throws Exception { doTestRewrite(config, request, expectedURI, expectedQueryString, expectedAttributeValue, false); } private void doTestRewrite(String config, String request, String expectedURI, String expectedQueryString, String expectedAttributeValue, boolean valveSkip) throws Exception { doTestRewriteEx(config, request, expectedURI, expectedQueryString, expectedAttributeValue, valveSkip, null, null); } private void doTestRewriteEx(String config, String request, String expectedURI, String expectedQueryString, String expectedAttributeValue, boolean valveSkip, Map<String, List<String>> resHead, Map<String, List<String>> reqHead ) throws Exception { Tomcat tomcat = getTomcatInstance(); // No file system docBase required Context ctx = getProgrammaticRootContext(); RewriteValve rewriteValve = new RewriteValve(); ctx.getPipeline().addValve(rewriteValve); if (valveSkip) { ctx.getPipeline().addValve(new ValveBase() { @Override public void invoke(Request request, Response response) throws IOException, ServletException { throw new IllegalStateException(); } }); } rewriteValve.setConfiguration(config); Tomcat.addServlet(ctx, "snoop", new SnoopServlet()); ctx.addServletMappingDecoded("/a/Z", "snoop"); ctx.addServletMappingDecoded("/a/%5A", "snoop"); ctx.addServletMappingDecoded("/c/*", "snoop"); ctx.addServletMappingDecoded("/W/*", "snoop"); Tomcat.addServlet(ctx, "default", new DefaultServlet()); ctx.addServletMappingDecoded("/", "default"); tomcat.start(); ByteChunk res = new ByteChunk(); int rc = methodUrl("http://localhost:" + getPort() + request, res, DEFAULT_CLIENT_TIMEOUT_MS, reqHead, resHead, Method.GET, true); res.setCharset(StandardCharsets.UTF_8); if (expectedURI == null) { // Rewrite is expected to fail. Probably because invalid characters // were written into the request target Assert.assertEquals(400, rc); } else { // If there is an expected URI, the request should be successful Assert.assertEquals(200, rc); String body = res.toString(); RequestDescriptor requestDesc = SnoopResult.parse(body); String requestURI = requestDesc.getRequestInfo("REQUEST-URI"); Assert.assertEquals(expectedURI, requestURI); if (expectedQueryString == null) { Assert.assertTrue(requestDesc.getParams().isEmpty()); } else { String queryString = requestDesc.getRequestInfo("REQUEST-QUERY-STRING"); Assert.assertEquals(expectedQueryString, queryString); } if (expectedAttributeValue != null) { String attributeValue = requestDesc.getAttribute("X-Test"); Assert.assertEquals(expectedAttributeValue, attributeValue); } } } private void doTestRedirect(String config, String request, String expectedURI, int expectedStatusCode) throws Exception { Tomcat tomcat = getTomcatInstance(); // No file system docBase required Context ctx = tomcat.addContext("redirect", null); RewriteValve rewriteValve = new RewriteValve(); ctx.getPipeline().addValve(rewriteValve); rewriteValve.setConfiguration(config); Tomcat.addServlet(ctx, "tester", new TesterServlet()); ctx.addServletMappingDecoded("/from/a", "tester"); ctx.addServletMappingDecoded("/to/b", "tester"); tomcat.start(); ByteChunk res = new ByteChunk(); Map<String, List<String>> resHead = new HashMap<>(); int rc = methodUrl("http://localhost:" + getPort() + request, res, DEFAULT_CLIENT_TIMEOUT_MS, null, resHead, Method.GET, false); res.setCharset(StandardCharsets.UTF_8); if (expectedURI == null) { // Rewrite is expected to fail. Probably because invalid characters // were written into the request target Assert.assertEquals(400, rc); } else { List<String> locations = resHead.get("Location"); Assert.assertFalse(locations.isEmpty()); String redirectURI = locations.get(0); Assert.assertEquals(expectedURI, redirectURI); Assert.assertEquals(expectedStatusCode, rc); } } @Test public void testCookie() throws Exception { Tomcat tomcat = getTomcatInstance(); // No file system docBase required Context ctx = tomcat.addContext("redirect", null); CookieTestValve cookieTestValve = new CookieTestValve(); tomcat.getHost().getPipeline().addValve(cookieTestValve); RewriteValve rewriteValve = new RewriteValve(); tomcat.getHost().getPipeline().addValve(rewriteValve); rewriteValve.setConfiguration("RewriteRule ^/source/(.*) /redirect/$1"); Tomcat.addServlet(ctx, "cookieTest", new CookieTestServlet()); ctx.addServletMappingDecoded("/", "cookieTest"); tomcat.start(); Map<String, List<String>> reqHead = new HashMap<>(); reqHead.put("cookie", Arrays.asList("test=data")); ByteChunk res = new ByteChunk(); int rc = methodUrl("http://localhost:" + getPort() + "/source/cookieTest", res, DEFAULT_CLIENT_TIMEOUT_MS, reqHead, null, Method.GET, false); Assert.assertEquals(HttpServletResponse.SC_OK, rc); res.setCharset(StandardCharsets.UTF_8); Assert.assertEquals("PASS", res.toString()); } public static class CookieTestValve extends ValveBase { @Override public void invoke(Request request, Response response) throws IOException, ServletException { Cookie[] cookies = request.getCookies(); if (cookies != null) { for (Cookie cookie : cookies) { if ("test".equals(cookie.getName())) { request.setAttribute("cookieTest", cookie.getValue()); break; } } } getNext().invoke(request, response); } } public static class CookieTestServlet extends HttpServlet { private static final long serialVersionUID = 1L; @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/plain"); resp.setCharacterEncoding("UTF-8"); PrintWriter pw = resp.getWriter(); if (req.getAttribute("cookieTest") != null) { pw.print("PASS"); } else { pw.print("FAIL"); } } } @Test public void testEncodedUriSimple() throws Exception { doTestRewriteWithEncoding("aaa"); } @Test public void testEncodedUriEncodedQuestionMark01() throws Exception { doTestRewriteWithEncoding("a%3fa"); } @Test public void testEncodedUriEncodedQuestionMark02() throws Exception { doTestRewriteWithEncoding("%3faa"); } @Test public void testEncodedUriEncodedQuestionMark03() throws Exception { doTestRewriteWithEncoding("aa%3f"); } @Test public void testEncodedUriEncodedQuestionMarkAndQueryString() throws Exception { doTestRewriteWithEncoding("a%3fa?b=c", "a%3fa", "b=c"); } @Test public void testEncodedUriEncodedSemicolon01() throws Exception { doTestRewriteWithEncoding("a%3ba"); } @Test public void testEncodedUriEncodedSemicolon02() throws Exception { doTestRewriteWithEncoding("%3baa"); } @Test public void testEncodedUriEncodedSemicolon03() throws Exception { doTestRewriteWithEncoding("aa%3b"); } private void doTestRewriteWithEncoding(String segment) throws Exception { doTestRewriteWithEncoding(segment, segment, null); } private void doTestRewriteWithEncoding(String segment, String expectedSegment, String expectedQueryString) throws Exception { Tomcat tomcat = getTomcatInstance(); // No file system docBase required Context ctx = tomcat.addContext("", null); RewriteValve rewriteValve = new RewriteValve(); tomcat.getHost().getPipeline().addValve(rewriteValve); rewriteValve.setConfiguration("RewriteRule ^/source/(.*)$ /target/$1"); Tomcat.addServlet(ctx, "snoop", new SnoopServlet()); ctx.addServletMappingDecoded("/target/*", "snoop"); tomcat.start(); ByteChunk res = new ByteChunk(); int rc = getUrl("http://localhost:" + getPort() + "/source/" + segment, res, false); Assert.assertEquals(HttpServletResponse.SC_OK, rc); res.setCharset(StandardCharsets.UTF_8); String body = res.toString(); Assert.assertTrue(body, body.contains("REQUEST-URI: /target/" + expectedSegment)); Assert.assertTrue(body, body.contains("PATH-INFO: /" + URLDecoder.decode(expectedSegment, StandardCharsets.UTF_8))); Assert.assertTrue(body, body.contains("REQUEST-QUERY-STRING: " + expectedQueryString)); } }
Detected license expression
apache-2.0
Detected license expression (SPDX)
Apache-2.0
Percentage of license text
2.71
Copyrights

      
    
Holders

      
    
Authors

      
    
License detections License expression License expression SPDX
apache_2_0-4bde3f57-78aa-4201-96bf-531cba09e7de apache-2.0 Apache-2.0
URL Start line End line
http://www.apache.org/licenses/LICENSE-2.0 9 9
https://bz.apache.org/bugzilla/show_bug.cgi?id=60013 286 286
https://bz.apache.org/bugzilla/show_bug.cgi?id=60116 713 713