AnderssonPeter/CompressedStaticFiles

Exception when path contains : character

sshumakov opened this issue · 12 comments

Whenever path contains ":" character, exception is thrown:

GET https://localhost/testtest - 404
GET https://localhost/test:test - 500

System.NotSupportedException

The given path's format is not supported.

I even tried to use StaticFileOptions to limit request path to certain folder, still, the same result.

My guess is that the underlying os does not support : in filenames.
What result are you expecting?

cata commented

@AnderssonPeter
I've just stumbled upon this issue.
I think the middleware should not throw an exception if the requested URL contains characters that are illegal in the underlying OS's paths/filenames.
I would expect Invoke to simply return _base.Invoke(context) in this circumstance

Consider the fact that an ASP.Net application may also serve dynamic content, in which case the URLs the server needs to handle, while valid, may contain characters that are illegal in the underlying file system.

I just ported to .net standard 2.0, and i think that solved this issue?
Could you verify?

cata commented

@AnderssonPeter - Thanks! I will try to switch back to using the CompressedStaticFiles nuget early next week and let you know if the issue is solved.

cata commented

@AnderssonPeter - a cursory examination of the code makes me think that it will still throw. To solve this on my side I put

var orginalFile = new FileInfo(orginalFilePath);
if (orginalFile.Exists)
{
foreach (var compressionType in compressionTypes.Keys)
{
if (browserSupportedCompressionTypes.Contains(compressionType, StringComparer.OrdinalIgnoreCase))
{
var fileExtension = compressionTypes[compressionType];
var filePath = orginalFilePath + fileExtension;
var file = new FileInfo(filePath);
if (file.Exists && file.Length < orginalFile.Length)
{
if (matchedFile == null)
matchedFile = file;
else if (matchedFile.Length > file.Length)
matchedFile = file;
}
}
}
if (matchedFile != null)
{
var matchedPath = context.Request.Path.Value + matchedFile.Extension;
_logger.LogFileServed(context.Request.Path.Value, matchedPath, orginalFile.Length, matchedFile.Length);
context.Request.Path = new PathString(matchedPath);
return _base.Invoke(context);
}
}
in a try-catch and returned _base.Invoke(context) if an exception was thrown.

I can submit a PR if you find the approach acceptable.

I tried to access test:test without getting a exception.
So what am I missing to cause the exception?

cata commented

Sorry for not responding sooner - here's a path that will cause the current implementation to throw: /%3A:

System.NotSupportedException: The given path's format is not supported.
   at System.Security.Permissions.FileIOPermission.EmulateFileIOPermissionChecks(String fullPath)
   at System.Security.Permissions.FileIOPermission.QuickDemand(FileIOPermissionAccess access, String fullPath, Boolean checkForDuplicates, Boolean needFullPath)
   at System.IO.FileInfo.Init(String fileName, Boolean checkHost)
   at CompressedStaticFiles.CompressedStaticFileMiddleware.Invoke(HttpContext context)

Thanks i will check it out when i get some free time!

@cata i tried to access a file with /%3A but i get no exception.
i ran the example project in this github and browsed to the following url http://localhost:50257/%3A
What version of .net core are you running when this happens?

cata commented

@AnderssonPeter thank you for looking into this. The project in question targets .Net framework 4.7.1. It cannot yet be migrated to .Net core due to extant dependencies.

@cata could you provide a example project? I can't get .net 4.7.1 to work with CompressedStaticFiles.

The following is my try, but startup.cs does not seem to be invoked!
Example.Net.zip

cata commented

@AnderssonPeter - sorry for not having responded sooner. I will look at the example this coming week