예제 #1
0
        // Call this when you have tried to load a url via XMLHttpRequest or
        // something along those lines, and the attempt has failed. We will mark the
        // domain as needing proxying, and will return a new proxy-enabled URL to try.
        // The exception is for flagship website URLs, which we know that the proxy
        // won't help with. For those, null is returned.
        public string activateProxy(string url)
        {
            // Get the domain. XXX copy/pastey from the above.

            string lc = url.ToLowerCase();
            string url_no_protocol;

            if (lc.StartsWith("http://"))
            {
                url_no_protocol = url.Substring(7);
            }
            else if (lc.StartsWith("https://"))
            {
                url_no_protocol = url.Substring(8);
            }
            else if (lc.StartsWith("//"))
            {
                url_no_protocol = url.Substring(2);
            }
            else
            {
                url_no_protocol = url;
            }

            string lcdomain;
            int    slash_index = url_no_protocol.IndexOf('/');

            if (slash_index < 0)
            {
                lcdomain = url_no_protocol;
            }
            else
            {
                lcdomain = url_no_protocol.Substring(0, slash_index).ToLowerCase();
            }

            // Is this a flagship or never-proxy URL? If so, don't bother proxying.

            if (!this.domain_handling.ContainsKey(lcdomain))
            {
                if (lcdomain.StartsWith("localhost:") || lcdomain.StartsWith("127.0.0.1:"))
                {
                    this.domain_handling[lcdomain] = DomainHandling.Localhost;
                }
                else
                {
                    this.domain_handling[lcdomain] = DomainHandling.TryNoProxy;
                }
            }

            DomainHandling mode = this.domain_handling[lcdomain];

            if (mode == DomainHandling.WWTFlagship || mode == DomainHandling.NeverProxy || mode == DomainHandling.Localhost)
            {
                return(null);
            }

            // OK, we should try proxying. So:

            this.domain_handling[lcdomain] = DomainHandling.Proxy;
            return(this.rewrite(url, URLRewriteMode.AsIfAbsolute));
        }
예제 #2
0
        public String rewrite(String url, URLRewriteMode rwmode)
        {
            // Sadly, we can't take advantage of JS/browser URL parsing
            // because this function might be passed template URLs like
            // "http://r{S:2}.ortho.tiles.virtualearth.net/..." that won't
            // parse. So we have to split up the URL manually.

            string lc = url.ToLowerCase();
            string lcproto;
            string url_no_protocol;

            if (lc.StartsWith("http://"))
            {
                lcproto         = "http:";
                url_no_protocol = url.Substring(7);
            }
            else if (lc.StartsWith("https://"))
            {
                lcproto         = "https:";
                url_no_protocol = url.Substring(8);
            }
            else if (lc.StartsWith("//"))
            {
                lcproto         = "";
                url_no_protocol = url.Substring(2);
            }
            else if (lc.StartsWith("blob:"))
            {
                // The web client uses URL.createObjectURL() to ingest local
                // disk files into the web app. That function creates blob
                // URLs, and it turns out that we definitely don't want to
                // rewrite them!
                return(url);
            }
            else
            {
                switch (rwmode)
                {
                case URLRewriteMode.AsIfAbsolute:
                default:
                    // Treat `foo/bar` as a domain name of `foo` and a
                    // path of `/bar`. Really we should demand that the
                    // caller always pass us an absolute URL, but URLs
                    // will be coming from random data sources and we're
                    // not currently rigorous enough to guarantee that
                    // this function will get validated inputs -- and in
                    // such cases, throwing exceptions won't help.
                    lcproto         = "";
                    url_no_protocol = url;
                    break;

                case URLRewriteMode.OriginRelative:
                    // Treat `foo/bar` as a URL relative to the window
                    // origin. Since it looks relative, any weird
                    // templating stuff in the URL text *ought* not cause
                    // problems for the browser URL parsing ...
                    url = (String)Script.Literal("(new URL({0}, window.location.href)).toString()", url);
                    return(this.rewrite(url, URLRewriteMode.AsIfAbsolute));
                }
            }

            string domain;
            string rest; // potentially "/foo/CASE/bar?q=1&b=1#fragment"
            int    slash_index = url_no_protocol.IndexOf('/');

            if (slash_index < 0)
            {
                domain = url_no_protocol;
                rest   = "/";
            }
            else
            {
                domain = url_no_protocol.Substring(0, slash_index);
                rest   = url_no_protocol.Substring(slash_index); // starts with "/"
            }

            string lcdomain = domain.ToLowerCase();
            string lcpath   = rest.ToLowerCase().Split('?')[0];

            if (!this.domain_handling.ContainsKey(lcdomain))
            {
                // Domains include nonstandard port specifications, so it's
                // possible that we could get here with a discernably
                // localhost-y domain.
                if (lcdomain.StartsWith("localhost:") || lcdomain.StartsWith("127.0.0.1:"))
                {
                    this.domain_handling[lcdomain] = DomainHandling.Localhost;
                }
                else
                {
                    this.domain_handling[lcdomain] = DomainHandling.TryNoProxy;
                }
            }

            DomainHandling mode = this.domain_handling[lcdomain];

            switch (mode)
            {
            case DomainHandling.Localhost:
                return(url);     // can't proxy, so we'll just have to hope it works

            case DomainHandling.NeverProxy:
            case DomainHandling.TryNoProxy:
            default:
                if (this.force_https && lcproto != "https:")
                {
                    // Force HTTPS and we'll see what happens. If
                    // downloading fails, we'll set a flag and use our
                    // proxy to launder the security.
                    //
                    // NOTE: it is important that we use `domain` and not
                    // `lcdomain`, even though domain names are
                    // case-insensitive, because we might be processing a
                    // template URL containing text like `{S}`, and WWT's
                    // replacements *are* case-sensitive. Yes, I did learn
                    // this the hard way.
                    return("https://" + domain + rest);
                }
                return(url);

            case DomainHandling.Proxy:
                if (lcproto == "")
                {
                    // Make sure that we give the proxy a real absolute
                    // URL. Guess http, and if the proxy is forced to
                    // upgrade, so be it.
                    url = "http://" + url;
                }

                // We need to encode the URL as a query-string parameter
                // to pass to the proxy. However, the encoding will turn
                // "{}" into "%7B%7D", so that *if* this URL is then going
                // to be fed into the templating system,
                // search-and-replace for e.g. "{0}" will break. So we
                // un-encode those particular characters, since it ought
                // to be safe to do so anyway.
                url = url.EncodeUriComponent().Replace("%7B", "{").Replace("%7D", "}");

                return(this.core_dynamic_baseurl + "/webserviceproxy.aspx?targeturl=" + url);

            case DomainHandling.WWTFlagship:
                // Rewrite "flagship"/core URLs to go through whatever our
                // core bases are. Assume that URLs are dynamic (=> are
                // not loaded through the CDN) unless proven otherwise.
                bool is_static = false;

                if (lcpath.StartsWith("/data/"))
                {
                    is_static = true;
                }
                else if (this.flagship_static_lcpaths.ContainsKey(lcpath))
                {
                    is_static = true;
                }
                else if (lcpath.StartsWith("/content/"))
                {
                    is_static = true;
                }
                else if (lcpath.StartsWith("/engine/assets/"))
                {
                    is_static = true;
                }

                if (is_static)
                {
                    return(this.core_static_baseurl + rest);
                }
                return(this.core_dynamic_baseurl + rest);
            }
        }