Browse Source

Fixing redirect and cleanup.

Former-commit-id: 32e418b0f8b0b3b5a48dde36cc2f0ca52b8d3713
Former-commit-id: 31ab4e4c9d803625819d2646641c204460f69ed5
af/merge-core
James South 11 years ago
parent
commit
e03d784fd2
  1. 6
      build/build.xml
  2. 12
      src/ImageProcessor.Web.AzureBlobCache/AzureBlobCache.cs
  3. 4
      src/ImageProcessor.Web.PostProcessor/Properties/AssemblyInfo.cs
  4. 8
      src/ImageProcessor.Web.PostProcessor/README.md
  5. 1
      src/ImageProcessor.Web/Configuration/Resources/security.config
  6. 24
      src/ImageProcessor.Web/Helpers/ImageHelpers.cs
  7. 11
      src/ImageProcessor.Web/Helpers/RemoteFile.cs
  8. 82
      src/ImageProcessor.Web/HttpModules/ImageProcessingModule.cs
  9. 5
      src/ImageProcessor.Web/Services/RemoteImageService.cs
  10. 1
      src/ImageProcessor.sln.DotSettings
  11. 6
      src/ImageProcessor/ImageFactory.cs
  12. 1
      src/ImageProcessor/Imaging/Formats/FormatBase.cs
  13. 18
      src/TestWebsites/MVC/Global.asax.cs
  14. 3
      src/TestWebsites/MVC/Views/Home/Index.cshtml
  15. 2
      src/TestWebsites/MVC/config/imageprocessor/security.config

6
build/build.xml

@ -13,7 +13,7 @@
<project>
<name>ImageProcessor Web</name>
<version>4.1.5.0</version>
<version>4.2.0.0</version>
<folder>..\src\ImageProcessor.Web</folder>
<projfile>ImageProcessor.Web.csproj</projfile>
<outputs>
@ -24,7 +24,7 @@
<project>
<name>ImageProcessor Web PostProcessor</name>
<version>1.0.1.0</version>
<version>1.0.2.0</version>
<folder>..\src\ImageProcessor.Web.PostProcessor</folder>
<projfile>ImageProcessor.Web.PostProcessor.csproj</projfile>
<outputs>
@ -35,7 +35,7 @@
<project>
<name>ImageProcessor Web.config sample</name>
<version>2.1.1.0</version>
<version>2.2.0.0</version>
<nuspec>ImageProcessor.Web.Config.nuspec</nuspec>
</project>

12
src/ImageProcessor.Web.AzureBlobCache/AzureBlobCache.cs

