added some router thing and removed loads of crap

This commit is contained in:
Tom Gardham-Pallister
2016-07-02 16:09:54 +01:00
parent 948776115c
commit 3777e8c0c8
28 changed files with 425 additions and 590 deletions

49
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,49 @@
{
"version": "0.2.0",
"configurations": [
{
"name": ".NET Core Launch (console)",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
"program": "${workspaceRoot}/bin/Debug/<target-framework>/<project-name.dll>",
"args": [],
"cwd": "${workspaceRoot}",
"stopAtEntry": false,
"externalConsole": false
},
{
"name": ".NET Core Launch (web)",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
"program": "${workspaceRoot}/bin/Debug/<target-framework>/<project-name.dll>",
"args": [],
"cwd": "${workspaceRoot}",
"stopAtEntry": false,
"launchBrowser": {
"enabled": true,
"args": "${auto-detect-url}",
"windows": {
"command": "cmd.exe",
"args": "/C start ${auto-detect-url}"
},
"osx": {
"command": "open"
},
"linux": {
"command": "xdg-open"
}
},
"env": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
{
"name": ".NET Core Attach",
"type": "coreclr",
"request": "attach",
"processId": 0
}
]
}

View File

@ -1,19 +0,0 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.DependencyInjection;
namespace Ocelot.ApiGateway
{
public static class HelloExtensions
{
public static IRouteBuilder AddRouter(this IRouteBuilder routeBuilder,
IApplicationBuilder app)
{
routeBuilder.Routes.Add(new Route(new Router(),
"{*url}",
app.ApplicationServices.GetService<IInlineConstraintResolver>()));
return routeBuilder;
}
}
}

View File

@ -0,0 +1,12 @@
namespace Ocelot.ApiGateway.Infrastructure.Responses
{
public abstract class Error
{
public Error(string message)
{
Message = message;
}
public string Message { get; private set; }
}
}

View File

@ -0,0 +1,11 @@
namespace Ocelot.ApiGateway.Infrastructure.Responses
{
using System.Collections.Generic;
public class ErrorResponse : Response
{
public ErrorResponse(List<Error> errors) : base(errors)
{
}
}
}

View File

@ -0,0 +1,11 @@
namespace Ocelot.ApiGateway.Infrastructure.Responses
{
using System.Collections.Generic;
public class ErrorResponse<T> : Response<T>
{
public ErrorResponse(List<Error> errors) : base(errors)
{
}
}
}

View File

@ -0,0 +1,9 @@
namespace Ocelot.ApiGateway.Infrastructure.Responses
{
public class OkResponse : Response
{
public OkResponse()
{
}
}
}

View File

@ -0,0 +1,9 @@
namespace Ocelot.ApiGateway.Infrastructure.Responses
{
public class OkResponse<T> : Response<T>
{
public OkResponse(T data) : base(data)
{
}
}
}

View File

@ -0,0 +1,19 @@
namespace Ocelot.ApiGateway.Infrastructure.Responses
{
using System.Collections.Generic;
public abstract class Response
{
protected Response()
{
Errors = new List<Error>();
}
protected Response(List<Error> errors)
{
Errors = errors ?? new List<Error>();
}
public List<Error> Errors { get; private set; }
}
}

View File

@ -0,0 +1,18 @@
namespace Ocelot.ApiGateway.Infrastructure.Responses
{
using System.Collections.Generic;
public abstract class Response<T> : Response
{
protected Response(T data)
{
Data = data;
}
protected Response(List<Error> errors) : base(errors)
{
}
public T Data { get; private set; }
}
}

View File

@ -0,0 +1,10 @@
using Ocelot.ApiGateway.Infrastructure.Responses;
namespace Ocelot.ApiGateway.Infrastructure.Router
{
public interface IRouterService
{
Response AddRoute(string apiKey, string upstreamApiBaseUrl);
Response<Route> GetRoute(string apiKey);
}
}

View File

@ -0,0 +1,41 @@
using System;
using System.Collections.Generic;
using Ocelot.ApiGateway.Infrastructure.Responses;
namespace Ocelot.ApiGateway.Infrastructure.Router
{
public class InMemoryRouterService : IRouterService
{
private Dictionary<string, string> _routes;
public InMemoryRouterService()
{
_routes = new Dictionary<string,string>();
}
public Response AddRoute(string apiKey, string upstreamApiBaseUrl)
{
if(_routes.ContainsKey(apiKey))
{
return new ErrorResponse(new List<Error>(){new RouteKeyAlreadyExists("This key has already been used")});
}
_routes.Add(apiKey, upstreamApiBaseUrl);
return new OkResponse();
}
public Response<Route> GetRoute(string apiKey)
{
Console.WriteLine("looking for {0}", apiKey);
string upstreamApiBaseUrl = null;
if(_routes.TryGetValue(apiKey, out upstreamApiBaseUrl))
{
return new OkResponse<Route>(new Route(apiKey, upstreamApiBaseUrl));
}
Console.WriteLine("Couldnt find it");
return new ErrorResponse<Route>(new List<Error>(){new RouteKeyDoesNotExist("This key does not exist")});
}
}
}

View File

@ -0,0 +1,14 @@
namespace Ocelot.ApiGateway.Infrastructure.Router
{
public class Route
{
public Route(string apiKey, string upstreamRoute)
{
ApiKey = apiKey;
UpstreamRoute = upstreamRoute;
}
public string ApiKey {get;private set;}
public string UpstreamRoute {get;private set;}
}
}

View File

@ -0,0 +1,12 @@
using Ocelot.ApiGateway.Infrastructure.Responses;
namespace Ocelot.ApiGateway.Infrastructure.Router
{
public class RouteKeyAlreadyExists : Error
{
public RouteKeyAlreadyExists(string message)
: base(message)
{
}
}
}

View File

@ -0,0 +1,12 @@
using Ocelot.ApiGateway.Infrastructure.Responses;
namespace Ocelot.ApiGateway.Infrastructure.Router
{
public class RouteKeyDoesNotExist : Error
{
public RouteKeyDoesNotExist(string message)
: base(message)
{
}
}
}

View File

@ -0,0 +1,111 @@
using System;
using Ocelot.ApiGateway.Infrastructure.Responses;
using Shouldly;
using Xunit;
namespace Ocelot.ApiGateway.Infrastructure.Router
{
public class RouterTests
{
private string _upstreamApiUrl;
private string _apiKey;
private IRouterService _router;
private Response _response;
private Response<Route> _getRouteResponse;
public RouterTests()
{
_router = new InMemoryRouterService();
}
[Fact]
public void can_add_route()
{
GivenIHaveAnUpstreamApi("http://www.someapi.com/api1");
GivenIWantToRouteRequestsToMyUpstreamApi("api");
WhenIAddTheConfiguration();
ThenTheResponseIsSuccesful();
}
[Fact]
public void can_get_route_by_key()
{
GivenIHaveSetUpAnApiKeyAndUpstreamUrl("api2", "http://www.someapi.com/api2");
WhenIRetrieveTheRouteByKey();
ThenTheRouteIsReturned();
}
[Fact]
public void should_return_error_response_when_key_already_used()
{
GivenIHaveSetUpAnApiKeyAndUpstreamUrl("api2", "http://www.someapi.com/api2");
WhenITryToUseTheSameKey();
ThenTheKeyHasAlreadyBeenUsed();
}
[Fact]
public void should_return_error_response_if_key_doesnt_exist()
{
GivenIWantToRouteRequestsToMyUpstreamApi("api");
WhenIRetrieveTheRouteByKey();
ThenTheKeyDoesNotExist();
}
private void WhenITryToUseTheSameKey()
{
WhenIAddTheConfiguration();
}
private void ThenTheKeyHasAlreadyBeenUsed()
{
_response.ShouldNotBeNull();
_response.ShouldBeOfType<ErrorResponse>();
_response.Errors[0].Message.ShouldBe("This key has already been used");
}
private void ThenTheKeyDoesNotExist()
{
_getRouteResponse.ShouldNotBeNull();
_getRouteResponse.ShouldBeOfType<ErrorResponse<Route>>();
_getRouteResponse.Errors[0].Message.ShouldBe("This key does not exist");
}
private void WhenIRetrieveTheRouteByKey()
{
_getRouteResponse = _router.GetRoute(_apiKey);
}
private void ThenTheRouteIsReturned()
{
_getRouteResponse.Data.ApiKey.ShouldBe(_apiKey);
_getRouteResponse.Data.UpstreamRoute.ShouldBe(_upstreamApiUrl);
}
private void GivenIHaveSetUpAnApiKeyAndUpstreamUrl(string apiKey, string upstreamUrl)
{
GivenIHaveAnUpstreamApi(upstreamUrl);
GivenIWantToRouteRequestsToMyUpstreamApi(apiKey);
WhenIAddTheConfiguration();
}
private void GivenIHaveAnUpstreamApi(string upstreamApiUrl)
{
_upstreamApiUrl = upstreamApiUrl;
}
private void GivenIWantToRouteRequestsToMyUpstreamApi(string apiKey)
{
_apiKey = apiKey;
}
private void WhenIAddTheConfiguration()
{
_response = _router.AddRoute(_apiKey, _upstreamApiUrl);
}
private void ThenTheResponseIsSuccesful()
{
_response.ShouldBeOfType<OkResponse>();
}
}
}

View File

@ -0,0 +1,12 @@
using Microsoft.AspNetCore.Builder;
namespace Ocelot.ApiGateway.Middleware
{
public static class ProxyExtensions
{
public static IApplicationBuilder UseProxy(this IApplicationBuilder builder)
{
return builder.UseMiddleware<ProxyMiddleware>();
}
}
}

View File

@ -0,0 +1,20 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
namespace Ocelot.ApiGateway.Middleware
{
public class ProxyMiddleware
{
private readonly RequestDelegate _next;
public ProxyMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context)
{
await _next.Invoke(context);
}
}
}

