mwrock / RequestReduce

Instantly makes your .net website faster by reducing the number and size of requests with almost no effort.
www.requestreduce.org
Apache License 2.0
228 stars 48 forks source link

Supporting https & http on Appharbor #177

Open dazbradbury opened 12 years ago

dazbradbury commented 12 years ago

Hi,

Forgive me for asking about such a unique scenario, unfortunately, this issue resulted in me temporarily disabling request reduce until I had time to look into it (Hence my tardy reply to your other post).

Basically, AppHarbor use Forwarding headers on requests past their load balancers. This allows my app to know whether the request was a http, or https request.

Now, when using https, my users need to either have RequestReduce disabled, or use a URL Transformer to replace "http" with "https" in my resulting css. This works fine, but I can only get it to work if applied to ALL requests. Unfortunately, AppHarbor uses SNI-SSL, which throws errors on some browsers. This means I can't have an https-everywhere site.

My solution to this was to only do URL transformations if it's a HTTPS request, and was along the lines of:

RequestReduce.Api.Registry.UrlTransformer =
                (context, x, y) =>
                    ( IsSecureConnection(context.Request) : false)
                    ? y.Replace("http://www.mysite.co", "https://www.mysite.co") : y;

Unfortunately, the context.Request paramater is always null.

I'm also thinking, that as the resulting css is saved, I would need multiple versions unless RR treats http and https as seperate requests and serves seperate css?

Is there a working solution for this scenario?

Thanks again, Daz.

mwrock commented 12 years ago

Hi Daz,

Unfortunately there is no other solution to this other than globally turning on https. While the context parameter of the UrlTransformer should only be null for sprite url transforming (not js or css urls), it has to be null when generating sprites because that is done in the background where there is no access to the request context.

dazbradbury commented 12 years ago

Thanks for the response!

I'm seeing non-null context values even though I have image sprite processing set to off, is this also what you would expect?

The code I posted causes no minified js/css to be stored by RR - because the context is always null, all minification attempts bomb out. I'm guessing there will be other issues with this set up, in that RR will serve up the same js/css regardless of whether it is http or https traffic? Hence, it needs to look at the whether ssl is enabled or not, and serve the relevant files. With appharbor, this is even more awkward due to their forwarding headers I mentioned previously.

I will hopefully find time to take a look at your source and propose some changes to allow for https/http differentiation, unfortunately I've not been able to find the time in the past couple of weeks.

Thanks again for the response! Daz.

jammykam commented 12 years ago

Is there a way to disable (using config or code) the insertion of the host URL into the CSS? i.e. only change the URL of background images in CSS to absolute paths starting with "/".

In a similar situation where we have http and https version of the site, but https is only up to the firewall so the server is always operating in http. Since the URL of the background image is http this causes a warning message (some content is not being served over a secure connection) in some versions of IE.

If we could get rid of the URL insertion then a single merged CSS file would work for both connections. I am unable to force the URL to https using the "contentHost" config attribute because we are running in a CMS environment hosting multiple sites.

mwrock commented 12 years ago

Yes. Use the urltransformer delegate discussed in the rr API wiki page and simply return the third input param removing the scheme and host if it ends in .css.

dazbradbury commented 12 years ago

Thanks! This looks like good workaround for me as well.

Would you be able to point me in the right direction to making this work fully with js and images? FYI - I've added the following.

RequestReduce.Api.Registry.UrlTransformer =
                (context, x, y) =>
                y.Replace("http://", "//");

RequestReduce.Api.Registry.UrlTransformer =
               (context, x, y) =>
               y.Replace("https://", "//");

Unfortunately, this doesn't have an affect on:

This pretty close to a fully working workaround though!

mwrock commented 12 years ago

I just tried this myself and it did work for the css background images. It will not currently work for URLs embedded in javascript. This is a known limitation of RequestReduce.

One thing to note is that you do not want to have your http and https replacements in separate calls to the UrlTransformer property since that sets a single property and does not add a new transformer. So the second call will overwrite the first.

dazbradbury commented 12 years ago

Perfect, thanks for the response. Will just do this for now:

