View | Details | Raw Unified | Return to bug 60411
Collapse All | Expand All

(-)java/org/apache/catalina/valves/rewrite/RewriteRule.java (-12 / +12 lines)
Lines 294-311 Link Here
294
    /**
294
    /**
295
     *  Prefix Substitution with http://thishost[:thisport]/ (which makes the
295
     *  Prefix Substitution with http://thishost[:thisport]/ (which makes the
296
     *  new URL a URI) to force a external redirection. If no code is given
296
     *  new URL a URI) to force a external redirection. If no code is given
297
     *  a HTTP response of 302 (MOVED TEMPORARILY) is used. If you want to
297
     *  an HTTP response of 302 (FOUND, previously MOVED TEMPORARILY) is used.
298
     *  use other response codes in the range 300-400 just specify them as
298
     *  If you want to  use other response codes in the range 300-399 just
299
     *  a number or use one of the following symbolic names: temp (default),
299
     *  specify them as a number or use one of the following symbolic names:
300
     *  permanent, seeother. Use it for rules which should canonicalize the
300
     *  temp (default), permanent, seeother. Use it for rules which should
301
     *  URL and give it back to the client, e.g., translate ``/~'' into ``/u/''
301
     *  canonicalize the URL and give it back to the client, e.g., translate
302
     *  or always append a slash to /u/user, etc. Note: When you use this flag,
302
     *  ``/~'' into ``/u/'' or always append a slash to /u/user, etc. Note:
303
     *  make sure that the substitution field is a valid URL! If not, you are
303
     *  When you use this flag, make sure that the substitution field is a
304
     *  redirecting to an invalid location! And remember that this flag itself
304
     *  valid URL! If not, you are redirecting to an invalid location!
305
     *  only prefixes the URL with http://thishost[:thisport]/, rewriting
305
     *  And remember that this flag itself only prefixes the URL with
306
     *  continues. Usually you also want to stop and do the redirection
306
     *  http://thishost[:thisport]/, rewriting continues. Usually you also
307
     *  immediately. To stop the rewriting you also have to provide the
307
     *  want to stop and do the redirection immediately. To stop the
308
     *  'L' flag.
308
     *  rewriting you also have to provide the 'L' flag.
309
     */
309
     */
310
    protected boolean redirect = false;
310
    protected boolean redirect = false;
311
    protected int redirectCode = 0;
311
    protected int redirectCode = 0;