View File

@ -0,0 +1,12 @@
using Microsoft.AspNetCore.Builder;
namespace Ocelot.ApiGateway.Middleware
{
public static class RequestLoggerExtensions
{
public static IApplicationBuilder UseRequestLogger(this IApplicationBuilder builder)
{
return builder.UseMiddleware<RequestLoggerMiddleware>();
}
}
}

View File

@ -0,0 +1,25 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
namespace Ocelot.ApiGateway.Middleware
{
public class RequestLoggerMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger _logger;
public RequestLoggerMiddleware(RequestDelegate next, ILoggerFactory loggerFactory)
{
_next = next;
_logger = loggerFactory.CreateLogger<RequestLoggerMiddleware>();
}
public async Task Invoke(HttpContext context)
{
_logger.LogInformation("Handling request: " + context.Request.Path);
await _next.Invoke(context);
_logger.LogInformation("Finished handling request.");
}
}
}

View File

@ -1,24 +0,0 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Routing;
namespace Ocelot.ApiGateway
{
public class Router : IRouter
{
public Task RouteAsync(RouteContext context)
{
context.Handler = async c =>
{
await c.Response.WriteAsync($"Hi, Tom!");
};
return Task.FromResult(0);
}
public VirtualPathData GetVirtualPath(VirtualPathContext context)
{
return null;
}
}
}

