/// <summary> /// Immutable content /// </summary> public async Task Execute(HttpContext httpContext, string type, string id) { if (httpContext == null) { throw new ArgumentNullException(nameof(httpContext)); } if (!ContentTypes.IsValid(type)) { _Logger.LogError("Invalid generic content type - {Id}.", id); httpContext.Response.StatusCode = 400; httpContext.Response.ContentLength = 0; } if (!_PublishingIdService.Validate(id)) { _Logger.LogError("Invalid content id - {Id}.", id); httpContext.Response.StatusCode = 400; httpContext.Response.ContentLength = 0; } if (!httpContext.Request.Headers.TryGetValue("if-none-match", out var etagValue)) { _Logger.LogError("Required request header missing - if-none-match."); httpContext.Response.ContentLength = 0; httpContext.Response.StatusCode = 400; } var content = await _DbContext.SafeGetContent(type, id, _DateTimeProvider.Snapshot); if (content == null) { _Logger.LogError("Content not found - {Id}.", id); httpContext.Response.StatusCode = 404; httpContext.Response.ContentLength = 0; return; } if (etagValue == content.PublishingId) { _Logger.LogWarning("Matching etag found, responding with 304 - {Id}.", id); httpContext.Response.StatusCode = 304; httpContext.Response.ContentLength = 0; return; } httpContext.Response.Headers.Add("etag", content.PublishingId); httpContext.Response.Headers.Add("last-modified", content.Release.ToUniversalTime().ToString("r")); httpContext.Response.Headers.Add("content-type", content.ContentTypeName); httpContext.Response.Headers.Add("cache-control", _HttpResponseHeaderConfig.ImmutableContentCacheControl); httpContext.Response.StatusCode = 200; httpContext.Response.ContentLength = content.Content?.Length ?? throw new InvalidOperationException("SignedContent empty."); await httpContext.Response.Body.WriteAsync(content.Content); }
public bool IsValid(ContentArgs args) { if (args == null) { return(false); } if (!ContentTypes.IsValid(args.ContentType)) { return(false); } if (!IsValidJson(args.Json)) { return(false); } return(true); }
public async Task Execute(HttpContext httpContext, string genericContentName, string id) { if (httpContext == null) { throw new ArgumentNullException(nameof(httpContext)); } if (!ContentTypes.IsValid(genericContentName)) { _Logger.LogError($"Invalid generic content type - {id}."); httpContext.Response.StatusCode = 400; httpContext.Response.ContentLength = 0; } if (!_PublishingId.Validate(id)) { _Logger.LogError($"Invalid content id - {id}."); httpContext.Response.StatusCode = 400; httpContext.Response.ContentLength = 0; } //This looked like a bug? if (!httpContext.Request.Headers.TryGetValue("if-none-match", out var etagValue)) { _Logger.LogError($"Required request header missing - if-none-match."); httpContext.Response.ContentLength = 0; httpContext.Response.StatusCode = 400; //TODO! } var content = await _DbContext.SafeGetContent(genericContentName, id); if (content == null) { //TODO tell CDN to ignore hunting? _Logger.LogError($"Content not found - {id}."); httpContext.Response.StatusCode = 404; httpContext.Response.ContentLength = 0; return; } if (etagValue == content.PublishingId) { _Logger.LogWarning($"Matching etag found, responding with 304 - {id}."); httpContext.Response.StatusCode = 304; httpContext.Response.ContentLength = 0; return; } //var accepts = httpContext.Request.Headers["accept"].ToHashSet(); //var signedResponse = content.SignedContentTypeName != null && accepts.Contains(content.SignedContentTypeName); //if (!signedResponse && !accepts.Contains(content.ContentTypeName)) //{ // _Logger.LogWarning($"Cannot give acceptable response, responding with 406 - {id}."); // httpContext.Response.StatusCode = 406; // httpContext.Response.ContentLength = 0; // return; //} httpContext.Response.Headers.Add("etag", content.PublishingId); httpContext.Response.Headers.Add("last-modified", content.Release.ToUniversalTime().ToString("r")); httpContext.Response.Headers.Add("content-type", content.ContentTypeName); httpContext.Response.Headers.Add("cache-control", _HttpResponseHeaderConfig.ImmutableContentCacheControl); httpContext.Response.StatusCode = 200; httpContext.Response.ContentLength = content.Content?.Length ?? throw new InvalidOperationException("SignedContent empty."); await httpContext.Response.Body.WriteAsync(content.Content); }