Err_too_many_redirects

Hi, on my dev server I want to show, local images if they exist, and if they do not exist I want to fetch them from our live server. Right now, all broken images on my local causes redirect loops. And whatever i put in the rewrite the loop still takes place. How can I break the loop and serve a different image?
The problem exist regardless, but this is the reverse proxy i have tryed.

<rewrite>
        <rules>
            <rule name="Rewrite storage requests to eleven.se" stopProcessing="true">
                <conditions>
			        <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true"/>
			    </conditions>
                <match url="^storage\/.+$" />
                <action type="Rewrite" url="https://liveserver.se/{R:0}" />
            </rule>
        </rules>
    </rewrite>

Litium version: 7.3

If the error is a permanent redirect it will be cached by the browser and you probably is looping between two cached urls.

When I test different sites I usual use the CDN feature in litium, then all storage-links will always be pointed to the live site and I don’t need to storage folder on my local computer.

<storage useCdn="true" useSecureCdn="true" cdnHost="https://www.domain.com" cdnSecureHost=""/>

I use the cdn option most of the time, but sometimes we want to test content that dose not exist live, only on the test server, so we want to be able to only fetch external images if the file is a 404 locally.

The rule should work fine, but we get this redirect loop before we even hit the rule it seams?
The loop is not a cache problem as far as i can tell, you can try your self, our test server dose not have the logo locally:

https://testse2.eleven.se/storage/AD6AF29A838747C38AE176484691D4189779A8C1A7D1A03CCEF767D02A8E4C14/841eef36a7604ad086954abd9a689126/239-50-0-png.Png/media/98400f7046c04d598fb89b93aafc61a9/eleven_logotype_RGB_petrol.png

This is without any added rewrite rules

When you access the file and got a redirect, do you have any information logged in the logfile on trace level?

No logs, this only happens on images that have the url in the database but missing files, random storage url returns 404 as expected. I think you can recreate this on a fresh install. We have seen this behavior for a while.

Regardless of this redirect loop, if I add my rule higher up in the hierarchy it migt bypass it? Can i do that somehow?

Also one more reason we need to do this, is that there is a “bug” in the backoffice when using the cdn option. the preview of the blocks cant be viewed/generated while using cdn do to “canvas tainted” exeptions.

Edit, so am now guessing that even with this fix since we dont know the file location on the server matchType=“IsFile” negate=“true” will not work?

Not sure exactly where and how the url-rewrite-rules attaches into the application flow. Maybe you can attach to the EndRequest event (global.asax) and there check if status is 404 and url starts with storage and in that case change the response to a redirect instead to the origin domain…

I think I have another solution for you, using a decorator as below with the following storage settings

<storage useCdn="false" useSecureCdn="false" cdnHost="https://www.domain.com"...

The cdnHost or cdnSecureHost is used for setting the live environment address.

using System;
using System.Linq;
using JetBrains.Annotations;
using Litium.Blobs;
using Litium.Runtime.DependencyInjection;
using Litium.Web.Media;

namespace Litium.Accelerator
{
    [ServiceDecorator(typeof(MediaLocationService))]
    public class MediaLocationServiceDeveloperhostDecorator : MediaLocationService
    {
        private static readonly string _host;

        private readonly MediaLocationService _parent;
        private readonly BlobService _blobService;

        static MediaLocationServiceDeveloperhostDecorator()
        {
            var cfg = Litium.Studio.Configuration.StorageConfig.Instance;
            _host = (cfg.CdnSecureHost ?? cfg.CdnHost ?? "")
                .Split(new[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries)
                .Select(x => x.Trim().TrimEnd('/'))
                .FirstOrDefault();
        }

        public MediaLocationServiceDeveloperhostDecorator(
            MediaLocationService parent,
            BlobService blobService)
        {
            _parent = parent;
            _blobService = blobService;
        }

        public override string GetLocation<T>([NotNull] MediaLocationServiceArgs args)
        {
            var mediaUrl = _parent.GetLocation<T>(args);

            var blob = _blobService.Get(args.BlobUri);
            if (string.IsNullOrEmpty(_host) || blob?.GetDefault()?.Exists == true)
            {
                return mediaUrl;
            }

            return string.Concat(_host, mediaUrl);
        }
    }
}
1 Like

After adding a protocol to “return string.Concat(_protocol + _host, mediaUrl)” it worked wonders thanks!.
But will the blob check slow down production? Should I do some checks if in producion or can I “disable” the GetLocation() decerator in the constructor based on settings?

    public override string GetLocation<T>([NotNull] MediaLocationServiceArgs args)
    {
 
        var mediaUrl = _parent.GetLocation<T>(args);
         if(_isProduction){
            return mediaUrl;
         }
        var blob = _blobService.Get(args.BlobUri);
        if (string.IsNullOrEmpty(_host) || blob?.GetDefault()?.Exists == true)
        {
            return mediaUrl;
        }

        return string.Concat(_host, mediaUrl);
    }

They have cache so I expect them to be fast. But if it is possible to do a production check then I think you can have it.

1 Like

The var blob = _blobService.Get(args.BlobUri); is only in memory but the blob?.GetDefault()?.Exists == true will check that the actual file exists.

I think you in the most cases compiling the solution in DEBUG mode when running local and RELEASE mode for production. In that case I should have used conditional code compilation.

#if DEBUG

/// all code that only should be there during debug build, in this case the full class

#endif
2 Likes