Skip to content

Commit

Permalink
OwinServerOptions and code cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
Jérôme Quiles committed Aug 30, 2017
1 parent 5e42918 commit 32dc79d
Show file tree
Hide file tree
Showing 26 changed files with 180 additions and 82 deletions.
7 changes: 7 additions & 0 deletions Skeleton.Tests.Common/CustomersController.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using Skeleton.Abstraction;
using Skeleton.Abstraction.Orm;
using Skeleton.Web.Server.Controllers;
using System.Web.Http;

namespace Skeleton.Tests.Common
{
Expand All @@ -14,5 +15,11 @@ public class CustomersController : EntityCrudController<Customer, CustomerDto>
: base(logger, reader, mapper, writer)
{
}

[HttpGet]
public IHttpActionResult Retry()
{
return InternalServerError();
}
}
}
4 changes: 2 additions & 2 deletions Skeleton.Tests.Core/Skeleton.Tests.Core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@
<Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<Private>False</Private>
</Reference>
<Reference Include="nunit.framework, Version=3.7.1.0, Culture=neutral, PublicKeyToken=2638cd05610744eb, processorArchitecture=MSIL">
<HintPath>..\packages\NUnit.3.7.1\lib\net45\nunit.framework.dll</HintPath>
<Reference Include="nunit.framework, Version=3.8.1.0, Culture=neutral, PublicKeyToken=2638cd05610744eb, processorArchitecture=MSIL">
<HintPath>..\packages\NUnit.3.8.1\lib\net45\nunit.framework.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
Expand Down
2 changes: 1 addition & 1 deletion Skeleton.Tests.Core/packages.config
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="NUnit" version="3.7.1" targetFramework="net461" />
<package id="NUnit" version="3.8.1" targetFramework="net461" />
<package id="NUnit3TestAdapter" version="3.8.0" targetFramework="net461" />
</packages>
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.CSharp" />
<Reference Include="nunit.framework, Version=3.7.1.0, Culture=neutral, PublicKeyToken=2638cd05610744eb, processorArchitecture=MSIL">
<HintPath>..\packages\NUnit.3.7.1\lib\net45\nunit.framework.dll</HintPath>
<Reference Include="nunit.framework, Version=3.8.1.0, Culture=neutral, PublicKeyToken=2638cd05610744eb, processorArchitecture=MSIL">
<HintPath>..\packages\NUnit.3.8.1\lib\net45\nunit.framework.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
Expand Down
2 changes: 1 addition & 1 deletion Skeleton.Tests.Infrastructure/packages.config
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="NUnit" version="3.7.1" targetFramework="net461" />
<package id="NUnit" version="3.8.1" targetFramework="net461" />
<package id="NUnit3TestAdapter" version="3.8.0" targetFramework="net461" />
</packages>
11 changes: 11 additions & 0 deletions Skeleton.Tests.Web/HttpClientEntityReaderTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ public void EntityReader_Page()
public void EntityReader_Query()
{
var request = new RestRequest()
.AddResource("query")
.AddQueryParameters(
new Query
{
Expand All @@ -83,5 +84,15 @@ public void EntityReader_Query()

Assert.IsNotNull(response);
}

[Test]
public void EntityReader_Retry()
{
var request = new RestRequest()
.AddResource("retry");
var response = _client.Get(request);

Assert.IsTrue(_client.RetryPolicy.RetryCount == 5);
}
}
}
9 changes: 2 additions & 7 deletions Skeleton.Tests.Web/Skeleton.Tests.Web.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -67,19 +67,14 @@
<HintPath>..\packages\Newtonsoft.Json.10.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="nunit.framework, Version=3.7.1.0, Culture=neutral, PublicKeyToken=2638cd05610744eb, processorArchitecture=MSIL">
<HintPath>..\packages\NUnit.3.7.1\lib\net45\nunit.framework.dll</HintPath>
<Reference Include="nunit.framework, Version=3.8.1.0, Culture=neutral, PublicKeyToken=2638cd05610744eb, processorArchitecture=MSIL">
<HintPath>..\packages\NUnit.3.8.1\lib\net45\nunit.framework.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Owin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f0ebd12fd5e55cc5, processorArchitecture=MSIL">
<HintPath>..\packages\Owin.1.0\lib\net40\Owin.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Serialize.Linq, Version=1.3.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Serialize.Linq.1.3.0\lib\net45\Serialize.Linq.dll</HintPath>
<SpecificVersion>False</SpecificVersion>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Configuration" />
<Reference Include="System.Net.Http" />
Expand Down
3 changes: 1 addition & 2 deletions Skeleton.Tests.Web/packages.config
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@
<package id="Microsoft.Owin.Host.HttpListener" version="3.1.0" targetFramework="net461" />
<package id="Microsoft.Owin.Hosting" version="3.1.0" targetFramework="net461" />
<package id="Newtonsoft.Json" version="10.0.3" targetFramework="net461" />
<package id="NUnit" version="3.7.1" targetFramework="net461" />
<package id="NUnit" version="3.8.1" targetFramework="net461" />
<package id="NUnit3TestAdapter" version="3.8.0" targetFramework="net461" />
<package id="Owin" version="1.0" targetFramework="net461" />
<package id="Serialize.Linq" version="1.3.0" targetFramework="net461" />
</packages>
2 changes: 1 addition & 1 deletion Skeleton.Web.Client/ExponentialRetryPolicy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public TimeSpan DelayInterval
public async Task<IRestResponse> ExecuteAsync(Func<Task<IRestResponse>> func)
{
IRestResponse response = null;
for (RetryCount = 0; RetryCount <= _maxRetries; RetryCount++)
for (RetryCount = 0; RetryCount < _maxRetries; RetryCount++)
{
if (RetryCount != 0)
Task.Delay(DelayInterval).Wait();
Expand Down
1 change: 1 addition & 0 deletions Skeleton.Web.Client/RestClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ protected virtual async Task<IRestResponse> SendAsync(IRestRequest request)

return await RetryPolicy.ExecuteAsync(async () =>
{
// Clone request is required as HttpClient forbid resending the same request
var requestClone = RetryPolicy.RetryCount > 0
? Clone(requestMessage)
: requestMessage;
Expand Down
22 changes: 9 additions & 13 deletions Skeleton.Web.Server/Configuration/CompressionMiddleware.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,47 +9,43 @@
namespace Skeleton.Web.Server.Configuration
{
// Adapted from https://github.com/mikegore1000/SqueezeMe
public class CompressionMiddleware
public sealed class CompressionMiddleware: OwinMiddleware
{
private readonly Func<IDictionary<string, object>, Task> next;
private readonly OwinCompression compression = new OwinCompression();

private readonly List<ICompressor> compressors = new List<ICompressor>
{
new GZipCompressor(),
new DeflateCompressor()
};

public CompressionMiddleware(Func<IDictionary<string, object>, Task> next)
public CompressionMiddleware(OwinMiddleware next)
:base(next)
{
this.next = next;
}

public async Task Invoke(IDictionary<string, object> environment)
public override async Task Invoke(IOwinContext context)
{
environment.ThrowIfNull();

var context = new OwinContext(environment);
var httpOutputStream = context.Response.Body;
var compressor = GetCompressor(context.Request);

if (compressor == null)
{
await next.Invoke(environment);
await Next.Invoke(context);
return;
}

await compression.Compress(next, context, compressor, httpOutputStream);
await compression.Compress(Next, context, compressor, httpOutputStream);

context.Response.Body = httpOutputStream;
}

private ICompressor GetCompressor(IOwinRequest request)
{
if (!request.Headers.ContainsKey(Constants.AcceptEncoding))
if (!request.Headers.ContainsKey(Constants.Headers.AcceptEncoding))
return null;

return (from c in compressors
from e in request.Headers.GetCommaSeparatedValues(Constants.AcceptEncoding)
from e in request.Headers.GetCommaSeparatedValues(Constants.Headers.AcceptEncoding)
.Select(x => StringWithQualityHeaderValue.Parse(x))
orderby e.Quality descending
where string.Compare(c.ContentEncoding, e.Value, StringComparison.OrdinalIgnoreCase) == 0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public virtual void HandleCore(ExceptionHandlerContext context)
{
context.ThrowIfNull();

var content = Constants.DefaultErrorMessage;
var content = Constants.Messages.DefaultErrorMessage;
#if DEBUG
content = context.Exception.Message;
#endif
Expand Down
10 changes: 5 additions & 5 deletions Skeleton.Web.Server/Configuration/OwinCompression.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ internal class OwinCompression
private const int BufferSize = 8192;

internal async Task Compress(
Func<IDictionary<string, object>, Task> next,
OwinContext context,
OwinMiddleware next,
IOwinContext context,
ICompressor compressor,
Stream httpOutputStream)
{
Expand All @@ -21,7 +21,7 @@ internal class OwinCompression
using (var compressedStream = compressor.CreateStream(memoryStream))
{
context.Response.Body = compressedStream;
await next.Invoke(context.Environment);
await next.Invoke(context);
}

if (memoryStream.Length > 0)
Expand All @@ -35,11 +35,11 @@ internal class OwinCompression
}

private static void SetResponseHeaders(
OwinContext context,
IOwinContext context,
ICompressor compressor,
MemoryStream memoryStream)
{
context.Response.Headers[Constants.ContentEncoding] = compressor.ContentEncoding;
context.Response.Headers[Constants.Headers.ContentEncoding] = compressor.ContentEncoding;
context.Response.ContentLength = memoryStream.Length;
}
}
Expand Down
27 changes: 27 additions & 0 deletions Skeleton.Web.Server/Configuration/RequestIdMiddleware.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using Microsoft.Owin;
using Skeleton.Core;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Skeleton.Web.Server.Configuration
{
public sealed class RequestIdMiddleware: OwinMiddleware
{
public RequestIdMiddleware(OwinMiddleware next ): base(next)
{
}

public override async Task Invoke(IOwinContext context)
{
var requestId = context.GetRequestId();

if (requestId.IsNotNullOrEmpty())
context.SetRequestId(requestId);

await Next.Invoke(context);
}
}
}
19 changes: 6 additions & 13 deletions Skeleton.Web.Server/Configuration/RequestLoggerMiddleware.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,23 +23,16 @@ public override async Task Invoke(IOwinContext context)
await LogRequest(context).ConfigureAwait(false);
}

// https://blog.heroku.com/http_request_id_s_improve_visibility_across_the_application_stack
private async Task LogRequest(IOwinContext context)
{
var requestId = context.GetRequestId();

var stopWath = Stopwatch.StartNew();

await Next.Invoke(context).ConfigureAwait(false);

stopWath.Stop();

_log.Info($"RequestId: {GetRequestId(context)} - Method :{context.Request.Method} - Url: {context.Request.Uri.PathAndQuery} - TimeElapsed: {stopWath.ElapsedMilliseconds} ms");
}

private string GetRequestId(IOwinContext context)
{
object id;
context.Environment.TryGetValue("owin.RequestId", out id);

return id.ToString();
}

_log.Info($"RequestId: {requestId} - Method :{context.Request.Method} - Url: {context.Request.Uri.PathAndQuery} - TimeElapsed: {stopWath.ElapsedMilliseconds} ms");
}
}
}
19 changes: 9 additions & 10 deletions Skeleton.Web.Server/Configuration/RequireSslMiddleware.cs
Original file line number Diff line number Diff line change
@@ -1,32 +1,31 @@
using Microsoft.Owin;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace Skeleton.Web.Server.Configuration
{
public class RequireSslMiddleware
public sealed class RequireSslMiddleware: OwinMiddleware
{
private readonly Func<IDictionary<string, object>, Task> _next;
private readonly OwinMiddleware _next;

public RequireSslMiddleware(Func<IDictionary<string, object>, Task> next)
{
_next = next;
public RequireSslMiddleware(OwinMiddleware next)
: base(next)
{
}

public async Task Invoke(IDictionary<string, object> env)
public override async Task Invoke(IOwinContext context)
{
var context = new OwinContext(env);

if (context.Request.Uri.Scheme != Uri.UriSchemeHttps)
{
context.Response.StatusCode = 403;
context.Response.ReasonPhrase = "SSL is required.";

await context.Response.WriteAsync(context.Response.ReasonPhrase);

return;
}

await _next(env);
await Next.Invoke(context);
}
}
}
31 changes: 24 additions & 7 deletions Skeleton.Web.Server/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,29 @@
{
internal static class Constants
{
internal const string DefaultRpcRoute = "DefaultRpcRoute";
internal const string DefaultApiPath = "api";
internal const string DefaultRpcRouteTemplate = DefaultApiPath + "/{controller}/{action}/{id}";
internal const string DefaultErrorMessage = "Oops! Sorry! Something went wrong.";
internal const string AcceptEncoding = "Accept-Encoding";
internal const string ContentEncoding = "Content-Encoding";
internal const string OwinContext = "MS_OwinContext";
internal static class Messages
{
internal const string DefaultErrorMessage = "Oops! Sorry! Something went wrong.";
}

internal static class Headers
{
internal const string AcceptEncoding = "Accept-Encoding";
internal const string ContentEncoding = "Content-Encoding";
internal const string RequestID = "X-Request-ID";
}

internal static class OwinEnvironment
{
internal const string Context = "MS_OwinContext";
internal const string RequestId = "owin.RequestId";
}

internal static class Routes
{
internal const string DefaultRpcRoute = "DefaultRpcRoute";
internal const string DefaultApiPath = "api";
internal const string DefaultRpcRouteTemplate = DefaultApiPath + "/{controller}/{action}/{id}";
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ public virtual async Task<IHttpActionResult> Create(TDto dto)
var newDto = Mapper.Map(entity);
return CreatedAtRoute(
Constants.DefaultRpcRoute,
Constants.Routes.DefaultRpcRoute,
new { id = entity.Id },
newDto);
});
Expand Down
2 changes: 1 addition & 1 deletion Skeleton.Web.Server/Controllers/DiscoverController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public IEnumerable<ServiceRegistry> Get()
{
var name = api.ActionDescriptor.ControllerDescriptor.ControllerName;
var builder = Request.CreateUriBuilder();
builder.Path = Constants.DefaultApiPath + "/" + name;
builder.Path = Constants.Routes.DefaultApiPath + "/" + name;
return new ServiceRegistry
{
Expand Down
Loading

0 comments on commit 32dc79d

Please sign in to comment.