[ExcludeFromCodeCoverage] //Mostly using the ImageSharp SDK so not worth testing. public IActionResult Run([HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequest req, ILogger log) { // Configure logging ScopedData data = new ScopedData(); if (data.InitialiseFromRequestHeaders(req)) { data.Apply(); } try { log.LogInformation("{functionName}: Image resize starting", FunctionName); using Image image = Image.Load(req.Body); // Note we don't dispose this stream on purpose as it's used by the http server plumbing to serve the reponse. MemoryStream output = new MemoryStream(); // Resize things down to a max width of x to ensure they're small enough for cog services if (image.Width > ResizeToWidthPixels) { // If you pass 0 as any of the values for width and height dimensions then ImageSharp will automatically determine the correct opposite dimensions size to preserve the original aspect ratio. // https://docs.sixlabors.com/articles/imagesharp/resize.html image.Mutate(x => x.Resize(ResizeToWidthPixels, 0)); } image.Save(output, new JpegEncoder()); output.Position = 0; log.LogInformation("{functionName}: Image resize complete sending result", FunctionName); return(new FileStreamResult(output, ReturnedContentType)); } catch (Exception ex) { log.LogError(ex, "{functionName}: Failed to resize image", FunctionName); ObjectResult internalErrorResponse = new ObjectResult($"Failed while attempting to resize image: {ex.Message}") { // Ensure a 500 response code as likely to be retryable error StatusCode = 500 }; return(internalErrorResponse); } finally { log.LogInformation("{functionName}: Completed", FunctionName); } }
/// <summary> /// Extension method to initialise the ScopedData instance from an incoming http Request. /// </summary> /// <param name="data">Reference to ScopedData instance.</param> /// <param name="req">The incoming http request.</param> /// <returns>boolean indicating whether any of the values have been set.</returns> public static bool InitialiseFromRequestHeaders(this ScopedData data, HttpRequest req) { bool updated = false; // If we have a correlation id in the header use it. This is preferred as we can still // log the creation of the BlobInfo object. if (req.Headers.ContainsKey(GeneralConstants.CorrelationIdHeaderName)) { StringValues correlationId = req.Headers[GeneralConstants.CorrelationIdHeaderName]; // We don't currently support a non-guid correlation id if (!Guid.TryParse(correlationId, out Guid corrId)) { throw new NotSupportedException($"The {GeneralConstants.CorrelationIdHeaderName} header is not a valid Guid"); } data.AddCustomData(GeneralConstants.CorrelationIdKey, corrId.ToString()); updated = true; } return(updated); }
[ExcludeFromCodeCoverage] //This function just calls other services which are tested so there is no logic here that can be tested. public async Task RunAsync([EventGridTrigger] EventGridEvent eventGridEvent, ILogger log) { try { // Get data from event grid event dynamic eventGridEventData = JsonConvert.DeserializeObject(eventGridEvent.Data.ToString()); Uri uri = new Uri(eventGridEventData.url.ToString()); // Generate correlation id and set Telemetry Guid correlation = _blobInfoFactoryService.CreateCorrelationId(); ScopedData scopedData = new ScopedData(); scopedData.AddCustomData(GeneralConstants.CorrelationIdKey, correlation.ToString()).Apply(); log.LogInformation("Started: {functionName} {uri}, {name}", _functionName, uri, uri.Segments.Last()); // Exclude empty files and folders if (!string.IsNullOrEmpty(uri.AbsoluteUri)) { // Generate BlobInfo BlobInfo blobInfo = _blobInfoFactoryService.CreateBlobInfo(uri, uri.Segments.Last(), correlation); log.LogInformation("{functionName}: created BlobInfo", _functionName); // Send service bus message await _serviceBusService.SubmitBlobInfoToServiceBus(blobInfo); log.LogInformation("{functionName}: submitted BlobInfo to Service Bus", _functionName); } } catch (Exception ex) { log.LogError(ex, "{functionName}: Failed to submit BlobInfo to Service Bus for {eventData}", _functionName, eventGridEvent.Data.ToString()); throw; } finally { log.LogInformation("{functionName}: Completed {eventData}", _functionName, eventGridEvent.Data.ToString()); } }