RequestReduce.Api.Registry.UrlTransformer =
                (context, x, y) =>
                y.Replace("http://", "//").Replace("https://", "//");

Seems to make everything work - just need to be careful with which external js files I process.

Thanks!

jammykam commented 12 years ago

Great, I will also implement this.

I still think this needs to be implemented out of the box though and there should be a config switch to NOT add domain names (better still, it should not do it by default unless CDN is specified).

Doing this will also will also save a few bytes in file size, and seeing as the whole point of RR....

mwrock commented 12 years ago

The problem with schema-less URIs is that IE 7 and IE 8 will download the css referenced bu these URIs twice. Eventually (the sooner the better), this will be a small edge case and I'd be happy to make it the default but they just represent too large of a market share right now.

Having an option to keep the URLs relative is very fair.

mwrock commented 12 years ago

I am reopening this since I plan to rework the absolute URL logic for.next weeks release. Essentially unless you are using the contenthost setting, rr generated URLs will be relative to the host.

Does anyone see any issues here?

dazbradbury commented 12 years ago

Thanks matt.

Just to clarify - does that mean you will treat https and http traffic differently and thus serve up two different sets of files for each?

Also - note that on Appharbor for example, traffic appears to be http due to the load balancer.

I've been re-writing the urls such that they are schema-less as suggested previously and that approach works best for me. I know IE7&IE8 users suffer due to css being downloaded twice, but that's a browser bug I'm happy not to work around for now.

Cheers, Daz.

jammykam commented 12 years ago

That's great, I think that is the expected behaviour from my point of view... Didn't know that about the http/https in Ie7/8 and agree that thing needs to die!

Look forward to the release.

mwrock commented 12 years ago

@dazbradbury yeah. if it was just my own site I was coding for, I'd let the IE 7/8 users suffer :) In fact, IE 7/8 users may just get a big page with links to chrome/FF/IE 9 asking them to install a modern browser for "today's web" but I dont feel right making that decision for site owners since I know for some (like my own employer and probably biggest RR user - MS) this is a sensitive topic.

I won't create separate resources for http/https. At least not now. Since now most urls will be relative it wont matter. If you use the content host for a CDN or cookieless domain, you can always use the schema less url in the config too.

dazbradbury commented 12 years ago

OK - thanks matt. I totally understand your reasoning - especially as MS are your employers! I used to have to support IE6 - but thankfully no longer!

I do use a CDN and schema less url in the config for most of my requests now - so I don't see this affecting me I guess. I was pretty happy with the previous workaround anyway!

Thanks again for taking the time to cover all the edge cases.

Cheers, Daz.

On Fri, Jun 1, 2012 at 4:37 PM, Matt Wrock < reply@reply.github.com

wrote:

@dazbradbury yeah. if it was just my own site I was coding for, I'd let the IE 7/8 users suffer :) In fact, IE 7/8 users may just get a big page with links to chrome/FF/IE 9 asking them to install a modern browser for "today's web" but I dont feel right making that decision for site owners since I know for some (like my own employer and probably biggest RR user - MS) this is a sensitive topic.

I won't create separate resources for http/https. At least not now. Since now most urls will be relative it wont matter. If you use the content host for a CDN or cookieless domain, you can always use the schema less url in the config too.


Reply to this email directly or view it on GitHub: https://github.com/mwrock/RequestReduce/issues/177#issuecomment-6063384

Darius Bradbury

jammykam commented 12 years ago

Hi Matt,

Any more updates on this? I downloaded the latest package but it is still the same behaviour... is there a change log somewhere so we know what updates are in each release?

thanks

mbolesta commented 12 years ago

Hi, I'm not seeing the UrlTransformer called against resources inside CSS files. When I add logging I only see it called for the top level CSS and JS bundle urls.

I need to strip the host name from the urls. I was able to work around this by defining my own minifier and running a regex against the content.

mwrock commented 12 years ago

I have not been able to get to this yet.Ramping up on a new job is unfortunately making it difficult to devote cycles here.

jammykam commented 12 years ago