@ -17,6 +17,7 @@ namespace ImageProcessor.Web.Caching
using System.IO;
using System.Linq;
using System.Net;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Web;
@ -217,16 +218,16 @@ namespace ImageProcessor.Web.Caching
Uri uri = new Uri(this.CachedPath);
string path = uri.GetLeftPart(UriPartial.Path).Substring(this.cloudCachedBlobContainer.Uri.ToString().Length + 1);
string directory = path.Substring(0, path.LastIndexOf('/'));
string parent = directory.Substring(path.LastIndexOf('/'));
string parent = directory.Substring(0, directory.LastIndexOf('/'));
BlobContinuationToken continuationToken = null;
CloudBlobDirectory directoryBlob = this.cloudCachedBlobContainer.GetDirectoryReference(parent);
List<IListBlobItem> results = new List<IListBlobItem>();
// Loop through the all the files in a non blocking fashion.
do
{
BlobResultSegment response = await directoryBlob.ListBlobsSegmentedAsync(continuationToken);
BlobResultSegment response = await this.cloudCachedBlobContainer
.ListBlobsSegmentedAsync(parent, true, BlobListingDetails.Metadata, 5000, continuationToken, null, null);
continuationToken = response.ContinuationToken;
results.AddRange(response.Results);
}
@ -280,7 +281,10 @@ namespace ImageProcessor.Web.Caching
}
else
{
string blobPath = this.CachedPath.Substring(this.cloudSourceBlobContainer.Uri.ToString().Length + 1);
Regex regex = new Regex("^http(s)?://");
string container = regex.Replace(this.cloudSourceBlobContainer.Uri.ToString(), string.Empty);
string blobPath = regex.Replace(this.RequestPath, string.Empty);
blobPath = blobPath.Replace(container, string.Empty).TrimStart('/');
CloudBlockBlob blockBlob = this.cloudSourceBlobContainer.GetBlockBlobReference(blobPath);
if (await blockBlob.ExistsAsync())

4
src/ImageProcessor.Web.PostProcessor/Properties/AssemblyInfo.cs

@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.1.0")]
[assembly: AssemblyVersion("1.0.1.0")]
[assembly: AssemblyFileVersion("1.0.1.0")]
[assembly: AssemblyVersion("1.0.2.0")]
[assembly: AssemblyFileVersion("1.0.2.0")]

8
src/ImageProcessor.Web.PostProcessor/README.md

@ -1,13 +1,13 @@
#Resource locations
###gifsicle
http://www.lcdf.org/gifsicle/
[http://www.lcdf.org/gifsicle/](http://www.lcdf.org/gifsicle/)
###jpegtran
http://jpegclub.org/jpegtran/
[http://jpegclub.org/jpegtran/](http://jpegclub.org/jpegtran/)
###optipng
http://optipng.sourceforge.net/
[http://optipng.sourceforge.net/](http://optipng.sourceforge.net/)
###pngout
http://advsys.net/ken/utils.htm
[http://advsys.net/ken/utils.htm](http://advsys.net/ken/utils.htm)

1
src/ImageProcessor.Web/Configuration/Resources/security.config

@ -5,6 +5,7 @@
<settings>
<setting key="MaxBytes" value="4194304"/>
<setting key="Timeout" value="3000"/>
<setting key="Protocol" value="http"/>
</settings>
<whitelist>
</whitelist>

24
src/ImageProcessor.Web/Helpers/ImageHelpers.cs

@ -104,30 +104,6 @@ namespace ImageProcessor.Web.Helpers
return string.Empty;
}
/// <summary>
/// Get the correct mime-type for the given string input.
/// </summary>
/// <param name="path">
/// The path to the cached image.
/// </param>
/// <returns>
/// The <see cref="string"/> matching the correct mime-type.
/// </returns>
public static string GetMimeType(string path)
{
using (FileStream file = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, false))
{
ISupportedImageFormat format = FormatUtilities.GetFormat(file);
if (format != null)
{
return format.MimeType;
}
}
return string.Empty;
}
/// <summary>
/// Builds a regular expression from the <see cref="T:ImageProcessor.Imaging.Formats.ISupportedImageFormat"/> type, this allows extensibility.
/// </summary>

11
src/ImageProcessor.Web/Helpers/RemoteFile.cs

@ -173,16 +173,20 @@ namespace ImageProcessor.Web.Helpers
/// </returns>
internal async Task<WebResponse> GetWebResponseAsync()
{
WebResponse response;
WebResponse response = null;
try
{
response = await this.GetWebRequest().GetResponseAsync();
}
catch (WebException ex)
{
if (ex.Status == WebExceptionStatus.NameResolutionFailure)
if (response != null)
{
throw new HttpException(404, "No image exists at " + Uri);
HttpWebResponse errorResponse = (HttpWebResponse)ex.Response;
if (errorResponse.StatusCode == HttpStatusCode.NotFound)
{
throw new HttpException(404, "No image exists at " + this.Uri);
}
}
throw;
@ -217,7 +221,6 @@ namespace ImageProcessor.Web.Helpers
#endregion
#region Private
/// <summary>
/// Creates the WebRequest object used internally for this RemoteFile instance.
/// </summary>

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

@ -148,7 +148,7 @@ namespace ImageProcessor.Web.HttpModules
context.AddOnPostAuthorizeRequestAsync(postAuthorizeHelper.BeginEventHandler, postAuthorizeHelper.EndEventHandler);
EventHandlerTaskAsyncHelper postProcessHelper = new EventHandlerTaskAsyncHelper(this.PostProcessImage);
context.AddOnPostRequestHandlerExecuteAsync(postProcessHelper.BeginEventHandler, postProcessHelper.EndEventHandler);
context.AddOnEndRequestAsync(postProcessHelper.BeginEventHandler, postProcessHelper.EndEventHandler);
context.PreSendRequestHeaders += this.ContextPreSendRequestHeaders;
}
@ -231,11 +231,11 @@ namespace ImageProcessor.Web.HttpModules
if (cachedPathObject != null)
{
string cachedPath = cachedPathObject.ToString();
// Trim the cache.
await this.imageCache.TrimCacheAsync();
string cachedPath = cachedPathObject.ToString();
// Fire the post processing event.
EventHandler<PostProcessingEventArgs> handler = OnPostProcessing;
if (handler != null)
@ -300,6 +300,7 @@ namespace ImageProcessor.Web.HttpModules
string queryString = string.Empty;
string urlParameters = string.Empty;
// Legacy support. I'd like to remove this asap.
if (hasMultiParams)
{
// We need to split the querystring to get the actual values we want.
@ -338,7 +339,13 @@ namespace ImageProcessor.Web.HttpModules
}
else
{
requestPath = HttpUtility.UrlDecode(request.QueryString.ToString());
// Parse any protocol values from settings.
string protocol = currentService.Settings["Protocol"] != null
? currentService.Settings["Protocol"] + "://"
: string.Empty;
requestPath = protocol + request.Path.Replace(currentService.Prefix, string.Empty).TrimStart('/');
queryString = HttpUtility.UrlDecode(request.QueryString.ToString());
}
}
@ -359,6 +366,7 @@ namespace ImageProcessor.Web.HttpModules
string fullPath = string.Format("{0}{1}?{2}", requestPath, parts, queryString);
object resourcePath;
// More legacy support code.
if (hasMultiParams)
{
resourcePath = string.IsNullOrWhiteSpace(urlParameters)
@ -394,50 +402,55 @@ namespace ImageProcessor.Web.HttpModules
{
byte[] imageBuffer = await currentService.GetImage(resourcePath);
using (MemoryStream memoryStream = new MemoryStream(imageBuffer))
using (MemoryStream inStream = 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(memoryStream);
memoryStream.Position = 0;
using (MemoryStream outStream = new MemoryStream())
{
imageFactory.Load(inStream).AutoProcess(queryString).Save(outStream);
// Add to the cache.
await this.imageCache.AddImageToCacheAsync(memoryStream, imageFactory.CurrentImageFormat.MimeType);
// Add to the cache.
await this.imageCache.AddImageToCacheAsync(outStream, imageFactory.CurrentImageFormat.MimeType);
}
}
// 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;
bool isFileCached = new Uri(cachedPath).IsFile;
// 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;
bool isFileCached = new Uri(cachedPath).IsFile;
if (isFileLocal)
if (isFileLocal)
{
if (isFileCached)
{
if (isFileCached)
{
// Some services might only provide filename so we can't monitor for the browser.
context.Items[CachedResponseFileDependency] = Path.GetFileName(requestPath) == requestPath
? new List<string> { cachedPath }
: new List<string> { requestPath, cachedPath };
}
else
{
context.Items[CachedResponseFileDependency] = Path.GetFileName(requestPath) == requestPath
? null
: new List<string> { requestPath };
}
// Some services might only provide filename so we can't monitor for the browser.
context.Items[CachedResponseFileDependency] = Path.GetFileName(requestPath) == requestPath
? new List<string> { cachedPath }
: new List<string> { requestPath, cachedPath };
}
else if (isFileCached)
else
{
context.Items[CachedResponseFileDependency] = new List<string> { cachedPath };
context.Items[CachedResponseFileDependency] = Path.GetFileName(requestPath) == requestPath
? null
: new List<string> { requestPath };
}
}
else if (isFileCached)
{
context.Items[CachedResponseFileDependency] = new List<string> { cachedPath };
}
}
}
}
// The cached file is valid so just rewrite the path.
this.imageCache.RewritePath(context);
// Redirect if not a locally store file.
if (!new Uri(cachedPath).IsFile)
{
context.ApplicationInstance.CompleteRequest();
}
}
}
@ -557,11 +570,11 @@ namespace ImageProcessor.Web.HttpModules
IImageService imageService = null;
IList<IImageService> services = ImageProcessorConfiguration.Instance.ImageServices;
string path = request.Path;
string path = request.Path.TrimStart('/');
foreach (IImageService service in services)
{
string key = service.Prefix;
if (!string.IsNullOrWhiteSpace(key) && path.EndsWith(key, StringComparison.InvariantCultureIgnoreCase))
if (!string.IsNullOrWhiteSpace(key) && path.StartsWith(key, StringComparison.InvariantCultureIgnoreCase))
{
imageService = service;
}
@ -575,7 +588,6 @@ namespace ImageProcessor.Web.HttpModules
// Return the file based service
return services.FirstOrDefault(s => string.IsNullOrWhiteSpace(s.Prefix) && s.IsValidRequest(path));
}
#endregion
}
}