(-)java/org/apache/catalina/valves/rewrite/RewriteValve.java (-11 / +23 lines)
Lines 804-821 Link Here
804
        } else if (flag.startsWith("qsappend") || flag.startsWith("QSA")) {
804
        } else if (flag.startsWith("qsappend") || flag.startsWith("QSA")) {
805
            rule.setQsappend(true);
805
            rule.setQsappend(true);
806
        } else if (flag.startsWith("redirect") || flag.startsWith("R")) {
806
        } else if (flag.startsWith("redirect") || flag.startsWith("R")) {
807
            if (flag.startsWith("redirect=")) {
807
            rule.setRedirect(true);
808
                flag = flag.substring("redirect=".length());
808
            int redirectCode = HttpServletResponse.SC_FOUND;
809
                rule.setRedirect(true);
809
            if (flag.startsWith("redirect=") || flag.startsWith("R=")) {
810
                rule.setRedirectCode(Integer.parseInt(flag));
810
                if (flag.startsWith("redirect=")) {
811
            } else if (flag.startsWith("R=")) {
811
                    flag = flag.substring("redirect=".length());
812
                flag = flag.substring("R=".length());
812
                } else if (flag.startsWith("R=")) {
813
                rule.setRedirect(true);
813
                    flag = flag.substring("R=".length());
814
                rule.setRedirectCode(Integer.parseInt(flag));
814
                }
815
            } else {
815
                switch(flag) {
816
                rule.setRedirect(true);
816
                    case "temp":
817
                rule.setRedirectCode(HttpServletResponse.SC_FOUND);
817
                        redirectCode = HttpServletResponse.SC_FOUND;
818
                        break;
819
                    case "permanent":
820
                        redirectCode = HttpServletResponse.SC_MOVED_PERMANENTLY;
821
                        break;
822
                    case "seeother":
823
                        redirectCode = HttpServletResponse.SC_SEE_OTHER;
824
                        break;
825
                    default:
826
                        redirectCode = Integer.parseInt(flag);
827
                        break;
828
                }
818
            }
829
            }
830
            rule.setRedirectCode(redirectCode);
819
        } else if (flag.startsWith("skip") || flag.startsWith("S")) {
831
        } else if (flag.startsWith("skip") || flag.startsWith("S")) {
820
            if (flag.startsWith("skip=")) {
832
            if (flag.startsWith("skip=")) {
821
                flag = flag.substring("skip=".length());
833
                flag = flag.substring("skip=".length());
(-)test/org/apache/catalina/valves/rewrite/TestRewriteValve.java (+107 lines)
Lines 16-22 Link Here
16
 */
16
 */
17
package org.apache.catalina.valves.rewrite;
17
package org.apache.catalina.valves.rewrite;
18
18
19
import java.net.HttpURLConnection;
19
import java.nio.charset.StandardCharsets;
20
import java.nio.charset.StandardCharsets;
21
import java.util.List;
22
import java.util.HashMap;
23
import java.util.Map;
20
24
21
import org.junit.Assert;
25
import org.junit.Assert;
22
import org.junit.Test;
26
import org.junit.Test;
Lines 25-30 Link Here
25
import org.apache.catalina.servlets.DefaultServlet;
29
import org.apache.catalina.servlets.DefaultServlet;
26
import org.apache.catalina.startup.Tomcat;
30
import org.apache.catalina.startup.Tomcat;
27
import org.apache.catalina.startup.TomcatBaseTest;
31
import org.apache.catalina.startup.TomcatBaseTest;
32
import org.apache.catalina.startup.TesterServlet;
28
import org.apache.tomcat.util.buf.ByteChunk;
33
import org.apache.tomcat.util.buf.ByteChunk;
29
34
30
/*
35
/*
Lines 477-484 Link Here
477
        doTestRewrite("RewriteRule ^/b(.*) http://%{HTTP_HOST}:%{SERVER_PORT}/a$1 [R]",
482
        doTestRewrite("RewriteRule ^/b(.*) http://%{HTTP_HOST}:%{SERVER_PORT}/a$1 [R]",
478
                "/b/%255A", "/a/%255A");
483
                "/b/%255A", "/a/%255A");
479
    }
484
    }
485
	
486
	@Test
487
	public void testDefaultRedirect() throws Exception {
488
		 // Disable the following of redirects for this test only
489
        boolean originalValue = HttpURLConnection.getFollowRedirects();
490
        HttpURLConnection.setFollowRedirects(false);
491
		try {
492
		    doTestRedirect("RewriteRule ^/from/a$ /to/b [R]", "/redirect/from/a", "/redirect/to/b",
493
			    302);
494
	    } finally {
495
            HttpURLConnection.setFollowRedirects(originalValue);
496
        }
497
    }
498
	
499
	@Test
500
	public void testTempRedirect() throws Exception {
501
		 // Disable the following of redirects for this test only
502
        boolean originalValue = HttpURLConnection.getFollowRedirects();
503
        HttpURLConnection.setFollowRedirects(false);
504
		try {
505
		    doTestRedirect("RewriteRule ^/from/a$ /to/b [R=temp]", "/redirect/from/a", "/redirect/to/b",
506
			    302);
507
	    } finally {
508
            HttpURLConnection.setFollowRedirects(originalValue);
509
        }
510
    }
480
511
512
	@Test
513
	public void testPermanentRedirect() throws Exception {
514
		 // Disable the following of redirects for this test only
515
        boolean originalValue = HttpURLConnection.getFollowRedirects();
516
        HttpURLConnection.setFollowRedirects(false);
517
		try {
518
		    doTestRedirect("RewriteRule ^/from/a$ /to/b [R=permanent]", "/redirect/from/a", "/redirect/to/b",
519
			    301);
520
	    } finally {
521
            HttpURLConnection.setFollowRedirects(originalValue);
522
        }
523
    }
481
524
525
	@Test
526
	public void testSeeotherRedirect() throws Exception {
527
		 // Disable the following of redirects for this test only
528
        boolean originalValue = HttpURLConnection.getFollowRedirects();
529
        HttpURLConnection.setFollowRedirects(false);
530
		try {
531
		    doTestRedirect("RewriteRule ^/from/a$ /to/b [R=seeother]", "/redirect/from/a", "/redirect/to/b",
532
			    303);
533
	    } finally {
534
            HttpURLConnection.setFollowRedirects(originalValue);
535
        }
536
    }
537
538
	@Test
539
	public void test307Redirect() throws Exception {
540
		 // Disable the following of redirects for this test only
541
        boolean originalValue = HttpURLConnection.getFollowRedirects();
542
        HttpURLConnection.setFollowRedirects(false);
543
		try {
544
		    doTestRedirect("RewriteRule ^/from/a$ /to/b [R=307]", "/redirect/from/a", "/redirect/to/b",
545
			    307);
546
	    } finally {
547
            HttpURLConnection.setFollowRedirects(originalValue);
548
        }
549
    }
550
551
482
    private void doTestRewrite(String config, String request, String expectedURI) throws Exception {
552
    private void doTestRewrite(String config, String request, String expectedURI) throws Exception {
483
        doTestRewrite(config, request, expectedURI, null);
553
        doTestRewrite(config, request, expectedURI, null);
484
    }
554
    }
Lines 536-539 Link Here
536
            }
606
            }
537
        }
607
        }
538
    }
608
    }
609
610
	private void doTestRedirect(String config, String request, String expectedURI,
611
	    int expectedStatusCode) throws Exception {
612
613
        Tomcat tomcat = getTomcatInstance();
614
615
        // No file system docBase required
616
        Context ctx = tomcat.addContext("redirect", null);
617
618
        RewriteValve rewriteValve = new RewriteValve();
619
        ctx.getPipeline().addValve(rewriteValve);
620
621
        rewriteValve.setConfiguration(config);
622
623
        Tomcat.addServlet(ctx, "tester", new TesterServlet());
624
        ctx.addServletMappingDecoded("/from/a", "tester");
625
        ctx.addServletMappingDecoded("/to/b", "tester");
626
627
        tomcat.start();
628
629
        ByteChunk res = new ByteChunk();
630
		Map<String, List<String>> resHead = new HashMap<>();
631
        int rc = getUrl("http://localhost:" + getPort() + request, res, null, resHead);
632
        res.setCharset(StandardCharsets.UTF_8);
633
634
        if (expectedURI == null) {
635
            // Rewrite is expected to fail. Probably because invalid characters
636
            // were written into the request target
637
            Assert.assertEquals(400, rc);
638
        } else {
639
            List<String> locations = resHead.get("Location");
640
			Assert.assertFalse(locations.isEmpty());
641
			String redirectURI = locations.get(0);
642
            Assert.assertEquals(expectedURI, redirectURI);
643
			Assert.assertEquals(expectedStatusCode, rc);
644
        }
645
    }
539
}
646
}
(-)webapps/docs/rewrite.xml (-2 / +2 lines)
Lines 680-688 Link Here
680
          Prefix <em>Substitution</em> with
680
          Prefix <em>Substitution</em> with
681
          <code>http://thishost[:thisport]/</code> (which makes the
681
          <code>http://thishost[:thisport]/</code> (which makes the
682
          new URL a URI) to force a external redirection. If no
682
          new URL a URI) to force a external redirection. If no
683
          <em>code</em> is given, a HTTP response of 302 (MOVED
683
          <em>code</em> is given, a HTTP response of 302 (FOUND, previously MOVED
684
          TEMPORARILY) will be returned. If you want to use other response
684
          TEMPORARILY) will be returned. If you want to use other response
685
          codes in the range 300-400, simply specify the appropriate number
685
          codes in the range 300-399, simply specify the appropriate number
686
          or use one of the following symbolic names:
686
          or use one of the following symbolic names:
687
          <code>temp</code> (default), <code>permanent</code>,
687
          <code>temp</code> (default), <code>permanent</code>,
688
          <code>seeother</code>. Use this for rules to
688
          <code>seeother</code>. Use this for rules to

Return to bug 60411