Browse Source

prefixed requests no longer require a querystring

Former-commit-id: ae8faff3e48c3029377ed07059371c5bcb2e9315
Former-commit-id: f629085773bfcbcbf7d8a120175b572397512a1d
af/merge-core
James South 11 years ago
parent
commit
bb441a16de
  1. 10
      src/ImageProcessor.Playground/Program.cs
  2. 232
      src/ImageProcessor.Web/HttpModules/ImageProcessingModule.cs

10
src/ImageProcessor.Playground/Program.cs

@ -53,7 +53,7 @@ namespace ImageProcessor.PlayGround
Image mask = Image.FromFile(Path.Combine(resolvedPath, "mask.png"));
Image overlay = Image.FromFile(Path.Combine(resolvedPath, "imageprocessor.128.png"));
//FileInfo fileInfo = new FileInfo(Path.Combine(resolvedPath, "monster.png"));
IEnumerable<FileInfo> files = GetFilesByExtensions(di, ".jpg");
IEnumerable<FileInfo> files = GetFilesByExtensions(di, ".gif");
//IEnumerable<FileInfo> files = GetFilesByExtensions(di, ".gif", ".webp", ".bmp", ".jpg", ".png", ".tif");
foreach (FileInfo fileInfo in files)
@ -88,11 +88,10 @@ namespace ImageProcessor.PlayGround
//.Resize(new Size((int)(size.Width * 1.1), 0))
//.ContentAwareResize(layer)
//.Constrain(size)
//.Rotate(-64)
//.Mask(mask)
//.Format(new PngFormat())
//.BackgroundColor(Color.Cyan)
.ReplaceColor(Color.FromArgb(255, 223, 224), Color.FromArgb(121, 188, 255), 128)
//.ReplaceColor(Color.FromArgb(255, 223, 224), Color.FromArgb(121, 188, 255), 128)
//.Resize(size)
// .Resize(new ResizeLayer(size, ResizeMode.Max))
// .Resize(new ResizeLayer(size, ResizeMode.Stretch))
@ -104,9 +103,10 @@ namespace ImageProcessor.PlayGround
//.Filter(MatrixFilters.Comic)
//.Flip()
//.Filter(MatrixFilters.HiSatch)
//.Pixelate(8)
.Pixelate(8)
.Rotate(45)
//.GaussianSharpen(10)
.Format(new PngFormat())
//.Format(new PngFormat() { IsIndexed = true })
//.Format(new PngFormat() { IsIndexed = true })
//.Save(Path.GetFullPath(Path.Combine(Path.GetDirectoryName(path), @"..\..\images\output", fileInfo.Name)));
.Save(Path.GetFullPath(Path.Combine(Path.GetDirectoryName(path), @"..\..\images\output", Path.GetFileNameWithoutExtension(fileInfo.Name) + ".png")));

232
src/ImageProcessor.Web/HttpModules/ImageProcessingModule.cs

