/// <summary> /// Helper method that returns the redirect url or null /// </summary> /// <param name="path">The path to get the redirect url for</param> /// <returns>The target url, or <c>null</c></returns> public async Task <string> GetRedirecLinkAsync(string path) { if (!FoundCache.TryGetValue(path, out var le)) { var notFound = await NotFoundCache.TryGetUnlessAsync(path, (a, b) => b < DateTime.Now); if (notFound.Key) { return(null); } le = await DB.RunInTransactionAsync(db => db.SelectSingle <LinkEntry>(x => x.Match == path)); if (le == null) { await NotFoundCache.AddOrReplaceAsync(path, DateTime.Now.Add(ExpireTimeout)); } else { await FoundCache.AddOrReplaceAsync(path, le); } } if (le != null && le.Enabled && le.IsActive) { return(le.TargetUrl); } return(null); }
public async Task <IResult> Get( [Parameter(ParameterSource.Url)] string id, [Parameter(ParameterSource.Query, required: false, name: "w")] int w = 0, [Parameter(ParameterSource.Query, required: false, name: "h")] int h = 0 ) { if (string.IsNullOrWhiteSpace(id)) { return(NotFound); } // Clamp the values w = Math.Min(Math.Max(0, w), MAX_DIMENSIONS); h = Math.Min(Math.Max(0, h), MAX_DIMENSIONS); var mapentry = await DB.RunInTransactionAsync(db => db.SelectItemById <Database.ImageMap>(id)); if (mapentry == null) { return(NotFound); } var resp = Context.Response; if (w == 0 && h == 0) { if (!string.IsNullOrWhiteSpace(mapentry.Sha256) && string.Equals(mapentry.Sha256, Context.Request.Headers["If-None-Match"])) { return(Status(HttpStatusCode.NotModified)); } var fi = new FileInfo(mapentry.Path); if (!fi.Exists) { return(NotFound); } resp.ContentLength = fi.Length; if (!string.IsNullOrWhiteSpace(mapentry.ContentType)) { resp.ContentType = mapentry.ContentType; } resp.StatusCode = HttpStatusCode.OK; resp.SetExpires(TimeSpan.FromHours(6)); if (!string.IsNullOrWhiteSpace(mapentry.Sha256)) { resp.AddHeader("ETag", mapentry.Sha256); } await resp.FlushHeadersAsync(); using (var s = File.OpenRead(mapentry.Path)) using (var rs = resp.GetResponseStream()) await s.CopyToAsync(rs); return(null); } var url = SyntheticUrl(id, w, h); if (!m_resizecache.TryGetValue(url, out var data)) { using (var img = Image.Load(mapentry.Path, out var format)) using (var ms = new MemoryStream()) using (var sha256 = System.Security.Cryptography.SHA256.Create()) { var enc = GetEncoder(format.Name); img.Mutate(x => x.Resize(w, h)); img.Metadata.ExifProfile = null; img.Save(ms, enc); var bytes = ms.ToArray(); data = new KeyValuePair <string, byte[]>(Convert.ToBase64String(sha256.ComputeHash(bytes)), bytes); } await m_resizecache.AddOrReplaceAsync(url, data); } else { if (string.Equals(data.Key, Context.Request.Headers["If-None-Match"])) { return(Status(HttpStatusCode.NotModified)); } } resp.ContentLength = data.Value.Length; if (!string.IsNullOrWhiteSpace(mapentry.ContentType)) { resp.ContentType = mapentry.ContentType; } resp.StatusCode = HttpStatusCode.OK; resp.SetExpires(TimeSpan.FromHours(6)); resp.AddHeader("ETag", data.Key); await resp.FlushHeadersAsync(); using (var rs = resp.GetResponseStream()) await rs.WriteAsync(data.Value, 0, data.Value.Length); return(null); }