Esempio n. 1
0
        public async Task SetAsync(
            RedisKey key,
            string response,
            int responseStatusCode,
            Dictionary <string, string[]> headers)
        {
            var storeKey = new StoreKey {
                { "key", key }
            };
            var etag = await _eTagGenerator.GenerateETag(storeKey, response);

            var hashFields = new[]
            {
                new HashEntry(ETagKey, etag.Value),
                new HashEntry(ETagTypeKey, etag.ETagType.ToString()),
                new HashEntry(LastModifiedKey, DateTime.Now.ToString("O", CultureInfo.InvariantCulture)),
                new HashEntry(SetByRegistryKey, true.ToString(CultureInfo.InvariantCulture)),
                new HashEntry(ValueKey, response),
                new HashEntry(HeadersKey, JsonConvert.SerializeObject(headers)),
                new HashEntry(ResponseStatusCodeKey, responseStatusCode)
            };

            if (_batch == null)
            {
                var db = _redis.GetDatabase();
                await db.HashSetAsync(key, hashFields, CommandFlags.FireAndForget);
            }
            else
            {
                await _batch.HashSetAsync(key, hashFields, CommandFlags.FireAndForget);
            }
        }
Esempio n. 2
0
        private async Task GenerateValidationHeadersOnResponse(HttpContext httpContext)
        {
            // don't generate these for 304 - that's taken care of at the
            // start of the request
            if (httpContext.Response.StatusCode == StatusCodes.Status304NotModified)
            {
                return;
            }

            // This takes care of storing new tags, also after a succesful PUT/POST/PATCH.
            // Other PUT/POST/PATCH requests must thus include the new ETag as If-Match,
            // otherwise the precondition will fail.
            //
            // If an API returns a 204 No Content after PUT/PATCH, the ETag will be generated
            // from an empty response - any other user/cache must GET the response again
            // before updating it.  Getting it will result in a new ETag value being generated.
            //
            // If an API returns a 200 Ok after PUT/PATCH, the ETag will be generated from
            // that response body - if the update was succesful but nothing was changed,
            // in those cases the original ETag for other users/caches will still be sufficient.

            // if the response body cannot be read, we can never
            // generate correct ETags (and it should never be cached)
            if (!httpContext.Response.Body.CanRead)
            {
                return;
            }

            _logger.LogInformation("Generating Validation headers.");

            var headers = httpContext.Response.Headers;

            // remove any other ETag and Last-Modified headers (could be set by other pieces of code)
            headers.Remove(HeaderNames.ETag);
            headers.Remove(HeaderNames.LastModified);

            // get the request key
            var storeKey = await _storeKeyGenerator.GenerateStoreKey(
                ConstructStoreKeyContext(httpContext.Request, _validationModelOptions));

            // get the response bytes
            if (httpContext.Response.Body.CanSeek)
            {
                httpContext.Response.Body.Position = 0;
            }

            var responseBodyContent = new StreamReader(httpContext.Response.Body).ReadToEnd();

            // Calculate the ETag to store in the store.
            var eTag = await _eTagGenerator.GenerateETag(storeKey, responseBodyContent);

            var lastModified = await _lastModifiedInjector.CalculateLastModified(
                new ResourceContext(httpContext.Request, storeKey));

            var lastModifiedValue = await _dateParser.LastModifiedToString(lastModified);

            // store the ETag & LastModified date with the request key as key in the ETag store
            await _store.SetAsync(storeKey, new ValidatorValue(eTag, lastModified));

            // set the ETag and LastModified header
            headers[HeaderNames.ETag]         = eTag.ToString();
            headers[HeaderNames.LastModified] = lastModifiedValue;

            _logger.LogInformation($"Validation headers generated. ETag: {eTag.ETagType}, {eTag}. Last-Modified: {lastModifiedValue}");
        }
Esempio n. 3
0
 private async Task GenerateETagHeaderAsync(HttpContext context)
 {
     context.Response.GetTypedHeaders().ETag = await _eTagGenerator.GenerateETag(context);
 }