Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
* ThreeMammals#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

* ThreeMammals#464 use seek instead of read on body check for websockets tests

* ThreeMammals#464 ran out of inodes on linux, looks like reloadonchange causes this
  • Loading branch information
TomPallister authored Jul 20, 2018
1 parent 12ef3bc commit 23c5fcb
Show file tree
Hide file tree
Showing 19 changed files with 1,253 additions and 1,034 deletions.
2 changes: 1 addition & 1 deletion samples/OcelotEureka/ApiGateway/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public static IWebHost BuildWebHost(string[] args) =>
.SetBasePath(hostingContext.HostingEnvironment.ContentRootPath)
.AddJsonFile("appsettings.json", true, true)
.AddJsonFile($"appsettings.{hostingContext.HostingEnvironment.EnvironmentName}.json", true, true)
.AddJsonFile("ocelot.json")
.AddJsonFile("ocelot.json", false, false)
.AddEnvironmentVariables();
})
.ConfigureServices(s =>
Expand Down
2 changes: 1 addition & 1 deletion samples/OcelotGraphQL/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ type Query {
.SetBasePath(hostingContext.HostingEnvironment.ContentRootPath)
.AddJsonFile("appsettings.json", true, true)
.AddJsonFile($"appsettings.{hostingContext.HostingEnvironment.EnvironmentName}.json", true, true)
.AddJsonFile("ocelot.json")
.AddJsonFile("ocelot.json", false, false)
.AddEnvironmentVariables();
})
.ConfigureServices(s => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,15 +59,14 @@ public Task<string> OpenAsync(CancellationToken cancellationToken)
{
this.webHost = new WebHostBuilder()
.UseKestrel()
//.UseStartup<Startup>()
.UseUrls(this.listeningAddress)
.ConfigureAppConfiguration((hostingContext, config) =>
{
config
.SetBasePath(hostingContext.HostingEnvironment.ContentRootPath)
.AddJsonFile("appsettings.json", true, true)
.AddJsonFile($"appsettings.{hostingContext.HostingEnvironment.EnvironmentName}.json", true, true)
.AddJsonFile("ocelot.json")
.AddJsonFile("ocelot.json", false, false)
.AddEnvironmentVariables();
})
.ConfigureLogging((hostingContext, logging) =>
Expand Down
122 changes: 61 additions & 61 deletions src/Ocelot/Authentication/Middleware/AuthenticationMiddleware.cs
Original file line number Diff line number Diff line change
@@ -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;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ public static IConfigurationBuilder AddOcelot(this IConfigurationBuilder builder

File.WriteAllText("ocelot.json", json);

builder.AddJsonFile("ocelot.json");
builder.AddJsonFile("ocelot.json", false, false);

return builder;
}
Expand Down
24 changes: 12 additions & 12 deletions src/Ocelot/Request/Mapper/IRequestMapper.cs
Original file line number Diff line number Diff line change
@@ -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);
}
}
207 changes: 99 additions & 108 deletions src/Ocelot/Request/Mapper/RequestMapper.cs
Original file line number Diff line number Diff line change
@@ -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());
}
}
}
Loading

0 comments on commit 23c5fcb

Please sign in to comment.