michael@0: // michael@0: // If a response to a non-safe HTTP request-method contains the Location- or michael@0: // Content-Location header, we must make sure to invalidate any cached entry michael@0: // representing the URIs pointed to by either header. RFC 2616 section 13.10 michael@0: // michael@0: // This test uses 3 URIs: "/post" is the target of a POST-request and always michael@0: // redirects (301) to "/redirect". The URIs "/redirect" and "/cl" both counts michael@0: // the number of loads from the server (handler). The response from "/post" michael@0: // always contains the headers "Location: /redirect" and "Content-Location: michael@0: // /cl", whose cached entries are to be invalidated. The tests verifies that michael@0: // "/redirect" and "/cl" are loaded from server the expected number of times. michael@0: // michael@0: michael@0: Cu.import("resource://testing-common/httpd.js"); michael@0: michael@0: var httpserv; michael@0: michael@0: function setupChannel(path) { michael@0: var ios = michael@0: Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService); michael@0: return chan = ios.newChannel(path, "", null) michael@0: .QueryInterface(Ci.nsIHttpChannel); michael@0: } michael@0: michael@0: // Verify that Content-Location-URI has been loaded once, load post_target michael@0: function InitialListener() { } michael@0: InitialListener.prototype = { michael@0: onStartRequest: function(request, context) { }, michael@0: onStopRequest: function(request, context, status) { michael@0: do_check_eq(1, numberOfCLHandlerCalls); michael@0: do_execute_soon(function() { michael@0: var channel = setupChannel("http://localhost:" + michael@0: httpserv.identity.primaryPort + "/post"); michael@0: channel.requestMethod = "POST"; michael@0: channel.asyncOpen(new RedirectingListener(), null); michael@0: }); michael@0: } michael@0: }; michael@0: michael@0: // Verify that Location-URI has been loaded once, reload post_target michael@0: function RedirectingListener() { } michael@0: RedirectingListener.prototype = { michael@0: onStartRequest: function(request, context) { }, michael@0: onStopRequest: function(request, context, status) { michael@0: do_check_eq(1, numberOfHandlerCalls); michael@0: do_execute_soon(function() { michael@0: var channel = setupChannel("http://localhost:" + michael@0: httpserv.identity.primaryPort + "/post"); michael@0: channel.requestMethod = "POST"; michael@0: channel.asyncOpen(new VerifyingListener(), null); michael@0: }); michael@0: } michael@0: }; michael@0: michael@0: // Verify that Location-URI has been loaded twice (cached entry invalidated), michael@0: // reload Content-Location-URI michael@0: function VerifyingListener() { } michael@0: VerifyingListener.prototype = { michael@0: onStartRequest: function(request, context) { }, michael@0: onStopRequest: function(request, context, status) { michael@0: do_check_eq(2, numberOfHandlerCalls); michael@0: var channel = setupChannel("http://localhost:" + michael@0: httpserv.identity.primaryPort + "/cl"); michael@0: channel.asyncOpen(new FinalListener(), null); michael@0: } michael@0: }; michael@0: michael@0: // Verify that Location-URI has been loaded twice (cached entry invalidated), michael@0: // stop test michael@0: function FinalListener() { } michael@0: FinalListener.prototype = { michael@0: onStartRequest: function(request, context) { }, michael@0: onStopRequest: function(request, context, status) { michael@0: do_check_eq(2, numberOfCLHandlerCalls); michael@0: httpserv.stop(do_test_finished); michael@0: } michael@0: }; michael@0: michael@0: function run_test() { michael@0: httpserv = new HttpServer(); michael@0: httpserv.registerPathHandler("/cl", content_location); michael@0: httpserv.registerPathHandler("/post", post_target); michael@0: httpserv.registerPathHandler("/redirect", redirect_target); michael@0: httpserv.start(-1); michael@0: michael@0: // Clear cache michael@0: evict_cache_entries(); michael@0: michael@0: // Load Content-Location URI into cache and start the chain of loads michael@0: var channel = setupChannel("http://localhost:" + michael@0: httpserv.identity.primaryPort + "/cl"); michael@0: channel.asyncOpen(new InitialListener(), null); michael@0: michael@0: do_test_pending(); michael@0: } michael@0: michael@0: var numberOfCLHandlerCalls = 0; michael@0: function content_location(metadata, response) { michael@0: numberOfCLHandlerCalls++; michael@0: response.setStatusLine(metadata.httpVersion, 200, "Ok"); michael@0: response.setHeader("Cache-Control", "max-age=360000", false); michael@0: } michael@0: michael@0: function post_target(metadata, response) { michael@0: response.setStatusLine(metadata.httpVersion, 301, "Moved Permanently"); michael@0: response.setHeader("Location", "/redirect", false); michael@0: response.setHeader("Content-Location", "/cl", false); michael@0: response.setHeader("Cache-Control", "max-age=360000", false); michael@0: } michael@0: michael@0: var numberOfHandlerCalls = 0; michael@0: function redirect_target(metadata, response) { michael@0: numberOfHandlerCalls++; michael@0: response.setStatusLine(metadata.httpVersion, 200, "Ok"); michael@0: response.setHeader("Cache-Control", "max-age=360000", false); michael@0: }