View File

@ -4,6 +4,8 @@ using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Routing;
using Ocelot.ApiGateway.Middleware;
using Microsoft.AspNetCore.Http;
namespace Ocelot.ApiGateway namespace Ocelot.ApiGateway
{ {
@ -32,13 +34,16 @@ namespace Ocelot.ApiGateway
{ {
loggerFactory.AddConsole(Configuration.GetSection("Logging")); loggerFactory.AddConsole(Configuration.GetSection("Logging"));
app.UseRequestLogger();
app.UseProxy();
loggerFactory.AddDebug(); loggerFactory.AddDebug();
var routeBuilder = new RouteBuilder(app); app.Run(async context =>
{
await context.Response.WriteAsync("Hello from Tom");
});
}
}
}
routeBuilder.AddRouter(app);
app.UseRouter(routeBuilder.Build());
}
}
}

View File

@ -13,9 +13,13 @@
"Microsoft.Extensions.Logging": "1.0.0-rc2-final", "Microsoft.Extensions.Logging": "1.0.0-rc2-final",
"Microsoft.Extensions.Logging.Console": "1.0.0-rc2-final", "Microsoft.Extensions.Logging.Console": "1.0.0-rc2-final",
"Microsoft.Extensions.Logging.Debug": "1.0.0-rc2-final", "Microsoft.Extensions.Logging.Debug": "1.0.0-rc2-final",
"Microsoft.AspNetCore.Routing": "1.0.0-rc2-final" "xunit": "2.1.0",
"dotnet-test-xunit": "1.0.0-rc2-final",
"Shouldly": "2.8.0"
}, },
"testRunner":"xunit",
"tools": { "tools": {
"Microsoft.AspNetCore.Server.IISIntegration.Tools": { "Microsoft.AspNetCore.Server.IISIntegration.Tools": {
"version": "1.0.0-preview1-final", "version": "1.0.0-preview1-final",

View File

@ -1,234 +0,0 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
build/
bld/
[Bb]in/
[Oo]bj/
# Visual Studio 2015 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUNIT
*.VisualState.xml
TestResult.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# DNX
project.lock.json
artifacts/
*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding add-in
.JustCode
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# TODO: Comment the next line if you want to checkin your web deploy settings
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/packages/*
# except build/, which is used as an MSBuild target.
!**/packages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/packages/repositories.config
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Microsoft Azure ApplicationInsights config file
ApplicationInsights.config
# Windows Store app package directory
AppPackages/
BundleArtifacts/
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.pfx
*.publishsettings
node_modules/
orleans.codegen.cs
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
# SQL Server files
*.mdf
*.ldf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
# FAKE - F# Make
.fake/

View File

@ -1,16 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Ocelot.Library
{
// This project can output the Class library as a NuGet Package.
// To enable this option, right-click on the project and select the Properties menu item. In the Build tab select "Produce outputs on build".
public class RouterMiddleware
{
public RouterMiddleware()
{
}
}
}

View File

@ -1,17 +0,0 @@
{
"version": "1.0.0-*",
"dependencies": {
"NETStandard.Library": "1.5.0-rc2-24027"
},
"frameworks": {
"netstandard1.5": {
"imports": "dnxcore50"
}
},
"tooling": {
"defaultNamespace": "Ocelot.Library"
}
}

View File

@ -1,234 +0,0 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
build/
bld/
[Bb]in/
[Oo]bj/
# Visual Studio 2015 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUNIT
*.VisualState.xml
TestResult.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# DNX
project.lock.json
artifacts/
*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding add-in
.JustCode
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# TODO: Comment the next line if you want to checkin your web deploy settings
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/packages/*
# except build/, which is used as an MSBuild target.
!**/packages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/packages/repositories.config
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Microsoft Azure ApplicationInsights config file
ApplicationInsights.config
# Windows Store app package directory
AppPackages/
BundleArtifacts/
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.pfx
*.publishsettings
node_modules/
orleans.codegen.cs
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
# SQL Server files
*.mdf
*.ldf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
# FAKE - F# Make
.fake/

View File

@ -1,16 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Ocelot.UnitTests
{
// This project can output the Class library as a NuGet Package.
// To enable this option, right-click on the project and select the Properties menu item. In the Build tab select "Produce outputs on build".
public class RouterMiddlwareTests
{
public RouterMiddlwareTests()
{
}
}
}

View File

@ -1,21 +0,0 @@
{
"version": "1.0.0-*",
"dependencies": {
"NETStandard.Library": "1.5.0-rc2-24027",
"Microsoft.AspNetCore.Server.Kestrel": "1.0.0-rc2-final",
"Microsoft.AspNetCore.Routing": "1.0.0-rc2-final",
"Microsoft.Extensions.Logging.Console": "1.0.0-rc2-final",
"Microsoft.AspNetCore.Server.IISIntegration": "1.0.0-rc2-final"
},
"frameworks": {
"netstandard1.5": {
"imports": "dnxcore50"
}
},
"tooling": {
"defaultNamespace": "Ocelot.UnitTests"
}
}