public async Task <bool> Handle(HttpListenerContext context, CancellationToken cancellationToken) { if (context == null) { throw new ArgumentNullException(nameof(context)); } cancellationToken.ThrowIfCancellationRequested(); if (!RouteMatcher.TryMatchImageTransformRequest(context.Request.HttpMethod, context.Request.Url, out var transformType, out var coords)) { // Not our route - return false, to allow proceed to the next handler (if any) return(false); } // Ensure we have content if (context.Request.ContentLength64 <= 0) { context.SendBadRequest("Image is absent"); return(true); } // Ensure it's of valid size if (context.Request.ContentLength64 > Constants.MAX_IMAGE_SIZE) { context.SendBadRequest("Image is to big (over 100Kb)"); return(true); } cancellationToken.ThrowIfCancellationRequested(); // Check before starting long-running operation // Try read image payload IImage image; try { image = m_ImageFactory.CreateFrom(context.Request.InputStream); } catch (Exception) { context.SendBadRequest("Bad image format"); return(true); } using (image) { // Check image size if (image.Width > Constants.MAX_IMAGE_WIDTH || image.Height > Constants.MAX_IMAGE_HEIGHT) { context.SendBadRequest("Image size is to big (over 1000px in width, height or both)"); return(true); } cancellationToken.ThrowIfCancellationRequested(); // Check before starting long-running operation image.Transform(transformType); cancellationToken.ThrowIfCancellationRequested(); // Check after long running operation and before another one // Find clipping area var clipBounds = Rectangle.Intersect(image.Bounds, coords.ToRectangle()); if (clipBounds.IsEmpty) { context.SendNoContent(); return(true); } // Produce output context.Response.Headers.Add("Content-Type", "image/png"); if (clipBounds == image.Bounds) { // No clipping required - save image as is await image.SaveAsync(context.Response.OutputStream, cancellationToken); } else { using (var clippedImage = image.Copy(clipBounds)) { await clippedImage.SaveAsync(context.Response.OutputStream, cancellationToken); } } context.Response.Close(); return(true); } }
public async Task <bool> Handle(HttpListenerContext context, CancellationToken cancellationToken) { if (context == null) { throw new ArgumentNullException(nameof(context)); } cancellationToken.ThrowIfCancellationRequested(); if (!RouteMatcher.TryMatchImageFilterRequest(context.Request.HttpMethod, context.Request.Url, out var filterDefinition, out var coords)) { // Not our route - return false, to allow proceed to the next handler (if any) return(false); } // Ensure we have content if (context.Request.ContentLength64 <= 0) { context.SendBadRequest("Image is absent"); return(true); } // Ensure it's of valid size if (context.Request.ContentLength64 > Constants.MAX_IMAGE_SIZE) { context.SendBadRequest("Image is to big (over 100Kb)"); return(true); } // Ensure filter is known var filter = m_Filters.GetFilterByDefinition(filterDefinition); if (filter == null) { context.SendBadRequest($"Unknown filter '{filterDefinition}'"); return(true); } cancellationToken.ThrowIfCancellationRequested(); // Check before starting long-running operation // Try read image payload IImage image; try { image = m_ImageFactory.CreateFrom(context.Request.InputStream); } catch (Exception) { context.SendBadRequest("Bad image format"); return(true); } using (image) { // Check image size if (image.Width > Constants.MAX_IMAGE_WIDTH || image.Height > Constants.MAX_IMAGE_HEIGHT) { context.SendBadRequest("Image size to big"); return(true); } cancellationToken.ThrowIfCancellationRequested(); // Check after long running operation // Find intersection area var filterBounds = Rectangle.Intersect(image.Bounds, coords.ToRectangle()); if (filterBounds.IsEmpty) { context.SendNoContent(); return(true); } cancellationToken.ThrowIfCancellationRequested(); // Check before starting long-running operation await filter.Apply(image, filterBounds, cancellationToken); cancellationToken.ThrowIfCancellationRequested(); // Check after long running operation and before another one using (var copy = image.Copy(filterBounds)) { context.Response.AddHeader("Content-Type", "image/png"); await copy.SaveAsync(context.Response.OutputStream, cancellationToken); context.Response.Close(); } return(true); } }