5
src/ImageProcessor.Web/Services/RemoteImageService.cs

@ -37,7 +37,8 @@ namespace ImageProcessor.Web.Services
this.Settings = new Dictionary<string, string>
{
{ "MaxBytes", "4194304" },
{ "Timeout", "30000" }
{ "Timeout", "30000" },
{ "Protocol", "http" }
};
this.WhiteList = new Uri[] { };
@ -105,7 +106,7 @@ namespace ImageProcessor.Web.Services
{
if (!uri.IsAbsoluteUri)
{
Uri rebaseUri = new Uri("http://" + uri.ToString().TrimStart(new[] { '.', '/' }));
Uri rebaseUri = new Uri("http://" + uri.ToString().TrimStart('.', '/'));
validUrl = upper.StartsWith(rebaseUri.Host.ToUpperInvariant()) || upper.EndsWith(rebaseUri.Host.ToUpperInvariant());
}
else

1
src/ImageProcessor.sln.DotSettings

@ -18,5 +18,6 @@
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=REF/@EntryIndexedValue">REF</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=RGB/@EntryIndexedValue">RGB</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=RGBA/@EntryIndexedValue">RGBA</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=SHA/@EntryIndexedValue">SHA</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=SRGB/@EntryIndexedValue">SRGB</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=SS/@EntryIndexedValue">SS</s:String></wpf:ResourceDictionary>

6
src/ImageProcessor/ImageFactory.cs

@ -139,6 +139,9 @@ namespace ImageProcessor
/// </returns>
public ImageFactory Load(Stream stream)
{
// Reset the position of the stream to ensure we're reading the correct part.
stream.Position = 0;
ISupportedImageFormat format = FormatUtilities.GetFormat(stream);
if (format == null)
@ -1070,8 +1073,9 @@ namespace ImageProcessor
if (this.ShouldProcess)
{
// Allow the same stream to be used as for input.
stream.Position = 0;
stream.SetLength(0);
this.Image = this.CurrentImageFormat.Save(stream, this.Image);
stream.Position = 0;
}
return this;

1
src/ImageProcessor/Imaging/Formats/FormatBase.cs

@ -108,7 +108,6 @@ namespace ImageProcessor.Imaging.Formats
public virtual Image Save(Stream stream, Image image)
{
image.Save(stream, this.ImageFormat);
stream.Position = 0;
return image;
}

18
src/TestWebsites/MVC/Global.asax.cs

@ -28,17 +28,17 @@ namespace Test_Website_NET45
RouteConfig.RegisterRoutes(RouteTable.Routes);
// Test the post processing event.
ImageProcessingModule.OnPostProcessing += (sender, args) => Debug.WriteLine(args.CachedImagePath);
//ImageProcessingModule.OnPostProcessing += (sender, args) => Debug.WriteLine(args.CachedImagePath);
ImageProcessingModule.OnProcessQuerystring += (sender, args) =>
{
if (!args.RawUrl.Contains("penguins"))
{
return args.Querystring += "watermark=protected&color=fff&fontsize=36&fontopacity=70textshadow=true&fontfamily=arial";
}
//ImageProcessingModule.OnProcessQuerystring += (sender, args) =>
// {
// if (!args.RawUrl.Contains("penguins"))
// {
// return args.Querystring += "watermark=protected&color=fff&fontsize=36&fontopacity=70textshadow=true&fontfamily=arial";
// }
return args.Querystring;
};
// return args.Querystring;
// };
}
private async void WritePath(object sender, PostProcessingEventArgs e)

3
src/TestWebsites/MVC/Views/Home/Index.cshtml

@ -7,7 +7,8 @@
<div class="row">
<div class="col-s-6">
<h2>Resized</h2>
<img src="/images/format-Penguins.jpg?width=310" />
<img src="/images/format.Penguins.jpg?width=302"/>
<img src="/remote.axd/ipcache.blob.core.windows.net/source/IMG_0671.JPG?width=302&filter=comic" />
@*<h3>Foreign language test.</h3>
<img src="/images/udendørs.jpg?width=300" />
<img src="/images/udendørs.jpg?preset=demo&filter=comic" />

2
src/TestWebsites/MVC/config/imageprocessor/security.config

@ -6,8 +6,10 @@
<settings>
<setting key="MaxBytes" value="4194304"/>
<setting key="Timeout" value="30000"/>
<setting key="Protocol" value="http"/>
</settings>
<whitelist>
<add url="http://ipcache.blob.core.windows.net/"/>
<add url="images.mymovies.net"/>
<add url="http://maps.googleapis.com"/>
<add url="fbcdn"/>

Loading…
Cancel
Save