mirror of
https://github.com/nsnail/Ocelot.git
synced 2025-06-19 19:58:14 +08:00
Feature/dont validate cached content headers (#406)
* #372 use period timespan to decide when client can make requests again * #400 dont validate cached body headers
This commit is contained in:
@ -1,120 +1,120 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using Ocelot.Logging;
|
||||
using Ocelot.Middleware;
|
||||
using System.IO;
|
||||
using Ocelot.Middleware.Multiplexer;
|
||||
|
||||
namespace Ocelot.Cache.Middleware
|
||||
{
|
||||
public class OutputCacheMiddleware : OcelotMiddleware
|
||||
{
|
||||
private readonly OcelotRequestDelegate _next;
|
||||
private readonly IOcelotCache<CachedResponse> _outputCache;
|
||||
private readonly IRegionCreator _regionCreator;
|
||||
|
||||
public OutputCacheMiddleware(OcelotRequestDelegate next,
|
||||
IOcelotLoggerFactory loggerFactory,
|
||||
IOcelotCache<CachedResponse> outputCache,
|
||||
IRegionCreator regionCreator)
|
||||
:base(loggerFactory.CreateLogger<OutputCacheMiddleware>())
|
||||
{
|
||||
_next = next;
|
||||
_outputCache = outputCache;
|
||||
_regionCreator = regionCreator;
|
||||
}
|
||||
|
||||
public async Task Invoke(DownstreamContext context)
|
||||
{
|
||||
if (!context.DownstreamReRoute.IsCached)
|
||||
{
|
||||
await _next.Invoke(context);
|
||||
return;
|
||||
}
|
||||
|
||||
var downstreamUrlKey = $"{context.DownstreamRequest.Method}-{context.DownstreamRequest.OriginalString}";
|
||||
|
||||
Logger.LogDebug($"Started checking cache for {downstreamUrlKey}");
|
||||
|
||||
var cached = _outputCache.Get(downstreamUrlKey, context.DownstreamReRoute.CacheOptions.Region);
|
||||
|
||||
if (cached != null)
|
||||
{
|
||||
Logger.LogDebug($"cache entry exists for {downstreamUrlKey}");
|
||||
|
||||
var response = CreateHttpResponseMessage(cached);
|
||||
SetHttpResponseMessageThisRequest(context, response);
|
||||
|
||||
Logger.LogDebug($"finished returned cached response for {downstreamUrlKey}");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Logger.LogDebug($"no resonse cached for {downstreamUrlKey}");
|
||||
|
||||
await _next.Invoke(context);
|
||||
|
||||
if (context.IsError)
|
||||
{
|
||||
Logger.LogDebug($"there was a pipeline error for {downstreamUrlKey}");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
cached = await CreateCachedResponse(context.DownstreamResponse);
|
||||
|
||||
_outputCache.Add(downstreamUrlKey, cached, TimeSpan.FromSeconds(context.DownstreamReRoute.CacheOptions.TtlSeconds), context.DownstreamReRoute.CacheOptions.Region);
|
||||
|
||||
Logger.LogDebug($"finished response added to cache for {downstreamUrlKey}");
|
||||
}
|
||||
|
||||
private void SetHttpResponseMessageThisRequest(DownstreamContext context, DownstreamResponse response)
|
||||
{
|
||||
context.DownstreamResponse = response;
|
||||
}
|
||||
|
||||
internal DownstreamResponse CreateHttpResponseMessage(CachedResponse cached)
|
||||
{
|
||||
if (cached == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var content = new MemoryStream(Convert.FromBase64String(cached.Body));
|
||||
|
||||
var streamContent = new StreamContent(content);
|
||||
|
||||
foreach (var header in cached.ContentHeaders)
|
||||
{
|
||||
streamContent.Headers.Add(header.Key, header.Value);
|
||||
}
|
||||
|
||||
return new DownstreamResponse(streamContent, cached.StatusCode, cached.Headers.ToList());
|
||||
}
|
||||
|
||||
internal async Task<CachedResponse> CreateCachedResponse(DownstreamResponse response)
|
||||
{
|
||||
if (response == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var statusCode = response.StatusCode;
|
||||
var headers = response.Headers.ToDictionary(v => v.Key, v => v.Values);
|
||||
string body = null;
|
||||
|
||||
if (response.Content != null)
|
||||
{
|
||||
var content = await response.Content.ReadAsByteArrayAsync();
|
||||
body = Convert.ToBase64String(content);
|
||||
}
|
||||
|
||||
var contentHeaders = response?.Content?.Headers.ToDictionary(v => v.Key, v => v.Value);
|
||||
|
||||
var cached = new CachedResponse(statusCode, headers, body, contentHeaders);
|
||||
return cached;
|
||||
}
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using Ocelot.Logging;
|
||||
using Ocelot.Middleware;
|
||||
using System.IO;
|
||||
using Ocelot.Middleware.Multiplexer;
|
||||
|
||||
namespace Ocelot.Cache.Middleware
|
||||
{
|
||||
public class OutputCacheMiddleware : OcelotMiddleware
|
||||
{
|
||||
private readonly OcelotRequestDelegate _next;
|
||||
private readonly IOcelotCache<CachedResponse> _outputCache;
|
||||
private readonly IRegionCreator _regionCreator;
|
||||
|
||||
public OutputCacheMiddleware(OcelotRequestDelegate next,
|
||||
IOcelotLoggerFactory loggerFactory,
|
||||
IOcelotCache<CachedResponse> outputCache,
|
||||
IRegionCreator regionCreator)
|
||||
:base(loggerFactory.CreateLogger<OutputCacheMiddleware>())
|
||||
{
|
||||
_next = next;
|
||||
_outputCache = outputCache;
|
||||
_regionCreator = regionCreator;
|
||||
}
|
||||
|
||||
public async Task Invoke(DownstreamContext context)
|
||||
{
|
||||
if (!context.DownstreamReRoute.IsCached)
|
||||
{
|
||||
await _next.Invoke(context);
|
||||
return;
|
||||
}
|
||||
|
||||
var downstreamUrlKey = $"{context.DownstreamRequest.Method}-{context.DownstreamRequest.OriginalString}";
|
||||
|
||||
Logger.LogDebug($"Started checking cache for {downstreamUrlKey}");
|
||||
|
||||
var cached = _outputCache.Get(downstreamUrlKey, context.DownstreamReRoute.CacheOptions.Region);
|
||||
|
||||
if (cached != null)
|
||||
{
|
||||
Logger.LogDebug($"cache entry exists for {downstreamUrlKey}");
|
||||
|
||||
var response = CreateHttpResponseMessage(cached);
|
||||
SetHttpResponseMessageThisRequest(context, response);
|
||||
|
||||
Logger.LogDebug($"finished returned cached response for {downstreamUrlKey}");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Logger.LogDebug($"no resonse cached for {downstreamUrlKey}");
|
||||
|
||||
await _next.Invoke(context);
|
||||
|
||||
if (context.IsError)
|
||||
{
|
||||
Logger.LogDebug($"there was a pipeline error for {downstreamUrlKey}");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
cached = await CreateCachedResponse(context.DownstreamResponse);
|
||||
|
||||
_outputCache.Add(downstreamUrlKey, cached, TimeSpan.FromSeconds(context.DownstreamReRoute.CacheOptions.TtlSeconds), context.DownstreamReRoute.CacheOptions.Region);
|
||||
|
||||
Logger.LogDebug($"finished response added to cache for {downstreamUrlKey}");
|
||||
}
|
||||
|
||||
private void SetHttpResponseMessageThisRequest(DownstreamContext context, DownstreamResponse response)
|
||||
{
|
||||
context.DownstreamResponse = response;
|
||||
}
|
||||
|
||||
internal DownstreamResponse CreateHttpResponseMessage(CachedResponse cached)
|
||||
{
|
||||
if (cached == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var content = new MemoryStream(Convert.FromBase64String(cached.Body));
|
||||
|
||||
var streamContent = new StreamContent(content);
|
||||
|
||||
foreach (var header in cached.ContentHeaders)
|
||||
{
|
||||
streamContent.Headers.TryAddWithoutValidation(header.Key, header.Value);
|
||||
}
|
||||
|
||||
return new DownstreamResponse(streamContent, cached.StatusCode, cached.Headers.ToList());
|
||||
}
|
||||
|
||||
internal async Task<CachedResponse> CreateCachedResponse(DownstreamResponse response)
|
||||
{
|
||||
if (response == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var statusCode = response.StatusCode;
|
||||
var headers = response.Headers.ToDictionary(v => v.Key, v => v.Values);
|
||||
string body = null;
|
||||
|
||||
if (response.Content != null)
|
||||
{
|
||||
var content = await response.Content.ReadAsByteArrayAsync();
|
||||
body = Convert.ToBase64String(content);
|
||||
}
|
||||
|
||||
var contentHeaders = response?.Content?.Headers.ToDictionary(v => v.Key, v => v.Value);
|
||||
|
||||
var cached = new CachedResponse(statusCode, headers, body, contentHeaders);
|
||||
return cached;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user