Mmh
Mmh

Reputation: 417

Tracking the redirection path of URLs in javascript

I am trying to find number of redirections of a requested url in a browser, and if possible want to track the redirected path of that URL through javascript.

For example, if i request 'A' in my browser.assume the redirection flow as A->B->C->D. Means,it gets redirected to 'D'. In this case i need to get three 301 redirect status codes and one 200 ok status code.

I tried the below method in my addon.js(and made an addon to firefox browser).

var req = new XMLHttpRequest();
req.open('GET', document.location, false);
req.send(null);
var headers = req.getAllResponseHeaders().toLowerCase();
var StatusValue = req.status;

It is giving 200 ok (I think it is of final url).

Is it possible to get all 301 redirects of a URL through Javascript.

Thanks,

Upvotes: 4

Views: 3457

Answers (2)

Martin
Martin

Reputation: 1

thx, the code works, but not as expected: A->B->C->D (channel_1 -> channel_2 -> channel_3 -> channel_4).

In my case it will record a redirect chain of A->B->C->D like:

A->B (channel_1 -> channel_2), than B->C (channel_1 -> channel_2), C->D (channel_1 -> channel_2); where channel_1 & channel_2 are random hash numbers.

So I can not link the chain together. that would be the strategy to capture the chain of events (while the pages redirect using, meta-refresh, javascript, http...)?

Upvotes: -1

Wladimir Palant
Wladimir Palant

Reputation: 57681

nsIXMLHttpRequest interface has a member channel (accessible to extensions only) of type nsIChannel. You can assign your own callbacks to its notificationCallbacks property and implement nsIChannelEventSync interface to receive redirection events. Something along these lines:

Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");

var req = new XMLHttpRequest();
req.open('GET', document.location);

var oldNotifications = req.channel.notificationCallbacks;
var oldEventSink = null;
req.channel.notificationCallbacks =
{
  QueryInterface: XPCOMUtils.generateQI([
      Components.interfaces.nsIInterfaceRequestor,
      Components.interfaces.nsIChannelEventSink]),

  getInterface: function(iid)
  {
    // We are only interested in nsIChannelEventSink, return the old callbacks
    // for any other interface requests.
    if (iid.equals(Ci.nsIChannelEventSink))
    {
      try {
        oldEventSink = oldNotifications.QueryInterface(iid);
      } catch(e) {}
      return this;
    }

    if (oldNotifications)
      return oldNotifications.QueryInterface(iid);
    else
      throw Components.results.NS_ERROR_NO_INTERFACE;
  },

  asyncOnChannelRedirect: function(oldChannel, newChannel, flags, callback)
  {
    var type = null;
    if (flags & Components.interfaces.nsIChannelEventSink.REDIRECT_TEMPORARY)
      type = "temporary";
    else if (flags & Components.interfaces.nsIChannelEventSink.REDIRECT_PERMANENT)
      type = "permanent";
    else if (flags & Components.interfaces.nsIChannelEventSink.REDIRECT_INTERNAL)
      type = "internal";

    Components.utils.reportError("Redirect from " + oldChannel.URI.spec + " " +
                                 "to " + newChannel.URI.spec + " " +
                                 (type ? "(" + type + ")" : ""));

    if (oldEventSink)
      oldEventSink.asyncOnChannelRedirect(oldChannel, newChannel, flags, callback);
    else
      callback.onRedirectVerifyCallback(Cr.NS_OK);
  }
};

req.send(null);

This code makes sure to always call the old notification callbacks while logging any calls to nsIChannelEventSync.asyncOnChannelRedirect.

For reference: nsIInterfaceRequestor, XPCOMUtils.

Upvotes: 1

Related Questions