Fair enough and understandable. Keep us informed when you finally get a bit time to implement this.

thanks.

mbolesta commented 12 years ago

Understandable. Thanks for your efforts!

On Tue, Jun 26, 2012 at 11:34 AM, Matt Wrock < reply@reply.github.com

wrote:

I have not been able to get to this yet.Ramping up on a new job is unfortunately making it difficult to devote cycles here.


Reply to this email directly or view it on GitHub: https://github.com/mwrock/RequestReduce/issues/177#issuecomment-6579035

Khepri commented 12 years ago

Wanted to follow up on this. We currently have a case where we have an htc file included in a stylesheet from a common shared content site that is included via a virtual directory. The style sheet entry ends up looking like

img.pngfix,div.pngfix img{behavior:url(/_common/htc/iepngfix.htc)

ReduceRequest is changing this to the full domain path.

img.pngfix,div.pngfix img{behavior:url([http://domain]/_common/htc/iepngfix.htc)

IE doesn't like this throwing a permission denied error which I'd expect. I thought that adding the following to our app startup would resolve this.

        RequestReduce.Api.Registry.UrlTransformer =
                        (context, x, y) =>
                        y.Replace("[http://domain]", "");

But it doesn't seem to have any effect.

Is this issue the correct one to address this on? I'd like in general for the paths to not be modified at all if that is possible.

jammykam commented 12 years ago

Yes, this is the same issue. I've used a different framework which doesn't touch the URL's, but personally I find this one better otherwise you end up having to put in longer, absolute paths in your source.

I couldn't get the above to work fro global.asax, so I put it in Page_Load of Masterpage, that did the trick but it doesn't seem quite right... I'm hoping the fix will be out soon...

sramani commented 12 years ago

Hello,

It appears I am also experiencing similar issue while using RequestReduce. It works fine locally(on my PC with http://) but once elevation to DEV environment done where "load balancing" will be applied. My portal works fine(I can use all my portal functionality) however RR could not process any of css ,javascript and background images as RR converted relative urls to fully qualified urls with "http://" where it supposed to be "https://" in DEV that causing below error...

: There were errors reducing http://computing-dev.exdev.net/Content/themes/base/reset.css::http://computing-dev.exdev.net/Content/themes/base/jquery-ui-1.8.14.custom.css::http://computing-dev.exdev.net/Content/themes/base/typography.css::http://computing-dev.exdev.net/Content/themes/base/eynav.css::http://computing-dev.exdev.net/Content/themes/base/structure-fluid.css::http://computing-dev.exdev.net/Content/themes/base/ey.css::http://computing-dev.exdev.net/Content/themes/base/Site.css:: Exception #2: RequestReduce had problems accessing http://computing-dev.exdev.net/Content/themes/base/reset.css. Error Message from WebClient is: The underlying connection was closed: An unexpected error occurred on a receive.

As soon as I change maually url from http://computing-dev.exdev.net/Content/themes/base/reset.css to https://computing-dev.exdev.net/Content/themes/base/reset.css,it works perfectly fine.

I tried with below code but does not help

RequestReduce.Api.Registry.UrlTransformer = (context, x, y) => y.Replace("http://", "//").Replace("https://", "//");

Wondering could anyone route me correct direction here?

Thanks, Ramani

gaevoy commented 11 years ago

You have to replace default Minifier with next one:

public class SchemaLessUrlReplacer : RequestReduce.Utilities.IMinifier
{
    private readonly Minifier minifier = new Minifier();
    public string Minify<T>(string unMinifiedContent) where T : RequestReduce.ResourceTypes.IResourceType
    {
        string content = minifier.Minify<T>(unMinifiedContent);
        if (typeof(T) == typeof(RequestReduce.ResourceTypes.CssResource))
        {
            content = new StringBuilder(content).Replace("http://", "//").Replace("https://", "//").ToString();
        }
        return content;
    }
}

Then register new one inside Application_Start() of global.asax:

public class MvcApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        ...
        RequestReduce.Api.Registry.RegisterMinifier<SchemaLessUrlReplacer>();
        ...
    }
}