Skip to content

Commit 8255bad

Browse files
Reintroduce tasks with config validation.
1 parent 7085e8b commit 8255bad

File tree

7 files changed

+133
-49
lines changed

7 files changed

+133
-49
lines changed

samples/ImageSharp.Web.Sample/Startup.cs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Licensed under the Apache License, Version 2.0.
33

44
using System;
5+
using System.Threading.Tasks;
56
using Microsoft.AspNetCore.Builder;
67
using Microsoft.AspNetCore.Hosting;
78
using Microsoft.Extensions.Configuration;
@@ -86,10 +87,10 @@ private void ConfigureDefaultServicesAndCustomOptions(IServiceCollection service
8687
options.BrowserMaxAge = TimeSpan.FromDays(7);
8788
options.CacheMaxAge = TimeSpan.FromDays(365);
8889
options.CachedNameLength = 8;
89-
options.OnParseCommands = _ => { };
90-
options.OnBeforeSave = _ => { };
91-
options.OnProcessed = _ => { };
92-
options.OnPrepareResponse = _ => { };
90+
options.OnParseCommandsAsync = _ => Task.CompletedTask;
91+
options.OnBeforeSaveAsync = _ => Task.CompletedTask;
92+
options.OnProcessedAsync = _ => Task.CompletedTask;
93+
options.OnPrepareResponseAsync = _ => Task.CompletedTask;
9394
});
9495
}
9596

