test_redirect_loop.js (2733B)
1 "use strict"; 2 3 const { HttpServer } = ChromeUtils.importESModule( 4 "resource://testing-common/httpd.sys.mjs" 5 ); 6 7 /* 8 * This xpcshell test checks whether we detect infinite HTTP redirect loops. 9 * We check loops with "Location:" set to 1) full URI, 2) relative URI, and 3) 10 * empty Location header (which resolves to a relative link to the original 11 * URI when the original URI ends in a slash). 12 */ 13 14 var httpServer = new HttpServer(); 15 httpServer.start(-1); 16 const PORT = httpServer.identity.primaryPort; 17 18 var fullLoopPath = "/fullLoop"; 19 var fullLoopURI = "http://localhost:" + PORT + fullLoopPath; 20 21 var relativeLoopPath = "/relativeLoop"; 22 var relativeLoopURI = "http://localhost:" + PORT + relativeLoopPath; 23 24 // must use directory-style URI, so empty Location redirects back to self 25 var emptyLoopPath = "/empty/"; 26 var emptyLoopURI = "http://localhost:" + PORT + emptyLoopPath; 27 28 function make_channel(url) { 29 return NetUtil.newChannel({ uri: url, loadUsingSystemPrincipal: true }); 30 } 31 32 function fullLoopHandler(metadata, response) { 33 response.setStatusLine(metadata.httpVersion, 301, "Moved"); 34 response.setHeader( 35 "Location", 36 "http://localhost:" + PORT + "/fullLoop", 37 false 38 ); 39 } 40 41 function relativeLoopHandler(metadata, response) { 42 response.setStatusLine(metadata.httpVersion, 301, "Moved"); 43 response.setHeader("Location", "relativeLoop", false); 44 } 45 46 function emptyLoopHandler(metadata, response) { 47 // Comrades! We must seize power from the petty-bourgeois running dogs of 48 // httpd.js in order to reply with a blank Location header! 49 response.seizePower(); 50 response.write("HTTP/1.0 301 Moved\r\n"); 51 response.write("Location: \r\n"); 52 response.write("Content-Length: 4\r\n"); 53 response.write("\r\n"); 54 response.write("oops"); 55 response.finish(); 56 } 57 58 function testFullLoop(request) { 59 Assert.equal(request.status, Cr.NS_ERROR_REDIRECT_LOOP); 60 61 var chan = make_channel(relativeLoopURI); 62 chan.asyncOpen( 63 new ChannelListener(testRelativeLoop, null, CL_EXPECT_FAILURE) 64 ); 65 } 66 67 function testRelativeLoop(request) { 68 Assert.equal(request.status, Cr.NS_ERROR_REDIRECT_LOOP); 69 70 var chan = make_channel(emptyLoopURI); 71 chan.asyncOpen(new ChannelListener(testEmptyLoop, null, CL_EXPECT_FAILURE)); 72 } 73 74 function testEmptyLoop(request) { 75 Assert.equal(request.status, Cr.NS_ERROR_REDIRECT_LOOP); 76 77 httpServer.stop(do_test_finished); 78 } 79 80 function run_test() { 81 httpServer.registerPathHandler(fullLoopPath, fullLoopHandler); 82 httpServer.registerPathHandler(relativeLoopPath, relativeLoopHandler); 83 httpServer.registerPathHandler(emptyLoopPath, emptyLoopHandler); 84 85 var chan = make_channel(fullLoopURI); 86 chan.asyncOpen(new ChannelListener(testFullLoop, null, CL_EXPECT_FAILURE)); 87 do_test_pending(); 88 }