mirror of
https://github.com/nsnail/Ocelot.git
synced 2025-06-19 10:38:15 +08:00
* #464 added code to request mapper to not automatically add content type and content length headers, .net will automatically try and add these headers in a few circumstances but this solves the 464 issue * #464 use seek instead of read on body check for websockets tests * #464 ran out of inodes on linux, looks like reloadonchange causes this
This commit is contained in:
@ -1,61 +1,61 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Errors;
|
||||
using Ocelot.Infrastructure.Extensions;
|
||||
using Ocelot.Logging;
|
||||
using Ocelot.Middleware;
|
||||
|
||||
namespace Ocelot.Authentication.Middleware
|
||||
{
|
||||
public class AuthenticationMiddleware : OcelotMiddleware
|
||||
{
|
||||
private readonly OcelotRequestDelegate _next;
|
||||
|
||||
public AuthenticationMiddleware(OcelotRequestDelegate next,
|
||||
IOcelotLoggerFactory loggerFactory)
|
||||
: base(loggerFactory.CreateLogger<AuthenticationMiddleware>())
|
||||
{
|
||||
_next = next;
|
||||
}
|
||||
|
||||
public async Task Invoke(DownstreamContext context)
|
||||
{
|
||||
if (IsAuthenticatedRoute(context.DownstreamReRoute))
|
||||
{
|
||||
Logger.LogInformation($"{context.HttpContext.Request.Path} is an authenticated route. {MiddlewareName} checking if client is authenticated");
|
||||
|
||||
var result = await context.HttpContext.AuthenticateAsync(context.DownstreamReRoute.AuthenticationOptions.AuthenticationProviderKey);
|
||||
|
||||
context.HttpContext.User = result.Principal;
|
||||
|
||||
if (context.HttpContext.User.Identity.IsAuthenticated)
|
||||
{
|
||||
Logger.LogInformation($"Client has been authenticated for {context.HttpContext.Request.Path}");
|
||||
await _next.Invoke(context);
|
||||
}
|
||||
else
|
||||
{
|
||||
var error = new UnauthenticatedError(
|
||||
$"Request for authenticated route {context.HttpContext.Request.Path} by {context.HttpContext.User.Identity.Name} was unauthenticated");
|
||||
|
||||
Logger.LogWarning($"Client has NOT been authenticated for {context.HttpContext.Request.Path} and pipeline error set. {error}");
|
||||
|
||||
SetPipelineError(context, error);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.LogInformation($"No authentication needed for {context.HttpContext.Request.Path}");
|
||||
|
||||
await _next.Invoke(context);
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsAuthenticatedRoute(DownstreamReRoute reRoute)
|
||||
{
|
||||
return reRoute.IsAuthenticated;
|
||||
}
|
||||
}
|
||||
}
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Errors;
|
||||
using Ocelot.Infrastructure.Extensions;
|
||||
using Ocelot.Logging;
|
||||
using Ocelot.Middleware;
|
||||
|
||||
namespace Ocelot.Authentication.Middleware
|
||||
{
|
||||
public class AuthenticationMiddleware : OcelotMiddleware
|
||||
{
|
||||
private readonly OcelotRequestDelegate _next;
|
||||
|
||||
public AuthenticationMiddleware(OcelotRequestDelegate next,
|
||||
IOcelotLoggerFactory loggerFactory)
|
||||
: base(loggerFactory.CreateLogger<AuthenticationMiddleware>())
|
||||
{
|
||||
_next = next;
|
||||
}
|
||||
|
||||
public async Task Invoke(DownstreamContext context)
|
||||
{
|
||||
if (IsAuthenticatedRoute(context.DownstreamReRoute))
|
||||
{
|
||||
Logger.LogInformation($"{context.HttpContext.Request.Path} is an authenticated route. {MiddlewareName} checking if client is authenticated");
|
||||
|
||||
var result = await context.HttpContext.AuthenticateAsync(context.DownstreamReRoute.AuthenticationOptions.AuthenticationProviderKey);
|
||||
|
||||
context.HttpContext.User = result.Principal;
|
||||
|
||||
if (context.HttpContext.User.Identity.IsAuthenticated)
|
||||
{
|
||||
Logger.LogInformation($"Client has been authenticated for {context.HttpContext.Request.Path}");
|
||||
await _next.Invoke(context);
|
||||
}
|
||||
else
|
||||
{
|
||||
var error = new UnauthenticatedError(
|
||||
$"Request for authenticated route {context.HttpContext.Request.Path} by {context.HttpContext.User.Identity.Name} was unauthenticated");
|
||||
|
||||
Logger.LogWarning($"Client has NOT been authenticated for {context.HttpContext.Request.Path} and pipeline error set. {error}");
|
||||
|
||||
SetPipelineError(context, error);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.LogInformation($"No authentication needed for {context.HttpContext.Request.Path}");
|
||||
|
||||
await _next.Invoke(context);
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsAuthenticatedRoute(DownstreamReRoute reRoute)
|
||||
{
|
||||
return reRoute.IsAuthenticated;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -71,7 +71,7 @@ namespace Ocelot.DependencyInjection
|
||||
|
||||
File.WriteAllText("ocelot.json", json);
|
||||
|
||||
builder.AddJsonFile("ocelot.json");
|
||||
builder.AddJsonFile("ocelot.json", false, false);
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
@ -1,12 +1,12 @@
|
||||
namespace Ocelot.Request.Mapper
|
||||
{
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Ocelot.Responses;
|
||||
|
||||
public interface IRequestMapper
|
||||
{
|
||||
Task<Response<HttpRequestMessage>> Map(HttpRequest request);
|
||||
}
|
||||
}
|
||||
namespace Ocelot.Request.Mapper
|
||||
{
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Ocelot.Responses;
|
||||
|
||||
public interface IRequestMapper
|
||||
{
|
||||
Response<HttpRequestMessage> Map(HttpRequest request);
|
||||
}
|
||||
}
|
||||
|
@ -1,108 +1,99 @@
|
||||
namespace Ocelot.Request.Mapper
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Http.Extensions;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
using Ocelot.Responses;
|
||||
|
||||
public class RequestMapper : IRequestMapper
|
||||
{
|
||||
private readonly string[] _unsupportedHeaders = { "host" };
|
||||
|
||||
public async Task<Response<HttpRequestMessage>> Map(HttpRequest request)
|
||||
{
|
||||
try
|
||||
{
|
||||
var requestMessage = new HttpRequestMessage()
|
||||
{
|
||||
Content = await MapContent(request),
|
||||
Method = MapMethod(request),
|
||||
RequestUri = MapUri(request)
|
||||
};
|
||||
|
||||
MapHeaders(request, requestMessage);
|
||||
|
||||
return new OkResponse<HttpRequestMessage>(requestMessage);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new ErrorResponse<HttpRequestMessage>(new UnmappableRequestError(ex));
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<HttpContent> MapContent(HttpRequest request)
|
||||
{
|
||||
if (request.Body == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var content = new ByteArrayContent(await ToByteArray(request.Body));
|
||||
|
||||
content.Headers
|
||||
.TryAddWithoutValidation("Content-Type", new[] {request.ContentType});
|
||||
|
||||
AddHeaderIfExistsOnRequest("Content-Language", content, request);
|
||||
AddHeaderIfExistsOnRequest("Content-Location", content, request);
|
||||
AddHeaderIfExistsOnRequest("Content-Range", content, request);
|
||||
AddHeaderIfExistsOnRequest("Content-MD5", content, request);
|
||||
AddHeaderIfExistsOnRequest("Content-Disposition", content, request);
|
||||
AddHeaderIfExistsOnRequest("Content-Encoding", content, request);
|
||||
|
||||
return content;
|
||||
}
|
||||
|
||||
private void AddHeaderIfExistsOnRequest(string key, HttpContent content, HttpRequest request)
|
||||
{
|
||||
if(request.Headers.ContainsKey(key))
|
||||
{
|
||||
content.Headers
|
||||
.TryAddWithoutValidation(key, request.Headers[key].ToList());
|
||||
}
|
||||
}
|
||||
|
||||
private HttpMethod MapMethod(HttpRequest request)
|
||||
{
|
||||
return new HttpMethod(request.Method);
|
||||
}
|
||||
|
||||
private Uri MapUri(HttpRequest request)
|
||||
{
|
||||
return new Uri(request.GetEncodedUrl());
|
||||
}
|
||||
|
||||
private void MapHeaders(HttpRequest request, HttpRequestMessage requestMessage)
|
||||
{
|
||||
foreach (var header in request.Headers)
|
||||
{
|
||||
if (IsSupportedHeader(header))
|
||||
{
|
||||
requestMessage.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<byte[]> ToByteArray(Stream stream)
|
||||
{
|
||||
using (stream)
|
||||
{
|
||||
using (var memStream = new MemoryStream())
|
||||
{
|
||||
await stream.CopyToAsync(memStream);
|
||||
return memStream.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsSupportedHeader(KeyValuePair<string, StringValues> header)
|
||||
{
|
||||
return !_unsupportedHeaders.Contains(header.Key.ToLower());
|
||||
}
|
||||
}
|
||||
}
|
||||
namespace Ocelot.Request.Mapper
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Http.Extensions;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
using Ocelot.Responses;
|
||||
|
||||
public class RequestMapper : IRequestMapper
|
||||
{
|
||||
private readonly string[] _unsupportedHeaders = { "host" };
|
||||
|
||||
public Response<HttpRequestMessage> Map(HttpRequest request)
|
||||
{
|
||||
try
|
||||
{
|
||||
var requestMessage = new HttpRequestMessage()
|
||||
{
|
||||
Content = MapContent(request),
|
||||
Method = MapMethod(request),
|
||||
RequestUri = MapUri(request)
|
||||
};
|
||||
|
||||
MapHeaders(request, requestMessage);
|
||||
|
||||
return new OkResponse<HttpRequestMessage>(requestMessage);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new ErrorResponse<HttpRequestMessage>(new UnmappableRequestError(ex));
|
||||
}
|
||||
}
|
||||
|
||||
private HttpContent MapContent(HttpRequest request)
|
||||
{
|
||||
if (request.Body == null || (request.Body.CanSeek && request.Body.Length <= 0))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var content = new StreamContent(request.Body);
|
||||
|
||||
if(!string.IsNullOrEmpty(request.ContentType))
|
||||
{
|
||||
content.Headers
|
||||
.TryAddWithoutValidation("Content-Type", new[] {request.ContentType});
|
||||
}
|
||||
|
||||
AddHeaderIfExistsOnRequest("Content-Language", content, request);
|
||||
AddHeaderIfExistsOnRequest("Content-Location", content, request);
|
||||
AddHeaderIfExistsOnRequest("Content-Range", content, request);
|
||||
AddHeaderIfExistsOnRequest("Content-MD5", content, request);
|
||||
AddHeaderIfExistsOnRequest("Content-Disposition", content, request);
|
||||
AddHeaderIfExistsOnRequest("Content-Encoding", content, request);
|
||||
|
||||
return content;
|
||||
}
|
||||
|
||||
private void AddHeaderIfExistsOnRequest(string key, HttpContent content, HttpRequest request)
|
||||
{
|
||||
if(request.Headers.ContainsKey(key))
|
||||
{
|
||||
content.Headers
|
||||
.TryAddWithoutValidation(key, request.Headers[key].ToList());
|
||||
}
|
||||
}
|
||||
|
||||
private HttpMethod MapMethod(HttpRequest request)
|
||||
{
|
||||
return new HttpMethod(request.Method);
|
||||
}
|
||||
|
||||
private Uri MapUri(HttpRequest request)
|
||||
{
|
||||
return new Uri(request.GetEncodedUrl());
|
||||
}
|
||||
|
||||
private void MapHeaders(HttpRequest request, HttpRequestMessage requestMessage)
|
||||
{
|
||||
foreach (var header in request.Headers)
|
||||
{
|
||||
if (IsSupportedHeader(header))
|
||||
{
|
||||
requestMessage.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsSupportedHeader(KeyValuePair<string, StringValues> header)
|
||||
{
|
||||
return !_unsupportedHeaders.Contains(header.Key.ToLower());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ namespace Ocelot.Request.Middleware
|
||||
|
||||
public async Task Invoke(DownstreamContext context)
|
||||
{
|
||||
var downstreamRequest = await _requestMapper.Map(context.HttpContext.Request);
|
||||
var downstreamRequest = _requestMapper.Map(context.HttpContext.Request);
|
||||
|
||||
if (downstreamRequest.IsError)
|
||||
{
|
||||
|
Reference in New Issue
Block a user