@@ -109,10 +110,10 @@ private void ConfigureCustomServicesAndCustomOptions(IServiceCollection services
109110
options.BrowserMaxAge = TimeSpan.FromDays(7);
110111
options.CacheMaxAge = TimeSpan.FromDays(365);
111112
options.CachedNameLength = 8;
112-
options.OnParseCommands = _ => { };
113-
options.OnBeforeSave = _ => { };
114-
options.OnProcessed = _ => { };
115-
options.OnPrepareResponse = _ => { };
113+
options.OnParseCommandsAsync = _ => Task.CompletedTask;
114+
options.OnBeforeSaveAsync = _ => Task.CompletedTask;
115+
options.OnProcessedAsync = _ => Task.CompletedTask;
116+
options.OnPrepareResponseAsync = _ => Task.CompletedTask;
116117
})
117118
.SetRequestParser<QueryCollectionRequestParser>()
118119
.Configure<PhysicalFileSystemCacheOptions>(options =>

src/ImageSharp.Web/Middleware/ImageContext.cs

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -111,13 +111,19 @@ public void ComprehendRequestHeaders(DateTimeOffset lastModified, long length)
111111
/// Gets the preconditioned state of the request.
112112
/// </summary>
113113
/// <returns>The <see cref="PreconditionState"/>.</returns>
114-
public PreconditionState GetPreconditionState() => GetMaxPreconditionState(this.ifMatchState, this.ifNoneMatchState, this.ifModifiedSinceState, this.ifUnmodifiedSinceState);
114+
public PreconditionState GetPreconditionState()
115+
=> GetMaxPreconditionState(
116+
this.ifMatchState,
117+
this.ifNoneMatchState,
118+
this.ifModifiedSinceState,
119+
this.ifUnmodifiedSinceState);
115120

116121
/// <summary>
117122
/// Gets a value indicating whether this request is a head request.
118123
/// </summary>
119124
/// <returns>THe <see cref="bool"/>.</returns>
120-
public bool IsHeadRequest() => string.Equals("HEAD", this.request.Method, StringComparison.OrdinalIgnoreCase);
125+
public bool IsHeadRequest()
126+
=> string.Equals("HEAD", this.request.Method, StringComparison.OrdinalIgnoreCase);
121127

122128
/// <summary>
123129
/// Set the response status headers.
@@ -126,12 +132,10 @@ public void ComprehendRequestHeaders(DateTimeOffset lastModified, long length)
126132
/// <param name="metaData">The image metadata.</param>
127133
/// <returns>The <see cref="Task"/>.</returns>
128134
public Task SendStatusAsync(int statusCode, in ImageCacheMetadata metaData)
129-
{
130-
this.ApplyResponseHeaders(statusCode, metaData.ContentType, metaData.CacheControlMaxAge);
131-
132-
// this.logger.LogHandled(statusCode, SubPath);
133-
return ResponseConstants.CompletedTask;
134-
}
135+
=> this.ApplyResponseHeadersAsync(
136+
statusCode,
137+
metaData.ContentType,
138+
metaData.CacheControlMaxAge);
135139

136140
/// <summary>
137141
/// Set the response content.
@@ -141,7 +145,10 @@ public Task SendStatusAsync(int statusCode, in ImageCacheMetadata metaData)
141145
/// <returns>The <see cref="Task"/>.</returns>
142146
public async Task SendAsync(Stream stream, ImageCacheMetadata metaData)
143147
{
144-
this.ApplyResponseHeaders(ResponseConstants.Status200Ok, metaData.ContentType, metaData.CacheControlMaxAge);
148+
await this.ApplyResponseHeadersAsync(
149+
ResponseConstants.Status200Ok,
150+
metaData.ContentType,
151+
metaData.CacheControlMaxAge);
145152

146153
if (stream.CanSeek)
147154
{
@@ -170,7 +177,10 @@ private static PreconditionState GetMaxPreconditionState(params PreconditionStat
170177
return max;
171178
}
172179

173-
private void ApplyResponseHeaders(int statusCode, string contentType, TimeSpan maxAge)
180+
private async Task ApplyResponseHeadersAsync(
181+
int statusCode,
182+
string contentType,
183+
TimeSpan maxAge)
174184
{
175185
this.response.StatusCode = statusCode;
176186
if (statusCode < 400)
@@ -193,7 +203,7 @@ private void ApplyResponseHeaders(int statusCode, string contentType, TimeSpan m
193203
MustRevalidate = true
194204
};
195205

196-
this.options.OnPrepareResponse?.Invoke(this.context);
206+
await this.options.OnPrepareResponseAsync.Invoke(this.context);
197207
}
198208

199209
if (statusCode == ResponseConstants.Status200Ok)

src/ImageSharp.Web/Middleware/ImageSharpMiddleware.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,8 @@ public async Task Invoke(HttpContext context)
159159
}
160160
}
161161

162-
this.options.OnParseCommands?.Invoke(new ImageCommandContext(context, commands, CommandParser.Instance));
162+
await this.options.OnParseCommandsAsync.Invoke(
163+
new ImageCommandContext(context, commands, CommandParser.Instance));
163164

164165
// Get the correct service for the request.
165166
IImageProvider provider = null;
@@ -244,7 +245,7 @@ private async Task ProcessRequestAsync(
244245
{
245246
using var image = FormattedImage.Load(this.options.Configuration, inStream);
246247
image.Process(this.logger, this.processors, commands);
247-
this.options.OnBeforeSave?.Invoke(image);
248+
await this.options.OnBeforeSaveAsync.Invoke(image);
248249
image.Save(outStream);
249250
format = image.Format;
250251
}
@@ -270,7 +271,7 @@ private async Task ProcessRequestAsync(
270271
outStream.Position = 0;
271272
string contentType = cachedImageMetadata.ContentType;
272273
string extension = this.formatUtilities.GetExtensionFromContentType(contentType);
273-
this.options.OnProcessed?.Invoke(new ImageProcessingContext(context, outStream, commands, contentType, extension));
274+
await this.options.OnProcessedAsync.Invoke(new ImageProcessingContext(context, outStream, commands, contentType, extension));
274275
outStream.Position = 0;
275276

276277
// Save the image to the cache and send the response to the caller.

src/ImageSharp.Web/Middleware/ImageSharpMiddlewareOptions.cs

Lines changed: 73 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,31 @@ namespace SixLabors.ImageSharp.Web.Middleware
1616
/// </summary>
1717
public class ImageSharpMiddlewareOptions
1818
{
19+
private Func<ImageCommandContext, Task> onParseCommandsAsync = c =>
20+
{
21+
if (c.Commands.Count == 0)
22+
{
23+
return Task.CompletedTask;
24+
}
25+
26+
// It's a good idea to have this to provide very basic security.
27+
// We can safely use the static resize processor properties.
28+
uint width = c.Parser.ParseValue<uint>(c.Commands.GetValueOrDefault(ResizeWebProcessor.Width));
29+
uint height = c.Parser.ParseValue<uint>(c.Commands.GetValueOrDefault(ResizeWebProcessor.Height));
30+
31+
if (width > 4000 && height > 4000)
32+
{
33+
c.Commands.Remove(ResizeWebProcessor.Width);
34+
c.Commands.Remove(ResizeWebProcessor.Height);
35+
}
36+
37+
return Task.CompletedTask;
38+
};
39+
40+
private Func<FormattedImage, Task> onBeforeSaveAsync = _ => Task.CompletedTask;
41+
private Func<ImageProcessingContext, Task> onProcessedAsync = _ => Task.CompletedTask;
42+
private Func<HttpContext, Task> onPrepareResponseAsync = _ => Task.CompletedTask;
43+
1944
/// <summary>
2045
/// Gets or sets the base library configuration.
2146
/// </summary>
@@ -55,44 +80,75 @@ public class ImageSharpMiddlewareOptions
5580
/// Gets or sets the additional command parsing method that can be used to used to augment commands.
5681
/// This is called once the commands have been gathered and before an <see cref="IImageProvider"/> has been assigned.
5782
/// </summary>
58-
public Func<ImageCommandContext, ValueTask> OnParseCommandsAsync { get; set; } = c =>
83+
public Func<ImageCommandContext, Task> OnParseCommandsAsync
5984
{
60-
if (c.Commands.Count != 0)
85+
get
6186
{
62-
// It's a good idea to have this to provide very basic security.
63-
// We can safely use the static resize processor properties.
64-
uint width = c.Parser.ParseValue<uint>(c.Commands.GetValueOrDefault(ResizeWebProcessor.Width));
65-
uint height = c.Parser.ParseValue<uint>(c.Commands.GetValueOrDefault(ResizeWebProcessor.Height));
66-
67-
if (width > 4000 && height > 4000)
68-
{
69-
c.Commands.Remove(ResizeWebProcessor.Width);
70-
c.Commands.Remove(ResizeWebProcessor.Height);
71-
}
87+
return this.onParseCommandsAsync;
7288
}
7389

74-
return default;
75-
};
90+
set
91+
{
92+
Guard.NotNull(value, nameof(this.OnParseCommandsAsync));
93+
this.onParseCommandsAsync = value;
94+
}
95+
}
7696

7797
/// <summary>
7898
/// Gets or sets the additional method that can be used for final manipulation before the image is saved.
7999
/// This is called after image has been processed, but before the image has been saved to the output stream for caching.
80100
/// This can be used to alter the metadata of the resultant image.
81101
/// </summary>
82-
public Func<FormattedImage, ValueTask> OnBeforeSaveAsync { get; set; }
102+
public Func<FormattedImage, Task> OnBeforeSaveAsync
103+
{
104+
get
105+
{
106+
return this.onBeforeSaveAsync;
107+
}
108+
109+
set
110+
{
111+
Guard.NotNull(value, nameof(this.OnBeforeSaveAsync));
112+
this.onBeforeSaveAsync = value;
113+
}
114+
}
83115

84116
/// <summary>
85117
/// Gets or sets the additional processing method.
86118
/// This is called after image has been processed, but before the result has been cached.
87119
/// This can be used to further optimize the resultant image.
88120
/// </summary>
89-
public Func<ImageProcessingContext, ValueTask> OnProcessedAsync { get; set; }
121+
public Func<ImageProcessingContext, Task> OnProcessedAsync
122+
{
123+
get
124+
{
125+
return this.onProcessedAsync;
126+
}
127+
128+
set
129+
{
130+
Guard.NotNull(value, nameof(this.OnProcessedAsync));
131+
this.onProcessedAsync = value;
132+
}
133+
}
90134

91135
/// <summary>
92136
/// Gets or sets the additional response method.
93137
/// This is called after the status code and headers have been set, but before the body has been written.
94138
/// This can be used to add or change the response headers.
95139
/// </summary>
96-
public Func<HttpContext, ValueTask> OnPrepareResponseAsync { get; set; }
140+
public Func<HttpContext, Task> OnPrepareResponseAsync
141+
{
142+
get
143+
{
144+
return this.onPrepareResponseAsync;
145+
}
146+
147+
set
148+
{
149+
Guard.NotNull(value, nameof(this.OnPrepareResponseAsync));
150+
this.onPrepareResponseAsync = value;
151+
}
152+
}
97153
}
98154
}

src/ImageSharp.Web/Middleware/ResponseConstants.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
// Copyright (c) Six Labors.
22
// Licensed under the Apache License, Version 2.0.
33

4-
using System.Threading.Tasks;
5-
64
namespace SixLabors.ImageSharp.Web.Middleware
75
{
86
/// <summary>

tests/ImageSharp.Web.Tests/TestUtilities/AzureBlobStorageCacheTestServerFixture.cs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Copyright (c) Six Labors.
22
// Licensed under the Apache License, Version 2.0.
33

4+
using System.Threading.Tasks;
45
using Azure.Storage.Blobs.Models;
56
using Microsoft.AspNetCore.Builder;
67
using Microsoft.Extensions.DependencyInjection;
@@ -18,35 +19,43 @@ protected override void ConfigureServices(IServiceCollection services)
1819
{
1920
services.AddImageSharp(options =>
2021
{
21-
options.OnParseCommands = context =>
22+
options.OnParseCommandsAsync = context =>
2223
{
2324
Assert.NotNull(context);
2425
Assert.NotNull(context.Context);
2526
Assert.NotNull(context.Commands);
2627
Assert.NotNull(context.Parser);
28+
29+
return Task.CompletedTask;
2730
};
2831

29-
options.OnProcessed = context =>
32+
options.OnProcessedAsync = context =>
3033
{
3134
Assert.NotNull(context);
3235
Assert.NotNull(context.Commands);
3336
Assert.NotNull(context.ContentType);
3437
Assert.NotNull(context.Context);
3538
Assert.NotNull(context.Extension);
3639
Assert.NotNull(context.Stream);
40+
41+
return Task.CompletedTask;
3742
};
3843

39-
options.OnBeforeSave = context =>
44+
options.OnBeforeSaveAsync = context =>
4045
{
4146
Assert.NotNull(context);
4247
Assert.NotNull(context.Format);
4348
Assert.NotNull(context.Image);
49+
50+
return Task.CompletedTask;
4451
};
4552

46-
options.OnPrepareResponse = context =>
53+
options.OnPrepareResponseAsync = context =>
4754
{
4855
Assert.NotNull(context);
4956
Assert.NotNull(context.Response);
57+
58+
return Task.CompletedTask;
5059
};
5160
})
5261
.ClearProviders()

tests/ImageSharp.Web.Tests/TestUtilities/PhysicalFileSystemCacheTestServerFixture.cs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Copyright (c) Six Labors.
22
// Licensed under the Apache License, Version 2.0.
33

4+
using System.Threading.Tasks;
45
using Microsoft.AspNetCore.Builder;
56
using Microsoft.Extensions.DependencyInjection;
67
using SixLabors.ImageSharp.Web.DependencyInjection;
@@ -16,35 +17,43 @@ protected override void ConfigureServices(IServiceCollection services)
1617
{
1718
services.AddImageSharp(options =>
1819
{
19-
options.OnParseCommands = context =>
20+
options.OnParseCommandsAsync = context =>
2021
{
2122
Assert.NotNull(context);
2223
Assert.NotNull(context.Context);
2324
Assert.NotNull(context.Commands);
2425
Assert.NotNull(context.Parser);
26+
27+
return Task.CompletedTask;
2528
};
2629

27-
options.OnProcessed = context =>
30+
options.OnProcessedAsync = context =>
2831
{
2932
Assert.NotNull(context);
3033
Assert.NotNull(context.Commands);
3134
Assert.NotNull(context.ContentType);
3235
Assert.NotNull(context.Context);
3336
Assert.NotNull(context.Extension);
3437
Assert.NotNull(context.Stream);
38+
39+
return Task.CompletedTask;
3540
};
3641

37-
options.OnBeforeSave = context =>
42+
options.OnBeforeSaveAsync = context =>
3843
{
3944
Assert.NotNull(context);
4045
Assert.NotNull(context.Format);
4146
Assert.NotNull(context.Image);
47+
48+
return Task.CompletedTask;
4249
};
4350

44-
options.OnPrepareResponse = context =>
51+
options.OnPrepareResponseAsync = context =>
4552
{
4653
Assert.NotNull(context);
4754
Assert.NotNull(context.Response);
55+
56+
return Task.CompletedTask;
4857
};
4958
})
5059
.ClearProviders()

0 commit comments

Comments
 (0)