@ -316,151 +316,161 @@ namespace ImageProcessor.Web.HttpModules
}
else
{
requestPath = HostingEnvironment.MapPath(request.Path);
queryString = HttpUtility.UrlDecode(request.QueryString.ToString());
}
// Only process requests that pass our sanitizing filter.
if (!string.IsNullOrWhiteSpace(queryString))
{
// Replace any presets in the querystring with the actual value.
queryString = this.ReplacePresetsInQueryString(queryString);
string parts = !string.IsNullOrWhiteSpace(urlParameters) ? "?" + urlParameters : string.Empty;
string fullPath = string.Format("{0}{1}?{2}", requestPath, parts, queryString);
object resourcePath;
if (hasMultiParams)
if (string.IsNullOrWhiteSpace(currentService.Prefix))
{
resourcePath = string.IsNullOrWhiteSpace(urlParameters)
? new Uri(requestPath, UriKind.RelativeOrAbsolute)
: new Uri(requestPath + "?" + urlParameters, UriKind.RelativeOrAbsolute);
requestPath = HostingEnvironment.MapPath(request.Path);
queryString = HttpUtility.UrlDecode(request.QueryString.ToString());
}
else
{
resourcePath = requestPath;
requestPath = HttpUtility.UrlDecode(request.QueryString.ToString());
}
}
// Check whether the path is valid for other requests.
if (resourcePath == null || !currentService.IsValidRequest(resourcePath.ToString()))
{
return;
}
// If the current service doesn't require a prefix, don't fetch it.
// Let the static file handler take over.
if (string.IsNullOrWhiteSpace(currentService.Prefix) && string.IsNullOrWhiteSpace(queryString))
{
return;
}
// Replace any presets in the querystring with the actual value.
queryString = this.ReplacePresetsInQueryString(queryString);
string parts = !string.IsNullOrWhiteSpace(urlParameters) ? "?" + urlParameters : string.Empty;
string fullPath = string.Format("{0}{1}?{2}", requestPath, parts, queryString);
object resourcePath;
if (hasMultiParams)
{
resourcePath = string.IsNullOrWhiteSpace(urlParameters)
? new Uri(requestPath, UriKind.RelativeOrAbsolute)
: new Uri(requestPath + "?" + urlParameters, UriKind.RelativeOrAbsolute);
}
else
{
resourcePath = requestPath;
}
// Create a new cache to help process and cache the request.
DiskCache cache = new DiskCache(requestPath, fullPath, queryString);
string cachedPath = cache.CachedPath;
// Check whether the path is valid for other requests.
if (resourcePath == null || !currentService.IsValidRequest(resourcePath.ToString()))
{
return;
}
// Since we are now rewriting the path we need to check again that the current user has access
// to the rewritten path.
// Get the user for the current request
// If the user is anonymous or authentication doesn't work for this suffix avoid a NullReferenceException
// in the UrlAuthorizationModule by creating a generic identity.
string virtualCachedPath = cache.VirtualCachedPath;
// Create a new cache to help process and cache the request.
DiskCache cache = new DiskCache(requestPath, fullPath, queryString);
string cachedPath = cache.CachedPath;
IPrincipal user = context.User ?? new GenericPrincipal(new GenericIdentity(string.Empty, string.Empty), new string[0]);
// Since we are now rewriting the path we need to check again that the current user has access
// to the rewritten path.
// Get the user for the current request
// If the user is anonymous or authentication doesn't work for this suffix avoid a NullReferenceException
// in the UrlAuthorizationModule by creating a generic identity.
string virtualCachedPath = cache.VirtualCachedPath;
// Do we have permission to call UrlAuthorizationModule.CheckUrlAccessForPrincipal?
PermissionSet permission = new PermissionSet(PermissionState.None);
permission.AddPermission(new AspNetHostingPermission(AspNetHostingPermissionLevel.Unrestricted));
bool hasPermission = permission.IsSubsetOf(AppDomain.CurrentDomain.PermissionSet);
IPrincipal user = context.User ?? new GenericPrincipal(new GenericIdentity(string.Empty, string.Empty), new string[0]);
bool isAllowed = true;
// Do we have permission to call UrlAuthorizationModule.CheckUrlAccessForPrincipal?
PermissionSet permission = new PermissionSet(PermissionState.None);
permission.AddPermission(new AspNetHostingPermission(AspNetHostingPermissionLevel.Unrestricted));
bool hasPermission = permission.IsSubsetOf(AppDomain.CurrentDomain.PermissionSet);
// Run the rewritten path past the authorization system again.
// We can then use the result as the default "AllowAccess" value
if (hasPermission && !context.SkipAuthorization)
{
isAllowed = UrlAuthorizationModule.CheckUrlAccessForPrincipal(virtualCachedPath, user, "GET");
}
bool isAllowed = true;
if (isAllowed)
{
// Is the file new or updated?
bool isNewOrUpdated = cache.IsNewOrUpdatedFile(cachedPath);
// Run the rewritten path past the authorization system again.
// We can then use the result as the default "AllowAccess" value
if (hasPermission && !context.SkipAuthorization)
{
isAllowed = UrlAuthorizationModule.CheckUrlAccessForPrincipal(virtualCachedPath, user, "GET");
}
// Only process if the file has been updated.
if (isNewOrUpdated)
if (isAllowed)
{
// Is the file new or updated?
bool isNewOrUpdated = cache.IsNewOrUpdatedFile(cachedPath);
// Only process if the file has been updated.
if (isNewOrUpdated)
{
// Process the image.
using (ImageFactory imageFactory = new ImageFactory(preserveExifMetaData != null && preserveExifMetaData.Value))
{
// Process the image.
using (ImageFactory imageFactory = new ImageFactory(preserveExifMetaData != null && preserveExifMetaData.Value))
using (await this.locker.LockAsync(cachedPath))
{
using (await this.locker.LockAsync(cachedPath))
{
byte[] imageBuffer = await currentService.GetImage(resourcePath);
byte[] imageBuffer = await currentService.GetImage(resourcePath);
using (MemoryStream memoryStream = new MemoryStream(imageBuffer))
{
// Reset the position of the stream to ensure we're reading the correct part.
memoryStream.Position = 0;
using (MemoryStream memoryStream = new MemoryStream(imageBuffer))
{
// Reset the position of the stream to ensure we're reading the correct part.
memoryStream.Position = 0;
// Process the Image
imageFactory.Load(memoryStream).AutoProcess(queryString).Save(cachedPath);
// Process the Image
imageFactory.Load(memoryStream).AutoProcess(queryString).Save(cachedPath);
// Add to the cache.
cache.AddImageToCache(cachedPath);
// Add to the cache.
cache.AddImageToCache(cachedPath);
// Store the cached path, response type, and cache dependency in the context for later retrieval.
context.Items[CachedPathKey] = cachedPath;
context.Items[CachedResponseTypeKey] = imageFactory.CurrentImageFormat.MimeType;
context.Items[CachedResponseFileDependency] = new List<string> { cachedPath };
}
// Store the cached path, response type, and cache dependency in the context for later retrieval.
context.Items[CachedPathKey] = cachedPath;
context.Items[CachedResponseTypeKey] = imageFactory.CurrentImageFormat.MimeType;
context.Items[CachedResponseFileDependency] = new List<string> { cachedPath };
}
}
}
}
// Image is from the cache so the mime-type will need to be set.
if (context.Items[CachedResponseTypeKey] == null)
{
string mimetype = ImageHelpers.GetMimeType(cachedPath);
if (!string.IsNullOrEmpty(mimetype))
{
context.Items[CachedResponseTypeKey] = mimetype;
}
}
// Image is from the cache so the mime-type will need to be set.
if (context.Items[CachedResponseTypeKey] == null)
{
string mimetype = ImageHelpers.GetMimeType(cachedPath);
if (context.Items[CachedResponseFileDependency] == null)
if (!string.IsNullOrEmpty(mimetype))
{
context.Items[CachedResponseFileDependency] = new List<string> { cachedPath };
context.Items[CachedResponseTypeKey] = mimetype;
}
}
string incomingEtag = context.Request.Headers["If" + "-None-Match"];
if (context.Items[CachedResponseFileDependency] == null)
{
context.Items[CachedResponseFileDependency] = new List<string> { cachedPath };
}
if (incomingEtag != null && !isNewOrUpdated)
{
// Set the Content-Length header so the client doesn't wait for
// content but keeps the connection open for other requests.
context.Response.AddHeader("Content-Length", "0");
context.Response.StatusCode = (int)HttpStatusCode.NotModified;
context.Response.SuppressContent = true;
string incomingEtag = context.Request.Headers["If" + "-None-Match"];
if (isFileLocal)
{
// Set the headers and quit.
// Some services might only provide filename so we can't monitor for the browser.
this.SetHeaders(
context,
(string)context.Items[CachedResponseTypeKey],
Path.GetFileName(requestPath) == requestPath ? new List<string> { cachedPath } : new List<string> { requestPath, cachedPath });
}
else
{
this.SetHeaders(context, (string)context.Items[CachedResponseTypeKey], new List<string> { cachedPath });
}
if (incomingEtag != null && !isNewOrUpdated)
{
// Set the Content-Length header so the client doesn't wait for
// content but keeps the connection open for other requests.
context.Response.AddHeader("Content-Length", "0");
context.Response.StatusCode = (int)HttpStatusCode.NotModified;
context.Response.SuppressContent = true;
// Complete the requests but don't abort the thread.
context.ApplicationInstance.CompleteRequest();
return;
if (isFileLocal)
{
// Set the headers and quit.
// Some services might only provide filename so we can't monitor for the browser.
this.SetHeaders(
context,
(string)context.Items[CachedResponseTypeKey],
Path.GetFileName(requestPath) == requestPath ? new List<string> { cachedPath } : new List<string> { requestPath, cachedPath });
}
else
{
this.SetHeaders(context, (string)context.Items[CachedResponseTypeKey], new List<string> { cachedPath });
}
// The cached file is valid so just rewrite the path.
context.RewritePath(virtualCachedPath, false);
}
else
{
throw new HttpException(403, "Access denied");
// Complete the requests but don't abort the thread.
context.ApplicationInstance.CompleteRequest();
return;
}
// The cached file is valid so just rewrite the path.
context.RewritePath(virtualCachedPath, false);
}
else
{
throw new HttpException(403, "Access denied");
}
}
}

Loading…
Cancel
Save