From df86052a31235d4dd740020dc8ddf574b3b1b81a Mon Sep 17 00:00:00 2001 From: Philip Wood Date: Sun, 25 Feb 2018 14:36:33 +0000 Subject: [PATCH 01/26] Add stylecop analyzers with default ruleset --- codeanalysis.ruleset | 120 ++++++++++++++++++ src/Ocelot/Ocelot.csproj | 4 + .../Ocelot.AcceptanceTests.csproj | 4 + .../Ocelot.Benchmarks.csproj | 4 + .../Ocelot.IntegrationTests.csproj | 44 ++++--- .../Ocelot.ManualTest.csproj | 4 + test/Ocelot.UnitTests/Ocelot.UnitTests.csproj | 4 + 7 files changed, 164 insertions(+), 20 deletions(-) create mode 100644 codeanalysis.ruleset diff --git a/codeanalysis.ruleset b/codeanalysis.ruleset new file mode 100644 index 00000000..f666b7e7 --- /dev/null +++ b/codeanalysis.ruleset @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Ocelot/Ocelot.csproj b/src/Ocelot/Ocelot.csproj index eb4ce773..8dc09d0e 100644 --- a/src/Ocelot/Ocelot.csproj +++ b/src/Ocelot/Ocelot.csproj @@ -17,6 +17,7 @@ True false Tom Pallister + ..\..\codeanalysis.ruleset full @@ -35,6 +36,9 @@ + + all + diff --git a/test/Ocelot.AcceptanceTests/Ocelot.AcceptanceTests.csproj b/test/Ocelot.AcceptanceTests/Ocelot.AcceptanceTests.csproj index ab7ae7ce..363e0dce 100644 --- a/test/Ocelot.AcceptanceTests/Ocelot.AcceptanceTests.csproj +++ b/test/Ocelot.AcceptanceTests/Ocelot.AcceptanceTests.csproj @@ -12,6 +12,7 @@ false false false + ..\..\codeanalysis.ruleset @@ -34,6 +35,9 @@ + + all + diff --git a/test/Ocelot.Benchmarks/Ocelot.Benchmarks.csproj b/test/Ocelot.Benchmarks/Ocelot.Benchmarks.csproj index ac2b0191..bc22e06c 100644 --- a/test/Ocelot.Benchmarks/Ocelot.Benchmarks.csproj +++ b/test/Ocelot.Benchmarks/Ocelot.Benchmarks.csproj @@ -11,6 +11,7 @@ false false false + ..\..\codeanalysis.ruleset @@ -19,6 +20,9 @@ + + all + diff --git a/test/Ocelot.IntegrationTests/Ocelot.IntegrationTests.csproj b/test/Ocelot.IntegrationTests/Ocelot.IntegrationTests.csproj index 6e1fdb4b..8dc250b2 100644 --- a/test/Ocelot.IntegrationTests/Ocelot.IntegrationTests.csproj +++ b/test/Ocelot.IntegrationTests/Ocelot.IntegrationTests.csproj @@ -11,6 +11,7 @@ false false false + ..\..\codeanalysis.ruleset @@ -18,29 +19,32 @@ - + - + - - - - - - - - - - - - - - - - - - + + + + all + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/Ocelot.ManualTest/Ocelot.ManualTest.csproj b/test/Ocelot.ManualTest/Ocelot.ManualTest.csproj index 7ec84c3d..ed0e2cb8 100644 --- a/test/Ocelot.ManualTest/Ocelot.ManualTest.csproj +++ b/test/Ocelot.ManualTest/Ocelot.ManualTest.csproj @@ -9,6 +9,7 @@ Exe Ocelot.ManualTest osx.10.11-x64;osx.10.12-x64;win7-x64;win10-x64 + ..\..\codeanalysis.ruleset @@ -38,6 +39,9 @@ + + all + diff --git a/test/Ocelot.UnitTests/Ocelot.UnitTests.csproj b/test/Ocelot.UnitTests/Ocelot.UnitTests.csproj index 7993644f..9165347e 100644 --- a/test/Ocelot.UnitTests/Ocelot.UnitTests.csproj +++ b/test/Ocelot.UnitTests/Ocelot.UnitTests.csproj @@ -12,6 +12,7 @@ false false false + ..\..\codeanalysis.ruleset @@ -37,6 +38,9 @@ + + all + From 9f458a878b54a53bddf4b1e6cdb41c6987f217ad Mon Sep 17 00:00:00 2001 From: Philip Wood Date: Sun, 25 Feb 2018 15:47:13 +0000 Subject: [PATCH 02/26] Disable all but the least contentious rules --- codeanalysis.ruleset | 229 ++++++++++++++++++++++++------------------- 1 file changed, 129 insertions(+), 100 deletions(-) diff --git a/codeanalysis.ruleset b/codeanalysis.ruleset index f666b7e7..e867f4e5 100644 --- a/codeanalysis.ruleset +++ b/codeanalysis.ruleset @@ -1,120 +1,149 @@  - - - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - + + + + + + + + + + + + + + + - - + + - - - + + + + \ No newline at end of file From f95911bdf1d0ebc29f4e236802c06b17f8bdaf17 Mon Sep 17 00:00:00 2001 From: TomPallister Date: Fri, 2 Mar 2018 10:25:44 +0000 Subject: [PATCH 03/26] added logo to project --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 7145dc38..26b3927b 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # Ocelot +[](http://threemammals.com/ocelot) + [![Build status](https://ci.appveyor.com/api/projects/status/r6sv51qx36sis1je?svg=true)](https://ci.appveyor.com/project/TomPallister/ocelot-fcfpb) [![Windows Build history](https://buildstats.info/appveyor/chart/TomPallister/ocelot-fcfpb?branch=develop&includeBuildsFromPullRequest=false)](https://ci.appveyor.com/project/TomPallister/ocelot-fcfpb/history?branch=develop) From 68bc37419d28f7ec2332c7f3a51e3b0dea0c1d79 Mon Sep 17 00:00:00 2001 From: Tom Pallister Date: Fri, 2 Mar 2018 17:05:13 +0000 Subject: [PATCH 04/26] Create ISSUE_TEMPLATE.md --- ISSUE_TEMPLATE.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 ISSUE_TEMPLATE.md diff --git a/ISSUE_TEMPLATE.md b/ISSUE_TEMPLATE.md new file mode 100644 index 00000000..3f0d0f3a --- /dev/null +++ b/ISSUE_TEMPLATE.md @@ -0,0 +1,17 @@ +## Expected Behavior / New Feature + + +## Actual Behavior / Motivation for New Feautre + + +## Steps to Reproduce the Problem + + 1. + 1. + 1. + +## Specifications + + - Version: + - Platform: + - Subsystem: From 5b317f460538684d9c299f3c3318e70a47164a7e Mon Sep 17 00:00:00 2001 From: Tom Pallister Date: Fri, 2 Mar 2018 17:06:59 +0000 Subject: [PATCH 05/26] Create ULL_REQUEST_TEMPLATE.md --- ULL_REQUEST_TEMPLATE.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 ULL_REQUEST_TEMPLATE.md diff --git a/ULL_REQUEST_TEMPLATE.md b/ULL_REQUEST_TEMPLATE.md new file mode 100644 index 00000000..72a3b6fe --- /dev/null +++ b/ULL_REQUEST_TEMPLATE.md @@ -0,0 +1,7 @@ +Fixes / New Feature # + +## Proposed Changes + + - + - + - From fefeca676ea1b9a0e3f08cd127e6f972c9b7240a Mon Sep 17 00:00:00 2001 From: Tom Pallister Date: Fri, 2 Mar 2018 17:08:43 +0000 Subject: [PATCH 06/26] Create CODE_OF_CONDUCT.md (#254) --- CODE_OF_CONDUCT.md | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 CODE_OF_CONDUCT.md diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 00000000..49a79976 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,46 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at tom@threemammals.co.uk. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] + +[homepage]: http://contributor-covenant.org +[version]: http://contributor-covenant.org/version/1/4/ From 59bd482fc7a01c43ae5a61274be09e1df9611375 Mon Sep 17 00:00:00 2001 From: Tom Pallister Date: Fri, 2 Mar 2018 17:11:22 +0000 Subject: [PATCH 07/26] Create CONTRIBUTING.md --- CONTRIBUTING.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..afac3db4 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,7 @@ +We love to receive contributions from the community so please keep them coming :) + +Pull requests, issues and commentary welcome! + +Please complete the relavent template for issues and PRs. Sometimes it's worth getting in touch with us to discuss changes +before doing any work incase this is something we are already doing or it might not make sense. We can also give +advice on the easiest way to do things :) From ca291413c613069c93d08c161872172b335d9b80 Mon Sep 17 00:00:00 2001 From: Tom Pallister Date: Fri, 2 Mar 2018 17:45:58 +0000 Subject: [PATCH 08/26] Update README.md --- README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 26b3927b..bae9993f 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,13 @@ -# Ocelot - [](http://threemammals.com/ocelot) [![Build status](https://ci.appveyor.com/api/projects/status/r6sv51qx36sis1je?svg=true)](https://ci.appveyor.com/project/TomPallister/ocelot-fcfpb) [![Windows Build history](https://buildstats.info/appveyor/chart/TomPallister/ocelot-fcfpb?branch=develop&includeBuildsFromPullRequest=false)](https://ci.appveyor.com/project/TomPallister/ocelot-fcfpb/history?branch=develop) - [![Coverage Status](https://coveralls.io/repos/github/TomPallister/Ocelot/badge.svg?branch=develop)](https://coveralls.io/github/TomPallister/Ocelot?branch=develop) +# Ocelot + Ocelot is a .NET Api Gateway. This project is aimed at people using .NET running a micro services / service orientated architecture that need a unified point of entry into their system. From dfb0759c754306dcdad0ef6a67aa28c5b1e5cc10 Mon Sep 17 00:00:00 2001 From: Tom Pallister Date: Fri, 2 Mar 2018 17:47:07 +0000 Subject: [PATCH 09/26] Rename ULL_REQUEST_TEMPLATE.md to PULL_REQUEST_TEMPLATE.md --- ULL_REQUEST_TEMPLATE.md => PULL_REQUEST_TEMPLATE.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename ULL_REQUEST_TEMPLATE.md => PULL_REQUEST_TEMPLATE.md (100%) diff --git a/ULL_REQUEST_TEMPLATE.md b/PULL_REQUEST_TEMPLATE.md similarity index 100% rename from ULL_REQUEST_TEMPLATE.md rename to PULL_REQUEST_TEMPLATE.md From 2d3d2abf068db0a8dd02c4431f7e5b0fb5684358 Mon Sep 17 00:00:00 2001 From: Tom Pallister Date: Fri, 2 Mar 2018 17:48:21 +0000 Subject: [PATCH 10/26] Update CONTRIBUTING.md --- CONTRIBUTING.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index afac3db4..e6f89046 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -5,3 +5,5 @@ Pull requests, issues and commentary welcome! Please complete the relavent template for issues and PRs. Sometimes it's worth getting in touch with us to discuss changes before doing any work incase this is something we are already doing or it might not make sense. We can also give advice on the easiest way to do things :) + +Finally we mark all existing issues as help wanted, small, medium and large effort. If you want to contriute for the first time I suggest looking at a help wanted & small effort issue :) From b7db8773b6d1ac2d928eb928d38a233a42e5c318 Mon Sep 17 00:00:00 2001 From: Tom Pallister Date: Fri, 2 Mar 2018 17:58:22 +0000 Subject: [PATCH 11/26] Update README.md --- README.md | 43 +++++++++++++++++++++++++++++++------------ 1 file changed, 31 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index bae9993f..71a58828 100644 --- a/README.md +++ b/README.md @@ -27,11 +27,28 @@ Ocelot manipulates the HttpRequest object into a state specified by its configur it reaches a request builder middleware where it creates a HttpRequestMessage object which is used to make a request to a downstream service. The middleware that makes the request is the last thing in the Ocelot pipeline. It does not call the next middleware. -The response from the downstream service is stored in a per request scoped repository -and retrieved as the requests goes back up the Ocelot pipeline. There is a piece of middleware -that maps the HttpResponseMessage onto the HttpResponse object and that is returned to the client. -That is basically it with a bunch of other features. - +The response from the downstream service is retrieved as the requests goes back up the Ocelot pipeline. +There is a piece of middleware that maps the HttpResponseMessage onto the HttpResponse object and that +is returned to the client. That is basically it with a bunch of other features! + +## Features + +A quick list of Ocelot's capabilities for more information see the [documentation](http://ocelot.readthedocs.io/en/latest/). + +* Routing +* Request Aggregation +* Service Discovery with Consul +* Authentication +* Authorisation +* Rate Limiting +* Caching +* Retry policies / QoS +* Load Balancing +* Logging / Tracing / Correlation +* Headers / Query String / Claims Transformation +* Custom Middleware / Delegating Handlers +* Configuration / Administration REST API + ## How to install Ocelot is designed to work with ASP.NET core only and is currently @@ -49,20 +66,22 @@ Please click [here](http://ocelot.readthedocs.io/en/latest/) for the Ocleot docu ## Coming up -You can see what we are working on [here](https://github.com/TomPallister/Ocelot/projects/1) +You can see what we are working on [here](https://github.com/ThreeMammals/Ocelot/issues). ## Contributing -Pull requests, issues and commentary welcome! No special process just create a request and get in -touch either via gitter or create an issue. +We love to receive contributions from the community so please keep them coming :) +Pull requests, issues and commentary welcome! + +Please complete the relavent template for issues and PRs. Sometimes it's worth getting in touch with us to discuss changes +before doing any work incase this is something we are already doing or it might not make sense. We can also give +advice on the easiest way to do things :) + +Finally we mark all existing issues as help wanted, small, medium and large effort. If you want to contriute for the first time I suggest looking at a help wanted & small effort issue :) ## Things that are currently annoying me -+ The base OcelotMiddleware lets you access things that are going to be null -and doesnt check the response is OK. I think the fact you can even call stuff -that isnt available is annoying. Let alone it be null. - [![](https://codescene.io/projects/697/status.svg) Get more details at **codescene.io**.](https://codescene.io/projects/697/jobs/latest-successful/results) From 9cb25ab063c03971f769ac1b60a35efedf1441c5 Mon Sep 17 00:00:00 2001 From: Tom Pallister Date: Fri, 2 Mar 2018 18:00:49 +0000 Subject: [PATCH 12/26] Update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 71a58828..fc9b67b8 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,8 @@ Ocelot is a .NET Api Gateway. This project is aimed at people using .NET running a micro services / service orientated architecture -that need a unified point of entry into their system. +that need a unified point of entry into their system. However it will worth with anything that +speaks HTTP and run on any platform that asp.net core supports. In particular I want easy integration with IdentityServer reference and bearer tokens. From c61dc9fd110a5777f6ca3ccef1eb04b248ff039b Mon Sep 17 00:00:00 2001 From: Philip Wood Date: Sat, 3 Mar 2018 13:14:24 +0000 Subject: [PATCH 13/26] Fix brace line spacing and remove multiple concurrent whitespace characters SA1025, SA1505, SA1508, SA-1509, SA1513 --- src/Ocelot/Authorisation/ClaimsAuthoriser.cs | 3 ++- src/Ocelot/Cache/RegionCreator.cs | 3 +-- src/Ocelot/Cache/Regions.cs | 3 ++- .../Claims/Middleware/ClaimsBuilderMiddleware.cs | 1 + src/Ocelot/Configuration/DownstreamHostAndPort.cs | 1 + .../Configuration/File/FileRateLimitOptions.cs | 2 -- src/Ocelot/Configuration/File/FileRateLimitRule.cs | 2 +- src/Ocelot/Configuration/QoSOptions.cs | 1 - src/Ocelot/Configuration/ReRouteOptions.cs | 4 ++-- .../Repository/ConsulFileConfigurationPoller.cs | 1 - .../Repository/ConsulFileConfigurationRepository.cs | 3 +-- .../Configuration/Setter/FileConfigurationSetter.cs | 4 ++-- .../Validator/FileValidationFailedError.cs | 1 - .../Validator/ReRouteFluentValidator.cs | 1 + src/Ocelot/DependencyInjection/OcelotBuilder.cs | 3 +-- src/Ocelot/DownstreamRouteFinder/DownstreamRoute.cs | 3 ++- .../DownstreamRouteFinder/UrlMatcher/UrlMatch.cs | 3 ++- .../UrlMatcher/UrlPathPlaceholderNameAndValue.cs | 3 ++- .../UrlPathPlaceholderNameAndValueFinder.cs | 4 +++- .../Errors/Middleware/ExceptionHandlerMiddleware.cs | 1 + src/Ocelot/Headers/HttpResponseHeaderReplacer.cs | 3 ++- src/Ocelot/LoadBalancer/LoadBalancers/Lease.cs | 1 + src/Ocelot/Logging/IOcelotLoggerFactory.cs | 1 + src/Ocelot/Middleware/OcelotPipelineConfiguration.cs | 3 +-- src/Ocelot/Raft/FakeCommand.cs | 2 +- src/Ocelot/Raft/FilePeersProvider.cs | 1 + src/Ocelot/Raft/HttpPeer.cs | 4 +++- src/Ocelot/Raft/SqlLiteLog.cs | 12 ++++++++---- src/Ocelot/RateLimit/ClientRateLimitProcessor.cs | 3 --- .../DistributedCacheRateLimitCounterHanlder.cs | 1 + .../Middleware/ClientRateLimitMiddleware.cs | 7 +++---- src/Ocelot/RateLimit/RateLimitCore.cs | 5 ++--- src/Ocelot/Requester/HttpClientHttpRequester.cs | 1 - src/Ocelot/Requester/MemoryHttpClientCache.cs | 1 + src/Ocelot/Requester/OcelotHttpTracingHandler.cs | 2 +- src/Ocelot/Responder/HttpContextResponder.cs | 1 - .../Responder/Middleware/ResponderMiddleware.cs | 1 - src/Ocelot/Responses/ErrorResponse.cs | 3 ++- src/Ocelot/Responses/ErrorResponseGeneric.cs | 6 +++--- src/Ocelot/Responses/ResponseGeneric.cs | 5 ++--- .../ServiceDiscoveryProviderFactory.cs | 2 +- src/Ocelot/Values/Service.cs | 1 + test/Ocelot.AcceptanceTests/AuthorisationTests.cs | 7 ++----- test/Ocelot.AcceptanceTests/ButterflyTracingTests.cs | 4 ++-- .../ClaimsToQueryStringForwardingTests.cs | 2 +- test/Ocelot.AcceptanceTests/ClientRateLimitTests.cs | 7 ++----- test/Ocelot.AcceptanceTests/CustomMiddlewareTests.cs | 1 - .../HttpDelegatingHandlersTests.cs | 4 +--- test/Ocelot.AcceptanceTests/LoadBalancerTests.cs | 3 +-- test/Ocelot.AcceptanceTests/QoSTests.cs | 3 +-- test/Ocelot.AcceptanceTests/ServiceDiscoveryTests.cs | 5 ++--- test/Ocelot.AcceptanceTests/Steps.cs | 1 + test/Ocelot.Benchmarks/Program.cs | 1 - test/Ocelot.IntegrationTests/AdministrationTests.cs | 1 - test/Ocelot.IntegrationTests/RaftTests.cs | 8 ++++---- .../ThreadSafeHeadersTests.cs | 2 +- .../Authentication/AuthenticationMiddlewareTests.cs | 4 ++-- .../Authorization/ClaimsAuthoriserTests.cs | 1 - .../Cache/OutputCacheMiddlewareTests.cs | 1 - .../Claims/AddClaimsToRequestTests.cs | 1 - .../Configuration/ClaimsToThingCreatorTests.cs | 3 ++- .../ConfigurationFluentValidationTests.cs | 3 ++- .../ConsulFileConfigurationPollerTests.cs | 2 +- .../Configuration/FileConfigurationCreatorTests.cs | 3 +-- .../FileConfigurationRepositoryTests.cs | 2 +- .../HeaderFindAndReplaceCreatorTests.cs | 4 +--- .../Configuration/HttpHandlerOptionsCreatorTests.cs | 1 - .../UpstreamTemplatePatternCreatorTests.cs | 4 ++-- .../DependencyInjection/OcelotBuilderTests.cs | 5 ++--- .../Errors/ExceptionHandlerMiddlewareTests.cs | 3 +-- .../Headers/AddHeadersToRequestTests.cs | 1 - .../HttpHeadersTransformationMiddlewareTests.cs | 1 - .../Headers/HttpResponseHeaderReplacerTests.cs | 3 ++- .../Infrastructure/HttpDataRepositoryTests.cs | 2 -- .../LoadBalancer/LeastConnectionTests.cs | 1 - .../LoadBalancer/LoadBalancerMiddlewareTests.cs | 1 - test/Ocelot.UnitTests/Middleware/MultiplexerTests.cs | 1 - .../DownstreamRequestInitialiserMiddlewareTests.cs | 1 - .../Requester/FakeDelegatingHandler.cs | 4 ++-- .../ServiceDiscovery/ServiceRegistryTests.cs | 3 +-- 80 files changed, 98 insertions(+), 119 deletions(-) diff --git a/src/Ocelot/Authorisation/ClaimsAuthoriser.cs b/src/Ocelot/Authorisation/ClaimsAuthoriser.cs index 4db1045c..3ca7809e 100644 --- a/src/Ocelot/Authorisation/ClaimsAuthoriser.cs +++ b/src/Ocelot/Authorisation/ClaimsAuthoriser.cs @@ -47,7 +47,8 @@ namespace Ocelot.Authorisation }); } } + return new OkResponse(true); } } -} \ No newline at end of file +} diff --git a/src/Ocelot/Cache/RegionCreator.cs b/src/Ocelot/Cache/RegionCreator.cs index e2ca874b..f5a94c21 100644 --- a/src/Ocelot/Cache/RegionCreator.cs +++ b/src/Ocelot/Cache/RegionCreator.cs @@ -4,7 +4,6 @@ using Ocelot.Configuration.File; namespace Ocelot.Cache { - public class RegionCreator : IRegionCreator { public string Create(FileReRoute reRoute) @@ -21,4 +20,4 @@ namespace Ocelot.Cache return region; } } -} \ No newline at end of file +} diff --git a/src/Ocelot/Cache/Regions.cs b/src/Ocelot/Cache/Regions.cs index f94cc306..baec6087 100644 --- a/src/Ocelot/Cache/Regions.cs +++ b/src/Ocelot/Cache/Regions.cs @@ -8,6 +8,7 @@ namespace Ocelot.Cache { Value = value; } + public List Value {get;private set;} } -} \ No newline at end of file +} diff --git a/src/Ocelot/Claims/Middleware/ClaimsBuilderMiddleware.cs b/src/Ocelot/Claims/Middleware/ClaimsBuilderMiddleware.cs index 5161b247..48f57834 100644 --- a/src/Ocelot/Claims/Middleware/ClaimsBuilderMiddleware.cs +++ b/src/Ocelot/Claims/Middleware/ClaimsBuilderMiddleware.cs @@ -39,6 +39,7 @@ namespace Ocelot.Claims.Middleware return; } } + await _next.Invoke(context); } } diff --git a/src/Ocelot/Configuration/DownstreamHostAndPort.cs b/src/Ocelot/Configuration/DownstreamHostAndPort.cs index 483e7523..186cce2f 100644 --- a/src/Ocelot/Configuration/DownstreamHostAndPort.cs +++ b/src/Ocelot/Configuration/DownstreamHostAndPort.cs @@ -7,6 +7,7 @@ Host = host; Port = port; } + public string Host { get; private set; } public int Port { get; private set; } } diff --git a/src/Ocelot/Configuration/File/FileRateLimitOptions.cs b/src/Ocelot/Configuration/File/FileRateLimitOptions.cs index b9277a3c..c7f99cb0 100644 --- a/src/Ocelot/Configuration/File/FileRateLimitOptions.cs +++ b/src/Ocelot/Configuration/File/FileRateLimitOptions.cs @@ -34,6 +34,4 @@ namespace Ocelot.Configuration.File /// public int HttpStatusCode { get; set; } = 429; } - - } diff --git a/src/Ocelot/Configuration/File/FileRateLimitRule.cs b/src/Ocelot/Configuration/File/FileRateLimitRule.cs index 55346d2e..2dda3084 100644 --- a/src/Ocelot/Configuration/File/FileRateLimitRule.cs +++ b/src/Ocelot/Configuration/File/FileRateLimitRule.cs @@ -6,7 +6,6 @@ using System.Threading.Tasks; namespace Ocelot.Configuration.File { - public class FileRateLimitRule { public FileRateLimitRule() @@ -38,6 +37,7 @@ namespace Ocelot.Configuration.File { return string.Empty; } + var sb = new StringBuilder(); sb.Append( $"{nameof(Period)}:{Period},{nameof(PeriodTimespan)}:{PeriodTimespan:F},{nameof(Limit)}:{Limit},{nameof(ClientWhitelist)}:["); diff --git a/src/Ocelot/Configuration/QoSOptions.cs b/src/Ocelot/Configuration/QoSOptions.cs index c518cfec..60e7cc03 100644 --- a/src/Ocelot/Configuration/QoSOptions.cs +++ b/src/Ocelot/Configuration/QoSOptions.cs @@ -24,6 +24,5 @@ namespace Ocelot.Configuration public int TimeoutValue { get; private set; } public TimeoutStrategy TimeoutStrategy { get; private set; } - } } diff --git a/src/Ocelot/Configuration/ReRouteOptions.cs b/src/Ocelot/Configuration/ReRouteOptions.cs index 5ec316c3..e3a7a7b1 100644 --- a/src/Ocelot/Configuration/ReRouteOptions.cs +++ b/src/Ocelot/Configuration/ReRouteOptions.cs @@ -9,12 +9,12 @@ namespace Ocelot.Configuration IsCached = isCached; IsQos = isQos; EnableRateLimiting = isEnableRateLimiting; - } + public bool IsAuthenticated { get; private set; } public bool IsAuthorised { get; private set; } public bool IsCached { get; private set; } public bool IsQos { get; private set; } public bool EnableRateLimiting { get; private set; } } -} \ No newline at end of file +} diff --git a/src/Ocelot/Configuration/Repository/ConsulFileConfigurationPoller.cs b/src/Ocelot/Configuration/Repository/ConsulFileConfigurationPoller.cs index 7e78b3aa..a2780062 100644 --- a/src/Ocelot/Configuration/Repository/ConsulFileConfigurationPoller.cs +++ b/src/Ocelot/Configuration/Repository/ConsulFileConfigurationPoller.cs @@ -34,7 +34,6 @@ namespace Ocelot.Configuration.Repository _polling = true; await Poll(); _polling = false; - }, null, 0, 1000); } diff --git a/src/Ocelot/Configuration/Repository/ConsulFileConfigurationRepository.cs b/src/Ocelot/Configuration/Repository/ConsulFileConfigurationRepository.cs index 91b4bd9d..746df5da 100644 --- a/src/Ocelot/Configuration/Repository/ConsulFileConfigurationRepository.cs +++ b/src/Ocelot/Configuration/Repository/ConsulFileConfigurationRepository.cs @@ -9,7 +9,6 @@ using Ocelot.ServiceDiscovery; namespace Ocelot.Configuration.Repository { - public class ConsulFileConfigurationRepository : IFileConfigurationRepository { private readonly ConsulClient _consul; @@ -76,4 +75,4 @@ namespace Ocelot.Configuration.Repository return new ErrorResponse(new UnableToSetConfigInConsulError($"Unable to set FileConfiguration in consul, response status code from consul was {result.StatusCode}")); } } -} \ No newline at end of file +} diff --git a/src/Ocelot/Configuration/Setter/FileConfigurationSetter.cs b/src/Ocelot/Configuration/Setter/FileConfigurationSetter.cs index 71f56277..38a7c1cb 100644 --- a/src/Ocelot/Configuration/Setter/FileConfigurationSetter.cs +++ b/src/Ocelot/Configuration/Setter/FileConfigurationSetter.cs @@ -12,7 +12,7 @@ namespace Ocelot.Configuration.Setter private readonly IOcelotConfigurationCreator _configCreator; private readonly IFileConfigurationRepository _repo; - public FileConfigurationSetter(IOcelotConfigurationRepository configRepo, + public FileConfigurationSetter(IOcelotConfigurationRepository configRepo, IOcelotConfigurationCreator configCreator, IFileConfigurationRepository repo) { _configRepo = configRepo; @@ -39,4 +39,4 @@ namespace Ocelot.Configuration.Setter return new ErrorResponse(config.Errors); } } -} \ No newline at end of file +} diff --git a/src/Ocelot/Configuration/Validator/FileValidationFailedError.cs b/src/Ocelot/Configuration/Validator/FileValidationFailedError.cs index b661e065..e90aa218 100644 --- a/src/Ocelot/Configuration/Validator/FileValidationFailedError.cs +++ b/src/Ocelot/Configuration/Validator/FileValidationFailedError.cs @@ -9,7 +9,6 @@ namespace Ocelot.Configuration.Validator { public FileValidationFailedError(string message) : base(message, OcelotErrorCode.FileValidationFailedError) { - } } } diff --git a/src/Ocelot/Configuration/Validator/ReRouteFluentValidator.cs b/src/Ocelot/Configuration/Validator/ReRouteFluentValidator.cs index f2ebbace..c2f4dc62 100644 --- a/src/Ocelot/Configuration/Validator/ReRouteFluentValidator.cs +++ b/src/Ocelot/Configuration/Validator/ReRouteFluentValidator.cs @@ -67,6 +67,7 @@ namespace Ocelot.Configuration.Validator { return true; } + var schemes = await _authenticationSchemeProvider.GetAllSchemesAsync(); var supportedSchemes = schemes.Select(scheme => scheme.Name).ToList(); diff --git a/src/Ocelot/DependencyInjection/OcelotBuilder.cs b/src/Ocelot/DependencyInjection/OcelotBuilder.cs index f4192713..6501b619 100644 --- a/src/Ocelot/DependencyInjection/OcelotBuilder.cs +++ b/src/Ocelot/DependencyInjection/OcelotBuilder.cs @@ -126,7 +126,7 @@ namespace Ocelot.DependencyInjection // see this for why we register this as singleton http://stackoverflow.com/questions/37371264/invalidoperationexception-unable-to-resolve-service-for-type-microsoft-aspnetc // could maybe use a scoped data repository - _services.TryAddSingleton(); + _services.TryAddSingleton(); _services.TryAddSingleton(); _services.AddMemoryCache(); _services.TryAddSingleton(); @@ -154,7 +154,6 @@ namespace Ocelot.DependencyInjection // We add this here so that we can always inject something into the factory for IoC.. _services.AddSingleton(); - } public IOcelotAdministrationBuilder AddAdministration(string path, string secret) diff --git a/src/Ocelot/DownstreamRouteFinder/DownstreamRoute.cs b/src/Ocelot/DownstreamRouteFinder/DownstreamRoute.cs index ed04daef..c7696ecf 100644 --- a/src/Ocelot/DownstreamRouteFinder/DownstreamRoute.cs +++ b/src/Ocelot/DownstreamRouteFinder/DownstreamRoute.cs @@ -11,7 +11,8 @@ namespace Ocelot.DownstreamRouteFinder TemplatePlaceholderNameAndValues = templatePlaceholderNameAndValues; ReRoute = reRoute; } + public List TemplatePlaceholderNameAndValues { get; private set; } public ReRoute ReRoute { get; private set; } } -} \ No newline at end of file +} diff --git a/src/Ocelot/DownstreamRouteFinder/UrlMatcher/UrlMatch.cs b/src/Ocelot/DownstreamRouteFinder/UrlMatcher/UrlMatch.cs index bfbd6fdc..9236ae39 100644 --- a/src/Ocelot/DownstreamRouteFinder/UrlMatcher/UrlMatch.cs +++ b/src/Ocelot/DownstreamRouteFinder/UrlMatcher/UrlMatch.cs @@ -6,6 +6,7 @@ namespace Ocelot.DownstreamRouteFinder.UrlMatcher { Match = match; } + public bool Match {get;private set;} } -} \ No newline at end of file +} diff --git a/src/Ocelot/DownstreamRouteFinder/UrlMatcher/UrlPathPlaceholderNameAndValue.cs b/src/Ocelot/DownstreamRouteFinder/UrlMatcher/UrlPathPlaceholderNameAndValue.cs index e299c770..f91faa1d 100644 --- a/src/Ocelot/DownstreamRouteFinder/UrlMatcher/UrlPathPlaceholderNameAndValue.cs +++ b/src/Ocelot/DownstreamRouteFinder/UrlMatcher/UrlPathPlaceholderNameAndValue.cs @@ -7,7 +7,8 @@ namespace Ocelot.DownstreamRouteFinder.UrlMatcher Name = name; Value = value; } + public string Name {get;private set;} public string Value {get;private set;} } -} \ No newline at end of file +} diff --git a/src/Ocelot/DownstreamRouteFinder/UrlMatcher/UrlPathPlaceholderNameAndValueFinder.cs b/src/Ocelot/DownstreamRouteFinder/UrlMatcher/UrlPathPlaceholderNameAndValueFinder.cs index 70cf2272..4471618f 100644 --- a/src/Ocelot/DownstreamRouteFinder/UrlMatcher/UrlPathPlaceholderNameAndValueFinder.cs +++ b/src/Ocelot/DownstreamRouteFinder/UrlMatcher/UrlPathPlaceholderNameAndValueFinder.cs @@ -50,6 +50,7 @@ namespace Ocelot.DownstreamRouteFinder.UrlMatcher counterForTemplate = endOfPlaceholder; } + counterForPath++; } @@ -90,6 +91,7 @@ namespace Ocelot.DownstreamRouteFinder.UrlMatcher return variableName; } + private int GetNextCounterPosition(string urlTemplate, int counterForTemplate, char delimiter) { var closingPlaceHolderPositionOnTemplate = urlTemplate.IndexOf(delimiter, counterForTemplate); @@ -111,4 +113,4 @@ namespace Ocelot.DownstreamRouteFinder.UrlMatcher return character == '{'; } } -} \ No newline at end of file +} diff --git a/src/Ocelot/Errors/Middleware/ExceptionHandlerMiddleware.cs b/src/Ocelot/Errors/Middleware/ExceptionHandlerMiddleware.cs index 9b49c84a..2b9e22e2 100644 --- a/src/Ocelot/Errors/Middleware/ExceptionHandlerMiddleware.cs +++ b/src/Ocelot/Errors/Middleware/ExceptionHandlerMiddleware.cs @@ -100,6 +100,7 @@ namespace Ocelot.Errors.Middleware message = $"{message}, inner exception message {e.InnerException.Message}, inner exception stack {e.InnerException.StackTrace}"; } + return $"{message} RequestId: {context.HttpContext.TraceIdentifier}"; } } diff --git a/src/Ocelot/Headers/HttpResponseHeaderReplacer.cs b/src/Ocelot/Headers/HttpResponseHeaderReplacer.cs index 347923ed..cb45ffc3 100644 --- a/src/Ocelot/Headers/HttpResponseHeaderReplacer.cs +++ b/src/Ocelot/Headers/HttpResponseHeaderReplacer.cs @@ -26,6 +26,7 @@ namespace Ocelot.Headers return $"{downstreamUrl}/"; }); } + public Response Replace(HttpResponseMessage response, List fAndRs, HttpRequestMessage httpRequestMessage) { foreach (var f in fAndRs) @@ -54,4 +55,4 @@ namespace Ocelot.Headers return new OkResponse(); } } -} \ No newline at end of file +} diff --git a/src/Ocelot/LoadBalancer/LoadBalancers/Lease.cs b/src/Ocelot/LoadBalancer/LoadBalancers/Lease.cs index 583b3002..2713d44b 100644 --- a/src/Ocelot/LoadBalancer/LoadBalancers/Lease.cs +++ b/src/Ocelot/LoadBalancer/LoadBalancers/Lease.cs @@ -9,6 +9,7 @@ namespace Ocelot.LoadBalancer.LoadBalancers HostAndPort = hostAndPort; Connections = connections; } + public ServiceHostAndPort HostAndPort { get; private set; } public int Connections { get; private set; } } diff --git a/src/Ocelot/Logging/IOcelotLoggerFactory.cs b/src/Ocelot/Logging/IOcelotLoggerFactory.cs index 29b4c9d0..3a145595 100644 --- a/src/Ocelot/Logging/IOcelotLoggerFactory.cs +++ b/src/Ocelot/Logging/IOcelotLoggerFactory.cs @@ -6,6 +6,7 @@ namespace Ocelot.Logging { IOcelotLogger CreateLogger(); } + /// /// Thin wrapper around the DotNet core logging framework, used to allow the scopedDataRepository to be injected giving access to the Ocelot RequestId /// diff --git a/src/Ocelot/Middleware/OcelotPipelineConfiguration.cs b/src/Ocelot/Middleware/OcelotPipelineConfiguration.cs index 3cfded9b..d58b8b09 100644 --- a/src/Ocelot/Middleware/OcelotPipelineConfiguration.cs +++ b/src/Ocelot/Middleware/OcelotPipelineConfiguration.cs @@ -37,7 +37,6 @@ /// /// This allows the user to implement there own query string manipulation logic /// - public Func, Task> PreQueryStringBuilderMiddleware { get; set; } - + public Func, Task> PreQueryStringBuilderMiddleware { get; set; } } } diff --git a/src/Ocelot/Raft/FakeCommand.cs b/src/Ocelot/Raft/FakeCommand.cs index 795ca7a5..45dd1045 100644 --- a/src/Ocelot/Raft/FakeCommand.cs +++ b/src/Ocelot/Raft/FakeCommand.cs @@ -8,8 +8,8 @@ namespace Ocelot.Raft public FakeCommand(string value) { this.Value = value; - } + public string Value { get; private set; } } } diff --git a/src/Ocelot/Raft/FilePeersProvider.cs b/src/Ocelot/Raft/FilePeersProvider.cs index aeca7b2c..1eddf5e3 100644 --- a/src/Ocelot/Raft/FilePeersProvider.cs +++ b/src/Ocelot/Raft/FilePeersProvider.cs @@ -37,6 +37,7 @@ namespace Ocelot.Raft _peers.Add(httpPeer); } } + public List Get() { return _peers; diff --git a/src/Ocelot/Raft/HttpPeer.cs b/src/Ocelot/Raft/HttpPeer.cs index ef76a583..34a94b27 100644 --- a/src/Ocelot/Raft/HttpPeer.cs +++ b/src/Ocelot/Raft/HttpPeer.cs @@ -28,7 +28,7 @@ namespace Ocelot.Raft { _identityServerConfiguration = identityServerConfiguration; _config = config; - Id = hostAndPort; + Id = hostAndPort; _hostAndPort = hostAndPort; _httpClient = httpClient; _jsonSerializerSettings = new JsonSerializerSettings() { @@ -68,6 +68,7 @@ namespace Ocelot.Raft { SetToken(); } + var json = JsonConvert.SerializeObject(appendEntries, _jsonSerializerSettings); var content = new StringContent(json); content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json"); @@ -94,6 +95,7 @@ namespace Ocelot.Raft { SetToken(); } + var json = JsonConvert.SerializeObject(command, _jsonSerializerSettings); var content = new StringContent(json); content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json"); diff --git a/src/Ocelot/Raft/SqlLiteLog.cs b/src/Ocelot/Raft/SqlLiteLog.cs index 098d9c06..9ca32af4 100644 --- a/src/Ocelot/Raft/SqlLiteLog.cs +++ b/src/Ocelot/Raft/SqlLiteLog.cs @@ -24,6 +24,7 @@ namespace Ocelot.Raft FileStream fs = File.Create(_path); fs.Dispose(); } + using(var connection = new SqliteConnection($"Data Source={_path};")) { connection.Open(); @@ -59,6 +60,7 @@ namespace Ocelot.Raft } } } + return result; } } @@ -88,6 +90,7 @@ namespace Ocelot.Raft } } } + return result; } } @@ -113,6 +116,7 @@ namespace Ocelot.Raft } } } + return result; } } @@ -222,15 +226,13 @@ namespace Ocelot.Raft }; var log = JsonConvert.DeserializeObject(data, jsonSerializerSettings); logsToReturn.Add((id, log)); - } } } } return logsToReturn; - } - + } } public long GetTermAtIndex(int index) @@ -256,9 +258,11 @@ namespace Ocelot.Raft } } } + return result; } } + public void Remove(int indexOfCommand) { lock(_lock) @@ -276,4 +280,4 @@ namespace Ocelot.Raft } } } -} \ No newline at end of file +} diff --git a/src/Ocelot/RateLimit/ClientRateLimitProcessor.cs b/src/Ocelot/RateLimit/ClientRateLimitProcessor.cs index 0415489c..9a4a4ce3 100644 --- a/src/Ocelot/RateLimit/ClientRateLimitProcessor.cs +++ b/src/Ocelot/RateLimit/ClientRateLimitProcessor.cs @@ -7,7 +7,6 @@ using System.Threading.Tasks; namespace Ocelot.RateLimit { - public class ClientRateLimitProcessor { private readonly IRateLimitCounterHandler _counterHandler; @@ -39,7 +38,5 @@ namespace Ocelot.RateLimit { return _core.ConvertToTimeSpan(timeSpan); } - } - } diff --git a/src/Ocelot/RateLimit/DistributedCacheRateLimitCounterHanlder.cs b/src/Ocelot/RateLimit/DistributedCacheRateLimitCounterHanlder.cs index ddcda184..91f933b7 100644 --- a/src/Ocelot/RateLimit/DistributedCacheRateLimitCounterHanlder.cs +++ b/src/Ocelot/RateLimit/DistributedCacheRateLimitCounterHanlder.cs @@ -34,6 +34,7 @@ namespace Ocelot.RateLimit { return JsonConvert.DeserializeObject(stored); } + return null; } diff --git a/src/Ocelot/RateLimit/Middleware/ClientRateLimitMiddleware.cs b/src/Ocelot/RateLimit/Middleware/ClientRateLimitMiddleware.cs index 064ec54b..2061decc 100644 --- a/src/Ocelot/RateLimit/Middleware/ClientRateLimitMiddleware.cs +++ b/src/Ocelot/RateLimit/Middleware/ClientRateLimitMiddleware.cs @@ -38,6 +38,7 @@ namespace Ocelot.RateLimit.Middleware await _next.Invoke(context); return; } + // compute identity from request var identity = SetIdentity(context.HttpContext, options); @@ -70,8 +71,8 @@ namespace Ocelot.RateLimit.Middleware return; } - } + //set X-Rate-Limit headers for the longest period if (!options.DisableRateLimitHeaders) { @@ -103,6 +104,7 @@ namespace Ocelot.RateLimit.Middleware { return true; } + return false; } @@ -134,8 +136,5 @@ namespace Ocelot.RateLimit.Middleware return Task.CompletedTask; } - } - } - diff --git a/src/Ocelot/RateLimit/RateLimitCore.cs b/src/Ocelot/RateLimit/RateLimitCore.cs index c3455682..cc027dfb 100644 --- a/src/Ocelot/RateLimit/RateLimitCore.cs +++ b/src/Ocelot/RateLimit/RateLimitCore.cs @@ -62,6 +62,7 @@ namespace Ocelot.RateLimit var expirationTime = ConvertToTimeSpan(rule.Period); _counterHandler.Set(counterId, counter, expirationTime); } + return counter; } @@ -92,7 +93,6 @@ namespace Ocelot.RateLimit rule.Period, rule.Limit.ToString(), (DateTime.UtcNow + ConvertToTimeSpan(rule.Period)).ToUniversalTime().ToString("o", DateTimeFormatInfo.InvariantInfo)); - } return headers; @@ -141,7 +141,6 @@ namespace Ocelot.RateLimit default: throw new FormatException($"{timeSpan} can't be converted to TimeSpan, unknown type {type}"); } - } - + } } } diff --git a/src/Ocelot/Requester/HttpClientHttpRequester.cs b/src/Ocelot/Requester/HttpClientHttpRequester.cs index a531d9b9..de9ea1c6 100644 --- a/src/Ocelot/Requester/HttpClientHttpRequester.cs +++ b/src/Ocelot/Requester/HttpClientHttpRequester.cs @@ -55,7 +55,6 @@ namespace Ocelot.Requester { _cacheHandlers.Set(cacheKey, httpClient, TimeSpan.FromHours(24)); } - } private IHttpClient GetHttpClient(string cacheKey, IHttpClientBuilder builder, DownstreamContext request) diff --git a/src/Ocelot/Requester/MemoryHttpClientCache.cs b/src/Ocelot/Requester/MemoryHttpClientCache.cs index 3ce1716b..e37a46a3 100644 --- a/src/Ocelot/Requester/MemoryHttpClientCache.cs +++ b/src/Ocelot/Requester/MemoryHttpClientCache.cs @@ -41,6 +41,7 @@ namespace Ocelot.Requester { connectionQueue.TryDequeue(out client); } + return client; } diff --git a/src/Ocelot/Requester/OcelotHttpTracingHandler.cs b/src/Ocelot/Requester/OcelotHttpTracingHandler.cs index e2658c7f..fbd24fbf 100644 --- a/src/Ocelot/Requester/OcelotHttpTracingHandler.cs +++ b/src/Ocelot/Requester/OcelotHttpTracingHandler.cs @@ -35,7 +35,7 @@ namespace Ocelot.Requester { request.Headers.Remove(prefix_spanId); request.Headers.TryAddWithoutValidation(prefix_spanId, span.SpanContext.SpanId); - }; + } span.Tags.Client().Component("HttpClient") .HttpMethod(request.Method.Method) diff --git a/src/Ocelot/Responder/HttpContextResponder.cs b/src/Ocelot/Responder/HttpContextResponder.cs index fbfbc6c2..7bc55d94 100644 --- a/src/Ocelot/Responder/HttpContextResponder.cs +++ b/src/Ocelot/Responder/HttpContextResponder.cs @@ -50,7 +50,6 @@ namespace Ocelot.Responder httpContext.Response.StatusCode = (int)response.StatusCode; return Task.CompletedTask; - }, context); using (Stream stream = new MemoryStream(content)) diff --git a/src/Ocelot/Responder/Middleware/ResponderMiddleware.cs b/src/Ocelot/Responder/Middleware/ResponderMiddleware.cs index bac062f8..4bfbad7a 100644 --- a/src/Ocelot/Responder/Middleware/ResponderMiddleware.cs +++ b/src/Ocelot/Responder/Middleware/ResponderMiddleware.cs @@ -29,7 +29,6 @@ namespace Ocelot.Responder.Middleware _responder = responder; _codeMapper = codeMapper; _logger = loggerFactory.CreateLogger(); - } public async Task Invoke(DownstreamContext context) diff --git a/src/Ocelot/Responses/ErrorResponse.cs b/src/Ocelot/Responses/ErrorResponse.cs index 28cd3f02..7a6688e7 100644 --- a/src/Ocelot/Responses/ErrorResponse.cs +++ b/src/Ocelot/Responses/ErrorResponse.cs @@ -8,8 +8,9 @@ namespace Ocelot.Responses public ErrorResponse(Error error) : base(new List{error}) { } + public ErrorResponse(List errors) : base(errors) { } } -} \ No newline at end of file +} diff --git a/src/Ocelot/Responses/ErrorResponseGeneric.cs b/src/Ocelot/Responses/ErrorResponseGeneric.cs index 837c2e5d..90a16cdd 100644 --- a/src/Ocelot/Responses/ErrorResponseGeneric.cs +++ b/src/Ocelot/Responses/ErrorResponseGeneric.cs @@ -7,12 +7,12 @@ namespace Ocelot.Responses { public ErrorResponse(Error error) : base(new List {error}) - { - + { } + public ErrorResponse(List errors) : base(errors) { } } -} \ No newline at end of file +} diff --git a/src/Ocelot/Responses/ResponseGeneric.cs b/src/Ocelot/Responses/ResponseGeneric.cs index 479dd08d..d06314bf 100644 --- a/src/Ocelot/Responses/ResponseGeneric.cs +++ b/src/Ocelot/Responses/ResponseGeneric.cs @@ -14,7 +14,6 @@ namespace Ocelot.Responses { } - public T Data { get; private set; } - + public T Data { get; private set; } } -} \ No newline at end of file +} diff --git a/src/Ocelot/ServiceDiscovery/ServiceDiscoveryProviderFactory.cs b/src/Ocelot/ServiceDiscovery/ServiceDiscoveryProviderFactory.cs index 0e75cb1a..09db94e4 100644 --- a/src/Ocelot/ServiceDiscovery/ServiceDiscoveryProviderFactory.cs +++ b/src/Ocelot/ServiceDiscovery/ServiceDiscoveryProviderFactory.cs @@ -14,7 +14,7 @@ namespace Ocelot.ServiceDiscovery _factory = factory; } - public IServiceDiscoveryProvider Get(ServiceProviderConfiguration serviceConfig, DownstreamReRoute reRoute) + public IServiceDiscoveryProvider Get(ServiceProviderConfiguration serviceConfig, DownstreamReRoute reRoute) { if (reRoute.UseServiceDiscovery) { diff --git a/src/Ocelot/Values/Service.cs b/src/Ocelot/Values/Service.cs index 1acb26e6..abf5449b 100644 --- a/src/Ocelot/Values/Service.cs +++ b/src/Ocelot/Values/Service.cs @@ -16,6 +16,7 @@ namespace Ocelot.Values Version = version; Tags = tags; } + public string Id { get; private set; } public string Name { get; private set; } diff --git a/test/Ocelot.AcceptanceTests/AuthorisationTests.cs b/test/Ocelot.AcceptanceTests/AuthorisationTests.cs index aaa4faff..06fee4ef 100644 --- a/test/Ocelot.AcceptanceTests/AuthorisationTests.cs +++ b/test/Ocelot.AcceptanceTests/AuthorisationTests.cs @@ -177,7 +177,7 @@ namespace Ocelot.AcceptanceTests AuthenticationOptions = new FileAuthenticationOptions { AuthenticationProviderKey = "Test", - AllowedScopes = new List{ "api", "api.readOnly", "openid", "offline_access" }, + AllowedScopes = new List{ "api", "api.readOnly", "openid", "offline_access" }, }, } } @@ -218,7 +218,7 @@ namespace Ocelot.AcceptanceTests AuthenticationOptions = new FileAuthenticationOptions { AuthenticationProviderKey = "Test", - AllowedScopes = new List{ "api", "openid", "offline_access" }, + AllowedScopes = new List{ "api", "openid", "offline_access" }, }, } } @@ -356,7 +356,6 @@ namespace Ocelot.AcceptanceTests "CustomerId", "LocationId", "UserType", "UserId" } }, - }) .AddInMemoryClients(new List { @@ -437,7 +436,6 @@ namespace Ocelot.AcceptanceTests "CustomerId", "LocationId", "UserType", "UserId", "Role" } }, - }) .AddInMemoryClients(new List { @@ -450,7 +448,6 @@ namespace Ocelot.AcceptanceTests AccessTokenType = tokenType, Enabled = true, RequireClientSecret = false, - } }) .AddTestUsers(users); diff --git a/test/Ocelot.AcceptanceTests/ButterflyTracingTests.cs b/test/Ocelot.AcceptanceTests/ButterflyTracingTests.cs index 84346985..52a589c1 100644 --- a/test/Ocelot.AcceptanceTests/ButterflyTracingTests.cs +++ b/test/Ocelot.AcceptanceTests/ButterflyTracingTests.cs @@ -52,7 +52,7 @@ namespace Ocelot.AcceptanceTests UpstreamHttpMethod = new List { "Get" }, HttpHandlerOptions = new FileHttpHandlerOptions { - UseTracing = true + UseTracing = true }, QoSOptions = new FileQoSOptions { @@ -77,7 +77,7 @@ namespace Ocelot.AcceptanceTests UpstreamHttpMethod = new List { "Get" }, HttpHandlerOptions = new FileHttpHandlerOptions { - UseTracing = true + UseTracing = true }, QoSOptions = new FileQoSOptions { diff --git a/test/Ocelot.AcceptanceTests/ClaimsToQueryStringForwardingTests.cs b/test/Ocelot.AcceptanceTests/ClaimsToQueryStringForwardingTests.cs index b8c1a59e..f73a360e 100644 --- a/test/Ocelot.AcceptanceTests/ClaimsToQueryStringForwardingTests.cs +++ b/test/Ocelot.AcceptanceTests/ClaimsToQueryStringForwardingTests.cs @@ -156,7 +156,7 @@ namespace Ocelot.AcceptanceTests { new ApiResource { - Name = apiName, + Name = apiName, Description = "My API", Enabled = true, DisplayName = "test", diff --git a/test/Ocelot.AcceptanceTests/ClientRateLimitTests.cs b/test/Ocelot.AcceptanceTests/ClientRateLimitTests.cs index 11ec83b1..fb09591b 100644 --- a/test/Ocelot.AcceptanceTests/ClientRateLimitTests.cs +++ b/test/Ocelot.AcceptanceTests/ClientRateLimitTests.cs @@ -56,7 +56,7 @@ namespace Ocelot.AcceptanceTests UpstreamHttpMethod = new List { "Get" }, RequestIdKey = _steps.RequestIdKey, - RateLimitOptions = new FileRateLimitRule() + RateLimitOptions = new FileRateLimitRule() { EnableRateLimiting = true, ClientWhitelist = new List(), @@ -75,7 +75,6 @@ namespace Ocelot.AcceptanceTests QuotaExceededMessage = "", RateLimitCounterPrefix = "", HttpStatusCode = 428 - }, RequestIdKey ="oceclientrequest" } @@ -117,7 +116,7 @@ namespace Ocelot.AcceptanceTests UpstreamHttpMethod = new List { "Get" }, RequestIdKey = _steps.RequestIdKey, - RateLimitOptions = new FileRateLimitRule() + RateLimitOptions = new FileRateLimitRule() { EnableRateLimiting = true, ClientWhitelist = new List() { "ocelotclient1"}, @@ -172,7 +171,5 @@ namespace Ocelot.AcceptanceTests _builder.Start(); } - - } } diff --git a/test/Ocelot.AcceptanceTests/CustomMiddlewareTests.cs b/test/Ocelot.AcceptanceTests/CustomMiddlewareTests.cs index 0f30ba73..2171f72d 100644 --- a/test/Ocelot.AcceptanceTests/CustomMiddlewareTests.cs +++ b/test/Ocelot.AcceptanceTests/CustomMiddlewareTests.cs @@ -352,7 +352,6 @@ namespace Ocelot.AcceptanceTests app.UsePathBase(basePath); app.Run(context => { - if(string.IsNullOrEmpty(basePath)) { context.Response.StatusCode = statusCode; diff --git a/test/Ocelot.AcceptanceTests/HttpDelegatingHandlersTests.cs b/test/Ocelot.AcceptanceTests/HttpDelegatingHandlersTests.cs index bb2a43df..c54294cd 100644 --- a/test/Ocelot.AcceptanceTests/HttpDelegatingHandlersTests.cs +++ b/test/Ocelot.AcceptanceTests/HttpDelegatingHandlersTests.cs @@ -70,8 +70,7 @@ namespace Ocelot.AcceptanceTests } class FakeHandler : DelegatingHandler - { - + { public DateTime TimeCalled { get; private set; } protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) @@ -111,6 +110,5 @@ namespace Ocelot.AcceptanceTests _builder.Start(); } - } } diff --git a/test/Ocelot.AcceptanceTests/LoadBalancerTests.cs b/test/Ocelot.AcceptanceTests/LoadBalancerTests.cs index a5c5e07c..d67e7e41 100644 --- a/test/Ocelot.AcceptanceTests/LoadBalancerTests.cs +++ b/test/Ocelot.AcceptanceTests/LoadBalancerTests.cs @@ -159,8 +159,7 @@ namespace Ocelot.AcceptanceTests catch (System.Exception exception) { await context.Response.WriteAsync(exception.StackTrace); - } - + } }); }) .Build(); diff --git a/test/Ocelot.AcceptanceTests/QoSTests.cs b/test/Ocelot.AcceptanceTests/QoSTests.cs index e4f8a026..d11721b8 100644 --- a/test/Ocelot.AcceptanceTests/QoSTests.cs +++ b/test/Ocelot.AcceptanceTests/QoSTests.cs @@ -51,8 +51,7 @@ namespace Ocelot.AcceptanceTests ExceptionsAllowedBeforeBreaking = 1, TimeoutValue = 500, DurationOfBreak = 1000 - }, - + }, } } }; diff --git a/test/Ocelot.AcceptanceTests/ServiceDiscoveryTests.cs b/test/Ocelot.AcceptanceTests/ServiceDiscoveryTests.cs index 572c7126..97e104c4 100644 --- a/test/Ocelot.AcceptanceTests/ServiceDiscoveryTests.cs +++ b/test/Ocelot.AcceptanceTests/ServiceDiscoveryTests.cs @@ -359,8 +359,7 @@ namespace Ocelot.AcceptanceTests catch (System.Exception exception) { await context.Response.WriteAsync(exception.StackTrace); - } - + } }); }) .Build(); @@ -406,4 +405,4 @@ namespace Ocelot.AcceptanceTests _steps.Dispose(); } } -} \ No newline at end of file +} diff --git a/test/Ocelot.AcceptanceTests/Steps.cs b/test/Ocelot.AcceptanceTests/Steps.cs index 6a6fa3c4..09f68998 100644 --- a/test/Ocelot.AcceptanceTests/Steps.cs +++ b/test/Ocelot.AcceptanceTests/Steps.cs @@ -144,6 +144,7 @@ namespace Ocelot.AcceptanceTests _ocelotClient = _ocelotServer.CreateClient(); } + /* public void GivenIHaveAddedXForwardedForHeader(string value) { diff --git a/test/Ocelot.Benchmarks/Program.cs b/test/Ocelot.Benchmarks/Program.cs index 231a816b..56b87404 100644 --- a/test/Ocelot.Benchmarks/Program.cs +++ b/test/Ocelot.Benchmarks/Program.cs @@ -8,7 +8,6 @@ namespace Ocelot.Benchmarks { var switcher = new BenchmarkSwitcher(new[] { typeof(UrlPathToUrlPathTemplateMatcherBenchmarks), - }); switcher.Run(args); diff --git a/test/Ocelot.IntegrationTests/AdministrationTests.cs b/test/Ocelot.IntegrationTests/AdministrationTests.cs index 3b2f6a35..e9fc390d 100644 --- a/test/Ocelot.IntegrationTests/AdministrationTests.cs +++ b/test/Ocelot.IntegrationTests/AdministrationTests.cs @@ -124,7 +124,6 @@ namespace Ocelot.IntegrationTests { Host = "127.0.0.1", } - }, ReRoutes = new List() { diff --git a/test/Ocelot.IntegrationTests/RaftTests.cs b/test/Ocelot.IntegrationTests/RaftTests.cs index e93e9ee4..b8c24d5a 100644 --- a/test/Ocelot.IntegrationTests/RaftTests.cs +++ b/test/Ocelot.IntegrationTests/RaftTests.cs @@ -45,6 +45,7 @@ namespace Ocelot.IntegrationTests _builders = new List(); _threads = new List(); } + public void Dispose() { foreach (var builder in _builders) @@ -194,7 +195,6 @@ namespace Ocelot.IntegrationTests var stopwatch = Stopwatch.StartNew(); while(stopwatch.ElapsedMilliseconds < 10000) { - } } @@ -204,10 +204,9 @@ namespace Ocelot.IntegrationTests var stopwatch = Stopwatch.StartNew(); while(stopwatch.ElapsedMilliseconds < 2000) { - } - bool CommandCalledOnAllStateMachines() + bool CommandCalledOnAllStateMachines() { try { @@ -225,6 +224,7 @@ namespace Ocelot.IntegrationTests index.ShouldBe(1); } } + _httpClientForAssertions.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", _token.AccessToken); var result = _httpClientForAssertions.GetAsync($"{peer.HostAndPort}/administration/configuration").Result; var json = result.Content.ReadAsStringAsync().Result; @@ -248,6 +248,7 @@ namespace Ocelot.IntegrationTests response.ReRoutes[i].UpstreamPathTemplate.ShouldBe(expecteds.Configuration.ReRoutes[i].UpstreamPathTemplate); response.ReRoutes[i].UpstreamHttpMethod.ShouldBe(expecteds.Configuration.ReRoutes[i].UpstreamHttpMethod); } + passed++; } @@ -384,7 +385,6 @@ namespace Ocelot.IntegrationTests var stopwatch = Stopwatch.StartNew(); while(stopwatch.ElapsedMilliseconds < 20000) { - } } } diff --git a/test/Ocelot.IntegrationTests/ThreadSafeHeadersTests.cs b/test/Ocelot.IntegrationTests/ThreadSafeHeadersTests.cs index f8533a04..e61fa63b 100644 --- a/test/Ocelot.IntegrationTests/ThreadSafeHeadersTests.cs +++ b/test/Ocelot.IntegrationTests/ThreadSafeHeadersTests.cs @@ -195,6 +195,7 @@ namespace Ocelot.IntegrationTests result.Result.ShouldBe(result.Random); } } + public void Dispose() { _builder?.Dispose(); @@ -208,7 +209,6 @@ namespace Ocelot.IntegrationTests { Result = result; Random = random; - } public int Result { get; private set; } diff --git a/test/Ocelot.UnitTests/Authentication/AuthenticationMiddlewareTests.cs b/test/Ocelot.UnitTests/Authentication/AuthenticationMiddlewareTests.cs index 07368127..1ab81895 100644 --- a/test/Ocelot.UnitTests/Authentication/AuthenticationMiddlewareTests.cs +++ b/test/Ocelot.UnitTests/Authentication/AuthenticationMiddlewareTests.cs @@ -49,7 +49,7 @@ namespace Ocelot.UnitTests.Authentication .BDDfy(); } - private void WhenICallTheMiddleware() + private void WhenICallTheMiddleware() { _next = async (context) => { byte[] byteArray = Encoding.ASCII.GetBytes("The user is authenticated"); @@ -89,7 +89,7 @@ namespace Ocelot.UnitTests.Authentication { string text = reader.ReadToEnd(); return text; - }; + } } } } diff --git a/test/Ocelot.UnitTests/Authorization/ClaimsAuthoriserTests.cs b/test/Ocelot.UnitTests/Authorization/ClaimsAuthoriserTests.cs index 0333268b..e2990864 100644 --- a/test/Ocelot.UnitTests/Authorization/ClaimsAuthoriserTests.cs +++ b/test/Ocelot.UnitTests/Authorization/ClaimsAuthoriserTests.cs @@ -28,7 +28,6 @@ namespace Ocelot.UnitTests.Authorization this.Given(x => x.GivenAClaimsPrincipal(new ClaimsPrincipal(new ClaimsIdentity(new List { new Claim("UserType", "registered"), - })))) .And(x => x.GivenARouteClaimsRequirement(new Dictionary { diff --git a/test/Ocelot.UnitTests/Cache/OutputCacheMiddlewareTests.cs b/test/Ocelot.UnitTests/Cache/OutputCacheMiddlewareTests.cs index 42c1e695..31cc11a8 100644 --- a/test/Ocelot.UnitTests/Cache/OutputCacheMiddlewareTests.cs +++ b/test/Ocelot.UnitTests/Cache/OutputCacheMiddlewareTests.cs @@ -110,7 +110,6 @@ namespace Ocelot.UnitTests.Cache private void GivenThereAreNoErrors() { _downstreamContext.Errors = new List(); - } private void ThenTheCacheGetIsCalledCorrectly() diff --git a/test/Ocelot.UnitTests/Claims/AddClaimsToRequestTests.cs b/test/Ocelot.UnitTests/Claims/AddClaimsToRequestTests.cs index ac60ee8b..cdb5c4c7 100644 --- a/test/Ocelot.UnitTests/Claims/AddClaimsToRequestTests.cs +++ b/test/Ocelot.UnitTests/Claims/AddClaimsToRequestTests.cs @@ -129,7 +129,6 @@ namespace Ocelot.UnitTests.Claims private void ThenTheResultIsError() { - _result.IsError.ShouldBe(true); } diff --git a/test/Ocelot.UnitTests/Configuration/ClaimsToThingCreatorTests.cs b/test/Ocelot.UnitTests/Configuration/ClaimsToThingCreatorTests.cs index 656fe5dc..522d853f 100644 --- a/test/Ocelot.UnitTests/Configuration/ClaimsToThingCreatorTests.cs +++ b/test/Ocelot.UnitTests/Configuration/ClaimsToThingCreatorTests.cs @@ -79,6 +79,7 @@ namespace Ocelot.UnitTests.Configuration { _result.Count.ShouldBeGreaterThan(0); } + private void GivenTheFollowingDictionary(Dictionary claimsToThings) { _claimsToThings = claimsToThings; @@ -107,4 +108,4 @@ namespace Ocelot.UnitTests.Configuration .Verify(x => x.Extract(_claimsToThings.First().Key, _claimsToThings.First().Value), Times.Once); } } -} \ No newline at end of file +} diff --git a/test/Ocelot.UnitTests/Configuration/ConfigurationFluentValidationTests.cs b/test/Ocelot.UnitTests/Configuration/ConfigurationFluentValidationTests.cs index e7e56178..632461fc 100644 --- a/test/Ocelot.UnitTests/Configuration/ConfigurationFluentValidationTests.cs +++ b/test/Ocelot.UnitTests/Configuration/ConfigurationFluentValidationTests.cs @@ -981,7 +981,8 @@ namespace Ocelot.UnitTests.Configuration .And(x => x.ThenTheErrorMessageAtPositionIs(0, "When not using service discovery DownstreamHostAndPorts must be set and not empty or Ocelot cannot find your service!")) .BDDfy(); } - [Fact] + + [Fact] public void configuration_is_not_valid_when_host_and_port_is_empty() { this.Given(x => x.GivenAConfiguration(new FileConfiguration diff --git a/test/Ocelot.UnitTests/Configuration/ConsulFileConfigurationPollerTests.cs b/test/Ocelot.UnitTests/Configuration/ConsulFileConfigurationPollerTests.cs index 64104871..10c8a012 100644 --- a/test/Ocelot.UnitTests/Configuration/ConsulFileConfigurationPollerTests.cs +++ b/test/Ocelot.UnitTests/Configuration/ConsulFileConfigurationPollerTests.cs @@ -34,6 +34,7 @@ namespace Ocelot.UnitTests.Configuration _repo.Setup(x => x.Get()).ReturnsAsync(new OkResponse(_fileConfig)); _poller = new ConsulFileConfigurationPoller(_factory.Object, _repo.Object, _setter.Object); } + public void Dispose() { _poller.Dispose(); @@ -49,7 +50,6 @@ namespace Ocelot.UnitTests.Configuration [Fact] public void should_call_setter_when_gets_new_config() { - var newConfig = new FileConfiguration { ReRoutes = new List { diff --git a/test/Ocelot.UnitTests/Configuration/FileConfigurationCreatorTests.cs b/test/Ocelot.UnitTests/Configuration/FileConfigurationCreatorTests.cs index 8bb0ecd2..cb6615bf 100644 --- a/test/Ocelot.UnitTests/Configuration/FileConfigurationCreatorTests.cs +++ b/test/Ocelot.UnitTests/Configuration/FileConfigurationCreatorTests.cs @@ -823,8 +823,7 @@ namespace Ocelot.UnitTests.Configuration result.DownstreamReRoute[0].ClaimsToClaims.Count.ShouldBe(expected.DownstreamReRoute[0].ClaimsToClaims.Count); result.DownstreamReRoute[0].ClaimsToHeaders.Count.ShouldBe(expected.DownstreamReRoute[0].ClaimsToHeaders.Count); result.DownstreamReRoute[0].ClaimsToQueries.Count.ShouldBe(expected.DownstreamReRoute[0].ClaimsToQueries.Count); - result.DownstreamReRoute[0].RequestIdKey.ShouldBe(expected.DownstreamReRoute[0].RequestIdKey); - + result.DownstreamReRoute[0].RequestIdKey.ShouldBe(expected.DownstreamReRoute[0].RequestIdKey); } } diff --git a/test/Ocelot.UnitTests/Configuration/FileConfigurationRepositoryTests.cs b/test/Ocelot.UnitTests/Configuration/FileConfigurationRepositoryTests.cs index e74d0067..15dd3729 100644 --- a/test/Ocelot.UnitTests/Configuration/FileConfigurationRepositoryTests.cs +++ b/test/Ocelot.UnitTests/Configuration/FileConfigurationRepositoryTests.cs @@ -111,7 +111,7 @@ namespace Ocelot.UnitTests.Configuration } } - private void GivenTheConfigurationIs(FileConfiguration fileConfiguration) + private void GivenTheConfigurationIs(FileConfiguration fileConfiguration) { var configurationPath = $"{AppContext.BaseDirectory}/configuration{(string.IsNullOrEmpty(_environmentName) ? string.Empty : ".")}{_environmentName}.json"; diff --git a/test/Ocelot.UnitTests/Configuration/HeaderFindAndReplaceCreatorTests.cs b/test/Ocelot.UnitTests/Configuration/HeaderFindAndReplaceCreatorTests.cs index 76c3c47f..3c817295 100644 --- a/test/Ocelot.UnitTests/Configuration/HeaderFindAndReplaceCreatorTests.cs +++ b/test/Ocelot.UnitTests/Configuration/HeaderFindAndReplaceCreatorTests.cs @@ -33,13 +33,11 @@ namespace Ocelot.UnitTests.Configuration UpstreamHeaderTransform = new Dictionary { {"Test", "Test, Chicken"}, - {"Moop", "o, a"} }, DownstreamHeaderTransform = new Dictionary { {"Pop", "West, East"}, - {"Bop", "e, r"} } }; @@ -155,4 +153,4 @@ namespace Ocelot.UnitTests.Configuration } } } -} \ No newline at end of file +} diff --git a/test/Ocelot.UnitTests/Configuration/HttpHandlerOptionsCreatorTests.cs b/test/Ocelot.UnitTests/Configuration/HttpHandlerOptionsCreatorTests.cs index 3821ef6b..b0b11bfc 100644 --- a/test/Ocelot.UnitTests/Configuration/HttpHandlerOptionsCreatorTests.cs +++ b/test/Ocelot.UnitTests/Configuration/HttpHandlerOptionsCreatorTests.cs @@ -7,7 +7,6 @@ using Xunit; namespace Ocelot.UnitTests.Configuration { - public class HttpHandlerOptionsCreatorTests { private readonly IHttpHandlerOptionsCreator _httpHandlerOptionsCreator; diff --git a/test/Ocelot.UnitTests/Configuration/UpstreamTemplatePatternCreatorTests.cs b/test/Ocelot.UnitTests/Configuration/UpstreamTemplatePatternCreatorTests.cs index ab7fba4a..c8e79675 100644 --- a/test/Ocelot.UnitTests/Configuration/UpstreamTemplatePatternCreatorTests.cs +++ b/test/Ocelot.UnitTests/Configuration/UpstreamTemplatePatternCreatorTests.cs @@ -70,7 +70,7 @@ namespace Ocelot.UnitTests.Configuration [Fact] public void should_create_template_pattern_that_matches_anything_to_end_of_string() { - var fileReRoute = new FileReRoute + var fileReRoute = new FileReRoute { UpstreamPathTemplate = "/api/products/{productId}", ReRouteIsCaseSensitive = true @@ -181,4 +181,4 @@ namespace Ocelot.UnitTests.Configuration _result.Priority.ShouldBe(v); } } -} \ No newline at end of file +} diff --git a/test/Ocelot.UnitTests/DependencyInjection/OcelotBuilderTests.cs b/test/Ocelot.UnitTests/DependencyInjection/OcelotBuilderTests.cs index 6f256d7f..e33ee812 100644 --- a/test/Ocelot.UnitTests/DependencyInjection/OcelotBuilderTests.cs +++ b/test/Ocelot.UnitTests/DependencyInjection/OcelotBuilderTests.cs @@ -38,6 +38,7 @@ namespace Ocelot.UnitTests.DependencyInjection _services.AddSingleton(_configRoot); _maxRetries = 100; } + private Exception _ex; [Fact] @@ -102,9 +103,7 @@ namespace Ocelot.UnitTests.DependencyInjection [Fact] public void should_set_up_administration_with_identity_server_options() { - Action options = o => { - - }; + Action options = o => {}; this.Given(x => WhenISetUpOcelotServices()) .When(x => WhenISetUpAdministration(options)) diff --git a/test/Ocelot.UnitTests/Errors/ExceptionHandlerMiddlewareTests.cs b/test/Ocelot.UnitTests/Errors/ExceptionHandlerMiddlewareTests.cs index c5180f74..e6c3e7ca 100644 --- a/test/Ocelot.UnitTests/Errors/ExceptionHandlerMiddlewareTests.cs +++ b/test/Ocelot.UnitTests/Errors/ExceptionHandlerMiddlewareTests.cs @@ -135,7 +135,7 @@ namespace Ocelot.UnitTests.Errors private void GivenTheConfigThrows() { - var ex = new Exception("outer", new Exception("inner")); + var ex = new Exception("outer", new Exception("inner")); _provider .Setup(x => x.Get()).ThrowsAsync(ex); } @@ -192,7 +192,6 @@ namespace Ocelot.UnitTests.Errors private void ThenTheResponseIsError() { - _downstreamContext.HttpContext.Response.StatusCode.ShouldBe(500); } diff --git a/test/Ocelot.UnitTests/Headers/AddHeadersToRequestTests.cs b/test/Ocelot.UnitTests/Headers/AddHeadersToRequestTests.cs index f69c6b9e..0a8290bc 100644 --- a/test/Ocelot.UnitTests/Headers/AddHeadersToRequestTests.cs +++ b/test/Ocelot.UnitTests/Headers/AddHeadersToRequestTests.cs @@ -130,7 +130,6 @@ namespace Ocelot.UnitTests.Headers private void ThenTheResultIsError() { - _result.IsError.ShouldBe(true); } diff --git a/test/Ocelot.UnitTests/Headers/HttpHeadersTransformationMiddlewareTests.cs b/test/Ocelot.UnitTests/Headers/HttpHeadersTransformationMiddlewareTests.cs index 90a24eaa..0a69bf89 100644 --- a/test/Ocelot.UnitTests/Headers/HttpHeadersTransformationMiddlewareTests.cs +++ b/test/Ocelot.UnitTests/Headers/HttpHeadersTransformationMiddlewareTests.cs @@ -80,7 +80,6 @@ namespace Ocelot.UnitTests.Headers _downstreamContext.TemplatePlaceholderNameAndValues = dR.TemplatePlaceholderNameAndValues; _downstreamContext.DownstreamReRoute = dR.ReRoute.DownstreamReRoute[0]; - } private void ThenTheIHttpContextRequestHeaderReplacerIsCalledCorrectly() diff --git a/test/Ocelot.UnitTests/Headers/HttpResponseHeaderReplacerTests.cs b/test/Ocelot.UnitTests/Headers/HttpResponseHeaderReplacerTests.cs index de8161c9..6b65bb67 100644 --- a/test/Ocelot.UnitTests/Headers/HttpResponseHeaderReplacerTests.cs +++ b/test/Ocelot.UnitTests/Headers/HttpResponseHeaderReplacerTests.cs @@ -22,6 +22,7 @@ namespace Ocelot.UnitTests.Headers { _replacer = new HttpResponseHeaderReplacer(); } + [Fact] public void should_replace_headers() { @@ -232,4 +233,4 @@ namespace Ocelot.UnitTests.Headers } } } -} \ No newline at end of file +} diff --git a/test/Ocelot.UnitTests/Infrastructure/HttpDataRepositoryTests.cs b/test/Ocelot.UnitTests/Infrastructure/HttpDataRepositoryTests.cs index df5068d3..407e9f47 100644 --- a/test/Ocelot.UnitTests/Infrastructure/HttpDataRepositoryTests.cs +++ b/test/Ocelot.UnitTests/Infrastructure/HttpDataRepositoryTests.cs @@ -27,7 +27,6 @@ namespace Ocelot.UnitTests.Infrastructure [Fact] public void get_returns_correct_key_from_http_context() { - this.Given(x => x.GivenAHttpContextContaining("key", "string")) .When(x => x.GetIsCalledWithKey("key")) .Then(x => x.ThenTheResultIsAnOkResponse("string")) @@ -83,6 +82,5 @@ namespace Ocelot.UnitTests.Infrastructure _result.ShouldBeOfType>(); ((OkResponse)_result).Data.ShouldBe(resultValue); } - } } diff --git a/test/Ocelot.UnitTests/LoadBalancer/LeastConnectionTests.cs b/test/Ocelot.UnitTests/LoadBalancer/LeastConnectionTests.cs index e372ac4e..687f8f40 100644 --- a/test/Ocelot.UnitTests/LoadBalancer/LeastConnectionTests.cs +++ b/test/Ocelot.UnitTests/LoadBalancer/LeastConnectionTests.cs @@ -91,7 +91,6 @@ namespace Ocelot.UnitTests.LoadBalancer hostAndPortTwo.Data.DownstreamHost.ShouldBe("127.0.0.2"); _leastConnection.Release(hostAndPortOne.Data); _leastConnection.Release(hostAndPortTwo.Data); - } private async Task LeaseDelayAndRelease() diff --git a/test/Ocelot.UnitTests/LoadBalancer/LoadBalancerMiddlewareTests.cs b/test/Ocelot.UnitTests/LoadBalancer/LoadBalancerMiddlewareTests.cs index 310c1818..0af8b3af 100644 --- a/test/Ocelot.UnitTests/LoadBalancer/LoadBalancerMiddlewareTests.cs +++ b/test/Ocelot.UnitTests/LoadBalancer/LoadBalancerMiddlewareTests.cs @@ -188,7 +188,6 @@ namespace Ocelot.UnitTests.LoadBalancer { _downstreamContext.IsError.ShouldBeTrue(); _downstreamContext.Errors.ShouldBe(_getHostAndPortError.Errors); - } private void ThenTheDownstreamUrlIsReplacedWith(string expectedUri) diff --git a/test/Ocelot.UnitTests/Middleware/MultiplexerTests.cs b/test/Ocelot.UnitTests/Middleware/MultiplexerTests.cs index 8a0e5670..adef00d5 100644 --- a/test/Ocelot.UnitTests/Middleware/MultiplexerTests.cs +++ b/test/Ocelot.UnitTests/Middleware/MultiplexerTests.cs @@ -58,7 +58,6 @@ namespace Ocelot.UnitTests.Middleware private void WhenIMultiplex() { _multiplexer.Multiplex(_context, _reRoute, _pipeline).GetAwaiter().GetResult(); - } private void ThePipelineIsCalled(int expected) diff --git a/test/Ocelot.UnitTests/Request/DownstreamRequestInitialiserMiddlewareTests.cs b/test/Ocelot.UnitTests/Request/DownstreamRequestInitialiserMiddlewareTests.cs index 5661ace6..2bd26a4b 100644 --- a/test/Ocelot.UnitTests/Request/DownstreamRequestInitialiserMiddlewareTests.cs +++ b/test/Ocelot.UnitTests/Request/DownstreamRequestInitialiserMiddlewareTests.cs @@ -36,7 +36,6 @@ namespace Ocelot.UnitTests.Request public DownstreamRequestInitialiserMiddlewareTests() { - _httpContext = new Mock(); _httpRequest = new Mock(); _requestMapper = new Mock(); diff --git a/test/Ocelot.UnitTests/Requester/FakeDelegatingHandler.cs b/test/Ocelot.UnitTests/Requester/FakeDelegatingHandler.cs index 545e956e..a53487a3 100644 --- a/test/Ocelot.UnitTests/Requester/FakeDelegatingHandler.cs +++ b/test/Ocelot.UnitTests/Requester/FakeDelegatingHandler.cs @@ -9,13 +9,13 @@ namespace Ocelot.UnitTests.Requester { public FakeDelegatingHandler() { - } public FakeDelegatingHandler(int order) { Order = order; } + public int Order {get;private set;} public DateTime TimeCalled {get;private set;} @@ -25,4 +25,4 @@ namespace Ocelot.UnitTests.Requester return new HttpResponseMessage(); } } -} \ No newline at end of file +} diff --git a/test/Ocelot.UnitTests/ServiceDiscovery/ServiceRegistryTests.cs b/test/Ocelot.UnitTests/ServiceDiscovery/ServiceRegistryTests.cs index 8a41fe7e..1079f201 100644 --- a/test/Ocelot.UnitTests/ServiceDiscovery/ServiceRegistryTests.cs +++ b/test/Ocelot.UnitTests/ServiceDiscovery/ServiceRegistryTests.cs @@ -131,8 +131,7 @@ namespace Ocelot.UnitTests.ServiceDiscovery else { _registeredServices[serviceNameAndAddress.Name] = new List(){ serviceNameAndAddress }; - } - + } } } } From edbed051deaba9caf2fb7c359f6ff6894a6e646a Mon Sep 17 00:00:00 2001 From: Philip Wood Date: Sat, 3 Mar 2018 13:16:26 +0000 Subject: [PATCH 14/26] Remove blank lines at start/end of files SA1517, SA1518 --- .../Authentication/Middleware/AuthenticationMiddleware.cs | 1 - src/Ocelot/Configuration/File/FileGlobalConfiguration.cs | 3 +-- src/Ocelot/Request/Mapper/RequestMapper.cs | 1 - test/Ocelot.AcceptanceTests/CannotStartOcelotTests.cs | 3 +-- 4 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/Ocelot/Authentication/Middleware/AuthenticationMiddleware.cs b/src/Ocelot/Authentication/Middleware/AuthenticationMiddleware.cs index ffdd1ac6..bd4683d0 100644 --- a/src/Ocelot/Authentication/Middleware/AuthenticationMiddleware.cs +++ b/src/Ocelot/Authentication/Middleware/AuthenticationMiddleware.cs @@ -63,4 +63,3 @@ namespace Ocelot.Authentication.Middleware } } } - diff --git a/src/Ocelot/Configuration/File/FileGlobalConfiguration.cs b/src/Ocelot/Configuration/File/FileGlobalConfiguration.cs index adbbdce1..8dea9ed6 100644 --- a/src/Ocelot/Configuration/File/FileGlobalConfiguration.cs +++ b/src/Ocelot/Configuration/File/FileGlobalConfiguration.cs @@ -1,5 +1,4 @@ - -namespace Ocelot.Configuration.File +namespace Ocelot.Configuration.File { public class FileGlobalConfiguration { diff --git a/src/Ocelot/Request/Mapper/RequestMapper.cs b/src/Ocelot/Request/Mapper/RequestMapper.cs index a6f22d6d..9af0d08e 100644 --- a/src/Ocelot/Request/Mapper/RequestMapper.cs +++ b/src/Ocelot/Request/Mapper/RequestMapper.cs @@ -92,4 +92,3 @@ } } } - diff --git a/test/Ocelot.AcceptanceTests/CannotStartOcelotTests.cs b/test/Ocelot.AcceptanceTests/CannotStartOcelotTests.cs index a4dfcac6..f6c77b1c 100644 --- a/test/Ocelot.AcceptanceTests/CannotStartOcelotTests.cs +++ b/test/Ocelot.AcceptanceTests/CannotStartOcelotTests.cs @@ -1,4 +1,3 @@ - using System; using System.Collections.Generic; using Microsoft.AspNetCore.Hosting; @@ -55,4 +54,4 @@ namespace Ocelot.AcceptanceTests _steps.Dispose(); } } -} \ No newline at end of file +} From 167fbb3dafb76abab4969bf9255d428282473518 Mon Sep 17 00:00:00 2001 From: Philip Wood Date: Sat, 3 Mar 2018 13:26:27 +0000 Subject: [PATCH 15/26] Remove multiple concurrent blank lines SA1507 --- src/Ocelot/Cache/Middleware/OutputCacheMiddleware.cs | 1 - src/Ocelot/Configuration/Builder/DownstreamReRouteBuilder.cs | 1 - .../Configuration/Creator/FileOcelotConfigurationCreator.cs | 1 - .../Configuration/Creator/UpstreamTemplatePatternCreator.cs | 1 - src/Ocelot/Configuration/QoSOptions.cs | 3 +-- src/Ocelot/DependencyInjection/OcelotBuilder.cs | 3 +-- .../Middleware/DownstreamRouteFinderMiddleware.cs | 1 - src/Ocelot/DownstreamUrlCreator/UrlBuilder.cs | 1 - src/Ocelot/Infrastructure/Claims/Parser/ClaimsParser.cs | 2 -- src/Ocelot/LoadBalancer/LoadBalancers/RoundRobin.cs | 1 - src/Ocelot/RateLimit/ClientRateLimitProcessor.cs | 1 - src/Ocelot/RequestId/Middleware/ReRouteRequestIdMiddleware.cs | 1 - test/Ocelot.AcceptanceTests/AggregateTests.cs | 1 - test/Ocelot.AcceptanceTests/ButterflyTracingTests.cs | 1 - test/Ocelot.AcceptanceTests/ClientRateLimitTests.cs | 4 ---- test/Ocelot.AcceptanceTests/ConfigurationInConsulTests.cs | 1 - test/Ocelot.AcceptanceTests/CustomMiddlewareTests.cs | 1 - test/Ocelot.AcceptanceTests/HeaderTests.cs | 1 - test/Ocelot.AcceptanceTests/RoutingTests.cs | 3 --- test/Ocelot.AcceptanceTests/UpstreamHostTests.cs | 1 - test/Ocelot.IntegrationTests/AdministrationTests.cs | 1 - test/Ocelot.UnitTests/Claims/AddClaimsToRequestTests.cs | 1 - test/Ocelot.UnitTests/Claims/ClaimsBuilderMiddlewareTests.cs | 1 - .../Configuration/ConfigurationFluentValidationTests.cs | 2 -- .../Configuration/ConsulFileConfigurationPollerTests.cs | 1 - .../Configuration/FileConfigurationCreatorTests.cs | 3 --- .../Configuration/FileConfigurationProviderTests.cs | 4 +--- .../Configuration/FileConfigurationSetterTests.cs | 3 +-- .../Configuration/HeaderFindAndReplaceCreatorTests.cs | 1 - .../Configuration/UpstreamTemplatePatternCreatorTests.cs | 1 - .../Controllers/FileConfigurationControllerTests.cs | 1 - .../DependencyInjection/OcelotBuilderTests.cs | 2 -- .../DownstreamRouteFinder/DownstreamRouteFinderTests.cs | 3 --- .../UrlMatcher/UrlPathPlaceholderNameAndValueFinderTests.cs | 3 +-- .../Errors/ExceptionHandlerMiddlewareTests.cs | 2 -- .../Headers/HttpResponseHeaderReplacerTests.cs | 1 - test/Ocelot.UnitTests/Infrastructure/ScopesAuthoriserTests.cs | 3 +-- test/Ocelot.UnitTests/LoadBalancer/LoadBalancerHouseTests.cs | 1 - .../Middleware/SimpleJsonResponseAggregatorTests.cs | 1 - .../RateLimit/ClientRateLimitMiddlewareTests.cs | 1 - .../RequestId/ReRouteRequestIdMiddlewareTests.cs | 1 - .../Requester/DelegatingHandlerHandlerProviderFactoryTests.cs | 1 - test/Ocelot.UnitTests/Requester/QosProviderHouseTests.cs | 1 - .../Responder/ErrorsToHttpStatusCodeMapperTests.cs | 1 - test/Ocelot.UnitTests/Responder/ResponderMiddlewareTests.cs | 1 - 45 files changed, 6 insertions(+), 65 deletions(-) diff --git a/src/Ocelot/Cache/Middleware/OutputCacheMiddleware.cs b/src/Ocelot/Cache/Middleware/OutputCacheMiddleware.cs index 873c4cf7..3d128b72 100644 --- a/src/Ocelot/Cache/Middleware/OutputCacheMiddleware.cs +++ b/src/Ocelot/Cache/Middleware/OutputCacheMiddleware.cs @@ -123,7 +123,6 @@ namespace Ocelot.Cache.Middleware var contentHeaders = response?.Content?.Headers.ToDictionary(v => v.Key, v => v.Value); - var cached = new CachedResponse(statusCode, headers, body, contentHeaders); return cached; } diff --git a/src/Ocelot/Configuration/Builder/DownstreamReRouteBuilder.cs b/src/Ocelot/Configuration/Builder/DownstreamReRouteBuilder.cs index bc860424..ca98a823 100644 --- a/src/Ocelot/Configuration/Builder/DownstreamReRouteBuilder.cs +++ b/src/Ocelot/Configuration/Builder/DownstreamReRouteBuilder.cs @@ -216,7 +216,6 @@ namespace Ocelot.Configuration.Builder return this; } - public DownstreamReRoute Build() { return new DownstreamReRoute( diff --git a/src/Ocelot/Configuration/Creator/FileOcelotConfigurationCreator.cs b/src/Ocelot/Configuration/Creator/FileOcelotConfigurationCreator.cs index fbc58020..a35c7d54 100644 --- a/src/Ocelot/Configuration/Creator/FileOcelotConfigurationCreator.cs +++ b/src/Ocelot/Configuration/Creator/FileOcelotConfigurationCreator.cs @@ -35,7 +35,6 @@ namespace Ocelot.Configuration.Creator private readonly IHeaderFindAndReplaceCreator _headerFAndRCreator; private readonly IDownstreamAddressesCreator _downstreamAddressesCreator; - public FileOcelotConfigurationCreator( IOptions options, IConfigurationValidator configurationValidator, diff --git a/src/Ocelot/Configuration/Creator/UpstreamTemplatePatternCreator.cs b/src/Ocelot/Configuration/Creator/UpstreamTemplatePatternCreator.cs index 1700472a..833c61db 100644 --- a/src/Ocelot/Configuration/Creator/UpstreamTemplatePatternCreator.cs +++ b/src/Ocelot/Configuration/Creator/UpstreamTemplatePatternCreator.cs @@ -67,7 +67,6 @@ namespace Ocelot.Configuration.Creator return false; } - private bool IsPlaceHolder(string upstreamTemplate, int i) { return upstreamTemplate[i] == '{'; diff --git a/src/Ocelot/Configuration/QoSOptions.cs b/src/Ocelot/Configuration/QoSOptions.cs index 60e7cc03..651bd506 100644 --- a/src/Ocelot/Configuration/QoSOptions.cs +++ b/src/Ocelot/Configuration/QoSOptions.cs @@ -14,8 +14,7 @@ namespace Ocelot.Configuration DurationOfBreak = durationofBreak; TimeoutValue = timeoutValue; TimeoutStrategy = timeoutStrategy; - } - + } public int ExceptionsAllowedBeforeBreaking { get; private set; } diff --git a/src/Ocelot/DependencyInjection/OcelotBuilder.cs b/src/Ocelot/DependencyInjection/OcelotBuilder.cs index 6501b619..350eb566 100644 --- a/src/Ocelot/DependencyInjection/OcelotBuilder.cs +++ b/src/Ocelot/DependencyInjection/OcelotBuilder.cs @@ -264,8 +264,7 @@ namespace Ocelot.DependencyInjection var urlFinder = new BaseUrlFinder(_configurationRoot); var baseSchemeUrlAndPort = urlFinder.Find(); - JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear(); - + JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear(); _services.AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme) .AddIdentityServerAuthentication(o => diff --git a/src/Ocelot/DownstreamRouteFinder/Middleware/DownstreamRouteFinderMiddleware.cs b/src/Ocelot/DownstreamRouteFinder/Middleware/DownstreamRouteFinderMiddleware.cs index 4b467b95..e5348410 100644 --- a/src/Ocelot/DownstreamRouteFinder/Middleware/DownstreamRouteFinderMiddleware.cs +++ b/src/Ocelot/DownstreamRouteFinder/Middleware/DownstreamRouteFinderMiddleware.cs @@ -17,7 +17,6 @@ namespace Ocelot.DownstreamRouteFinder.Middleware private readonly IOcelotConfigurationProvider _configProvider; private readonly IMultiplexer _multiplexer; - public DownstreamRouteFinderMiddleware(OcelotRequestDelegate next, IOcelotLoggerFactory loggerFactory, IDownstreamRouteFinder downstreamRouteFinder, diff --git a/src/Ocelot/DownstreamUrlCreator/UrlBuilder.cs b/src/Ocelot/DownstreamUrlCreator/UrlBuilder.cs index 80f2507d..3a2f8d2e 100644 --- a/src/Ocelot/DownstreamUrlCreator/UrlBuilder.cs +++ b/src/Ocelot/DownstreamUrlCreator/UrlBuilder.cs @@ -25,7 +25,6 @@ namespace Ocelot.DownstreamUrlCreator return new ErrorResponse(new List { new DownstreamHostNullOrEmptyError() }); } - var builder = new UriBuilder { Host = downstreamHostAndPort.DownstreamHost, diff --git a/src/Ocelot/Infrastructure/Claims/Parser/ClaimsParser.cs b/src/Ocelot/Infrastructure/Claims/Parser/ClaimsParser.cs index b3a028b3..1af0acbc 100644 --- a/src/Ocelot/Infrastructure/Claims/Parser/ClaimsParser.cs +++ b/src/Ocelot/Infrastructure/Claims/Parser/ClaimsParser.cs @@ -37,7 +37,6 @@ return new OkResponse(value); } - public Response> GetValuesByClaimType(IEnumerable claims, string claimType) { List values = new List(); @@ -47,7 +46,6 @@ return new OkResponse>(values); } - private Response GetValue(IEnumerable claims, string key) { var claim = claims.FirstOrDefault(c => c.Type == key); diff --git a/src/Ocelot/LoadBalancer/LoadBalancers/RoundRobin.cs b/src/Ocelot/LoadBalancer/LoadBalancers/RoundRobin.cs index efc00e5e..26d55b1f 100644 --- a/src/Ocelot/LoadBalancer/LoadBalancers/RoundRobin.cs +++ b/src/Ocelot/LoadBalancer/LoadBalancers/RoundRobin.cs @@ -17,7 +17,6 @@ namespace Ocelot.LoadBalancer.LoadBalancers _services = services; } - public async Task> Lease() { var services = await _services.Invoke(); diff --git a/src/Ocelot/RateLimit/ClientRateLimitProcessor.cs b/src/Ocelot/RateLimit/ClientRateLimitProcessor.cs index 9a4a4ce3..65a04504 100644 --- a/src/Ocelot/RateLimit/ClientRateLimitProcessor.cs +++ b/src/Ocelot/RateLimit/ClientRateLimitProcessor.cs @@ -23,7 +23,6 @@ namespace Ocelot.RateLimit return _core.ProcessRequest(requestIdentity, option); } - public int RetryAfterFrom(DateTime timestamp, RateLimitRule rule) { return _core.RetryAfterFrom(timestamp, rule); diff --git a/src/Ocelot/RequestId/Middleware/ReRouteRequestIdMiddleware.cs b/src/Ocelot/RequestId/Middleware/ReRouteRequestIdMiddleware.cs index 0b146b27..32ee6c68 100644 --- a/src/Ocelot/RequestId/Middleware/ReRouteRequestIdMiddleware.cs +++ b/src/Ocelot/RequestId/Middleware/ReRouteRequestIdMiddleware.cs @@ -18,7 +18,6 @@ namespace Ocelot.RequestId.Middleware private readonly IOcelotLogger _logger; private readonly IRequestScopedDataRepository _requestScopedDataRepository; - public ReRouteRequestIdMiddleware(OcelotRequestDelegate next, IOcelotLoggerFactory loggerFactory, IRequestScopedDataRepository requestScopedDataRepository) diff --git a/test/Ocelot.AcceptanceTests/AggregateTests.cs b/test/Ocelot.AcceptanceTests/AggregateTests.cs index c0ed2de2..8510fd1b 100644 --- a/test/Ocelot.AcceptanceTests/AggregateTests.cs +++ b/test/Ocelot.AcceptanceTests/AggregateTests.cs @@ -229,7 +229,6 @@ namespace Ocelot.AcceptanceTests .BDDfy(); } - [Fact] public void should_be_thread_safe() { diff --git a/test/Ocelot.AcceptanceTests/ButterflyTracingTests.cs b/test/Ocelot.AcceptanceTests/ButterflyTracingTests.cs index 52a589c1..a7411ebe 100644 --- a/test/Ocelot.AcceptanceTests/ButterflyTracingTests.cs +++ b/test/Ocelot.AcceptanceTests/ButterflyTracingTests.cs @@ -104,7 +104,6 @@ namespace Ocelot.AcceptanceTests .And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Tom")) .BDDfy(); - var commandOnAllStateMachines = WaitFor(5000).Until(() => _butterflyCalled == 4); commandOnAllStateMachines.ShouldBeTrue(); diff --git a/test/Ocelot.AcceptanceTests/ClientRateLimitTests.cs b/test/Ocelot.AcceptanceTests/ClientRateLimitTests.cs index fb09591b..dc9d5eef 100644 --- a/test/Ocelot.AcceptanceTests/ClientRateLimitTests.cs +++ b/test/Ocelot.AcceptanceTests/ClientRateLimitTests.cs @@ -20,13 +20,11 @@ namespace Ocelot.AcceptanceTests private readonly Steps _steps; private int _counterOne; - public ClientRateLimitTests() { _steps = new Steps(); } - public void Dispose() { _builder?.Dispose(); @@ -92,7 +90,6 @@ namespace Ocelot.AcceptanceTests .BDDfy(); } - [Fact] public void should_call_middleware_withWhitelistClient() { @@ -147,7 +144,6 @@ namespace Ocelot.AcceptanceTests .BDDfy(); } - private void GivenThereIsAServiceRunningOn(string baseUrl, string basePath) { _builder = new WebHostBuilder() diff --git a/test/Ocelot.AcceptanceTests/ConfigurationInConsulTests.cs b/test/Ocelot.AcceptanceTests/ConfigurationInConsulTests.cs index db617718..c0dfe1ef 100644 --- a/test/Ocelot.AcceptanceTests/ConfigurationInConsulTests.cs +++ b/test/Ocelot.AcceptanceTests/ConfigurationInConsulTests.cs @@ -175,7 +175,6 @@ namespace Ocelot.AcceptanceTests .BDDfy(); } - [Fact] public void should_load_configuration_out_of_consul_if_it_is_changed() { diff --git a/test/Ocelot.AcceptanceTests/CustomMiddlewareTests.cs b/test/Ocelot.AcceptanceTests/CustomMiddlewareTests.cs index 2171f72d..0cf33d4b 100644 --- a/test/Ocelot.AcceptanceTests/CustomMiddlewareTests.cs +++ b/test/Ocelot.AcceptanceTests/CustomMiddlewareTests.cs @@ -286,7 +286,6 @@ namespace Ocelot.AcceptanceTests .And(x => x.ThenTheCounterIs(1)) .BDDfy(); } - [Fact(Skip = "This is just an example to show how you could hook into Ocelot pipeline with your own middleware. At the moment you must use Response.OnCompleted callback and cannot change the response :( I will see if this can be changed one day!")] public void should_fix_issue_237() diff --git a/test/Ocelot.AcceptanceTests/HeaderTests.cs b/test/Ocelot.AcceptanceTests/HeaderTests.cs index e0bd67c8..b5a2711e 100644 --- a/test/Ocelot.AcceptanceTests/HeaderTests.cs +++ b/test/Ocelot.AcceptanceTests/HeaderTests.cs @@ -186,7 +186,6 @@ namespace Ocelot.AcceptanceTests .BDDfy(); } - private void GivenThereIsAServiceRunningOn(string baseUrl, string basePath, int statusCode, string headerKey) { _builder = new WebHostBuilder() diff --git a/test/Ocelot.AcceptanceTests/RoutingTests.cs b/test/Ocelot.AcceptanceTests/RoutingTests.cs index ea748a04..0a16e565 100644 --- a/test/Ocelot.AcceptanceTests/RoutingTests.cs +++ b/test/Ocelot.AcceptanceTests/RoutingTests.cs @@ -543,7 +543,6 @@ namespace Ocelot.AcceptanceTests .BDDfy(); } - [Fact] public void should_return_response_200_with_complex_url_that_starts_with_placeholder() { @@ -578,7 +577,6 @@ namespace Ocelot.AcceptanceTests .BDDfy(); } - [Fact] public void should_not_add_trailing_slash_to_downstream_url() { @@ -834,7 +832,6 @@ namespace Ocelot.AcceptanceTests .BDDfy(); } - [Fact] public void should_fix_145() { diff --git a/test/Ocelot.AcceptanceTests/UpstreamHostTests.cs b/test/Ocelot.AcceptanceTests/UpstreamHostTests.cs index 16e123a7..a6a495a1 100644 --- a/test/Ocelot.AcceptanceTests/UpstreamHostTests.cs +++ b/test/Ocelot.AcceptanceTests/UpstreamHostTests.cs @@ -58,7 +58,6 @@ namespace Ocelot.AcceptanceTests .BDDfy(); } - [Fact] public void should_return_response_200_with_simple_url_and_hosts_match_multiple_re_routes() { diff --git a/test/Ocelot.IntegrationTests/AdministrationTests.cs b/test/Ocelot.IntegrationTests/AdministrationTests.cs index e9fc390d..763d642c 100644 --- a/test/Ocelot.IntegrationTests/AdministrationTests.cs +++ b/test/Ocelot.IntegrationTests/AdministrationTests.cs @@ -484,7 +484,6 @@ namespace Ocelot.IntegrationTests app.UseOcelot().Wait(); }); - _builderTwo = _webHostBuilderTwo.Build(); _builderTwo.Start(); diff --git a/test/Ocelot.UnitTests/Claims/AddClaimsToRequestTests.cs b/test/Ocelot.UnitTests/Claims/AddClaimsToRequestTests.cs index cdb5c4c7..33ff1e06 100644 --- a/test/Ocelot.UnitTests/Claims/AddClaimsToRequestTests.cs +++ b/test/Ocelot.UnitTests/Claims/AddClaimsToRequestTests.cs @@ -93,7 +93,6 @@ namespace Ocelot.UnitTests.Claims .BDDfy(); } - private void GivenClaimsToThings(List configuration) { _claimsToThings = configuration; diff --git a/test/Ocelot.UnitTests/Claims/ClaimsBuilderMiddlewareTests.cs b/test/Ocelot.UnitTests/Claims/ClaimsBuilderMiddlewareTests.cs index be266f9e..5b5e386c 100644 --- a/test/Ocelot.UnitTests/Claims/ClaimsBuilderMiddlewareTests.cs +++ b/test/Ocelot.UnitTests/Claims/ClaimsBuilderMiddlewareTests.cs @@ -68,7 +68,6 @@ namespace Ocelot.UnitTests.Claims _middleware.Invoke(_downstreamContext).GetAwaiter().GetResult(); } - private void GivenTheDownStreamRouteIs(DownstreamRoute downstreamRoute) { _downstreamContext.TemplatePlaceholderNameAndValues = downstreamRoute.TemplatePlaceholderNameAndValues; diff --git a/test/Ocelot.UnitTests/Configuration/ConfigurationFluentValidationTests.cs b/test/Ocelot.UnitTests/Configuration/ConfigurationFluentValidationTests.cs index 632461fc..b4dc45b0 100644 --- a/test/Ocelot.UnitTests/Configuration/ConfigurationFluentValidationTests.cs +++ b/test/Ocelot.UnitTests/Configuration/ConfigurationFluentValidationTests.cs @@ -869,7 +869,6 @@ namespace Ocelot.UnitTests.Configuration .BDDfy(); } - [Theory] [InlineData(null)] [InlineData("")] @@ -1008,7 +1007,6 @@ namespace Ocelot.UnitTests.Configuration .BDDfy(); } - private void GivenAConfiguration(FileConfiguration fileConfiguration) { _fileConfiguration = fileConfiguration; diff --git a/test/Ocelot.UnitTests/Configuration/ConsulFileConfigurationPollerTests.cs b/test/Ocelot.UnitTests/Configuration/ConsulFileConfigurationPollerTests.cs index 10c8a012..b743b598 100644 --- a/test/Ocelot.UnitTests/Configuration/ConsulFileConfigurationPollerTests.cs +++ b/test/Ocelot.UnitTests/Configuration/ConsulFileConfigurationPollerTests.cs @@ -12,7 +12,6 @@ using Xunit; using Shouldly; using static Ocelot.UnitTests.Wait; - namespace Ocelot.UnitTests.Configuration { public class ConsulFileConfigurationPollerTests : IDisposable diff --git a/test/Ocelot.UnitTests/Configuration/FileConfigurationCreatorTests.cs b/test/Ocelot.UnitTests/Configuration/FileConfigurationCreatorTests.cs index cb6615bf..4de07053 100644 --- a/test/Ocelot.UnitTests/Configuration/FileConfigurationCreatorTests.cs +++ b/test/Ocelot.UnitTests/Configuration/FileConfigurationCreatorTests.cs @@ -502,7 +502,6 @@ namespace Ocelot.UnitTests.Configuration .WithUseServiceDiscovery(false) .Build(); - this.Given(x => x.GivenTheConfigIs(new FileConfiguration { ReRoutes = new List @@ -545,7 +544,6 @@ namespace Ocelot.UnitTests.Configuration .WithUpstreamTemplatePattern(new UpstreamPathTemplate("(?i)/api/products/.*/$", 1)) .Build(); - this.Given(x => x.GivenTheConfigIs(new FileConfiguration { ReRoutes = new List @@ -915,7 +913,6 @@ namespace Ocelot.UnitTests.Configuration .Setup(x => x.Create(It.IsAny())).Returns(serviceProviderConfiguration); } - private void GivenTheFollowingRegionIsReturned(string region) { _regionCreator diff --git a/test/Ocelot.UnitTests/Configuration/FileConfigurationProviderTests.cs b/test/Ocelot.UnitTests/Configuration/FileConfigurationProviderTests.cs index be3df6cc..506da50c 100644 --- a/test/Ocelot.UnitTests/Configuration/FileConfigurationProviderTests.cs +++ b/test/Ocelot.UnitTests/Configuration/FileConfigurationProviderTests.cs @@ -38,8 +38,6 @@ namespace Ocelot.UnitTests.Configuration .BDDfy(); } - - private void GivenTheConfigurationIs(FileConfiguration fileConfiguration) { _fileConfiguration = fileConfiguration; @@ -59,4 +57,4 @@ namespace Ocelot.UnitTests.Configuration .Verify(x => x.Get(), Times.Once); } } -} \ No newline at end of file +} diff --git a/test/Ocelot.UnitTests/Configuration/FileConfigurationSetterTests.cs b/test/Ocelot.UnitTests/Configuration/FileConfigurationSetterTests.cs index 60365661..e16148f2 100644 --- a/test/Ocelot.UnitTests/Configuration/FileConfigurationSetterTests.cs +++ b/test/Ocelot.UnitTests/Configuration/FileConfigurationSetterTests.cs @@ -48,7 +48,6 @@ namespace Ocelot.UnitTests.Configuration .BDDfy(); } - [Fact] public void should_return_error_if_unable_to_set_file_configuration() { @@ -110,4 +109,4 @@ namespace Ocelot.UnitTests.Configuration .Verify(x => x.AddOrReplace(_configuration.Data), Times.Once); } } -} \ No newline at end of file +} diff --git a/test/Ocelot.UnitTests/Configuration/HeaderFindAndReplaceCreatorTests.cs b/test/Ocelot.UnitTests/Configuration/HeaderFindAndReplaceCreatorTests.cs index 3c817295..37ee8957 100644 --- a/test/Ocelot.UnitTests/Configuration/HeaderFindAndReplaceCreatorTests.cs +++ b/test/Ocelot.UnitTests/Configuration/HeaderFindAndReplaceCreatorTests.cs @@ -84,7 +84,6 @@ namespace Ocelot.UnitTests.Configuration .BDDfy(); } - [Fact] public void should_use_base_url_partial_placeholder() { diff --git a/test/Ocelot.UnitTests/Configuration/UpstreamTemplatePatternCreatorTests.cs b/test/Ocelot.UnitTests/Configuration/UpstreamTemplatePatternCreatorTests.cs index c8e79675..9dce0e50 100644 --- a/test/Ocelot.UnitTests/Configuration/UpstreamTemplatePatternCreatorTests.cs +++ b/test/Ocelot.UnitTests/Configuration/UpstreamTemplatePatternCreatorTests.cs @@ -35,7 +35,6 @@ namespace Ocelot.UnitTests.Configuration .BDDfy(); } - [Fact] public void should_match_forward_slash_or_no_forward_slash_if_template_end_with_forward_slash() { diff --git a/test/Ocelot.UnitTests/Controllers/FileConfigurationControllerTests.cs b/test/Ocelot.UnitTests/Controllers/FileConfigurationControllerTests.cs index 0d95f0ea..c0ae8b87 100644 --- a/test/Ocelot.UnitTests/Controllers/FileConfigurationControllerTests.cs +++ b/test/Ocelot.UnitTests/Controllers/FileConfigurationControllerTests.cs @@ -111,7 +111,6 @@ namespace Ocelot.UnitTests.Controllers .BDDfy(); } - private void ThenTheNodeIsCalledCorrectly() { _node.Verify(x => x.Accept(It.IsAny()), Times.Once); diff --git a/test/Ocelot.UnitTests/DependencyInjection/OcelotBuilderTests.cs b/test/Ocelot.UnitTests/DependencyInjection/OcelotBuilderTests.cs index e33ee812..8ed1a327 100644 --- a/test/Ocelot.UnitTests/DependencyInjection/OcelotBuilderTests.cs +++ b/test/Ocelot.UnitTests/DependencyInjection/OcelotBuilderTests.cs @@ -70,7 +70,6 @@ namespace Ocelot.UnitTests.DependencyInjection .BDDfy(); } - [Fact] public void should_set_up_cache_manager() { @@ -151,7 +150,6 @@ namespace Ocelot.UnitTests.DependencyInjection .BDDfy(); } - [Fact] public void should_set_up_without_passing_in_config() { diff --git a/test/Ocelot.UnitTests/DownstreamRouteFinder/DownstreamRouteFinderTests.cs b/test/Ocelot.UnitTests/DownstreamRouteFinder/DownstreamRouteFinderTests.cs index b7761c60..cb5c2a67 100644 --- a/test/Ocelot.UnitTests/DownstreamRouteFinder/DownstreamRouteFinderTests.cs +++ b/test/Ocelot.UnitTests/DownstreamRouteFinder/DownstreamRouteFinderTests.cs @@ -35,7 +35,6 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder _downstreamRouteFinder = new Ocelot.DownstreamRouteFinder.Finder.DownstreamRouteFinder(_mockMatcher.Object, _finder.Object); } - [Fact] public void should_return_highest_priority_when_first() { @@ -182,7 +181,6 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder .BDDfy(); } - [Fact] public void should_not_append_slash_to_upstream_url_path() { @@ -598,7 +596,6 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder .BDDfy(); } - [Fact] public void should_return_route_when_host_matches_but_null_host_on_same_path_first() { diff --git a/test/Ocelot.UnitTests/DownstreamRouteFinder/UrlMatcher/UrlPathPlaceholderNameAndValueFinderTests.cs b/test/Ocelot.UnitTests/DownstreamRouteFinder/UrlMatcher/UrlPathPlaceholderNameAndValueFinderTests.cs index afd1b3ae..29bc8fcd 100644 --- a/test/Ocelot.UnitTests/DownstreamRouteFinder/UrlMatcher/UrlPathPlaceholderNameAndValueFinderTests.cs +++ b/test/Ocelot.UnitTests/DownstreamRouteFinder/UrlMatcher/UrlPathPlaceholderNameAndValueFinderTests.cs @@ -30,7 +30,6 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder.UrlMatcher .BDDfy(); } - [Fact] public void can_match_down_stream_url_with_nothing_then_placeholder_no_value_is_blank() { @@ -264,4 +263,4 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder.UrlMatcher _result = _finder.Find(_downstreamUrlPath, _downstreamPathTemplate); } } -} \ No newline at end of file +} diff --git a/test/Ocelot.UnitTests/Errors/ExceptionHandlerMiddlewareTests.cs b/test/Ocelot.UnitTests/Errors/ExceptionHandlerMiddlewareTests.cs index e6c3e7ca..89eaaa38 100644 --- a/test/Ocelot.UnitTests/Errors/ExceptionHandlerMiddlewareTests.cs +++ b/test/Ocelot.UnitTests/Errors/ExceptionHandlerMiddlewareTests.cs @@ -29,7 +29,6 @@ namespace Ocelot.UnitTests.Errors private DownstreamContext _downstreamContext; private OcelotRequestDelegate _next; - public ExceptionHandlerMiddlewareTests() { _provider = new Mock(); @@ -174,7 +173,6 @@ namespace Ocelot.UnitTests.Errors .Setup(x => x.Get()).ReturnsAsync(response); } - private void GivenAnExceptionWillNotBeThrownDownstream() { _shouldThrowAnException = false; diff --git a/test/Ocelot.UnitTests/Headers/HttpResponseHeaderReplacerTests.cs b/test/Ocelot.UnitTests/Headers/HttpResponseHeaderReplacerTests.cs index 6b65bb67..95ae6e6d 100644 --- a/test/Ocelot.UnitTests/Headers/HttpResponseHeaderReplacerTests.cs +++ b/test/Ocelot.UnitTests/Headers/HttpResponseHeaderReplacerTests.cs @@ -98,7 +98,6 @@ namespace Ocelot.UnitTests.Headers .BDDfy(); } - [Fact] public void should_replace_downstream_base_url_with_ocelot_base_url_and_path() { diff --git a/test/Ocelot.UnitTests/Infrastructure/ScopesAuthoriserTests.cs b/test/Ocelot.UnitTests/Infrastructure/ScopesAuthoriserTests.cs index 1d476db3..08f6a46d 100644 --- a/test/Ocelot.UnitTests/Infrastructure/ScopesAuthoriserTests.cs +++ b/test/Ocelot.UnitTests/Infrastructure/ScopesAuthoriserTests.cs @@ -35,7 +35,6 @@ namespace Ocelot.UnitTests.Infrastructure .BDDfy(); } - [Fact] public void should_return_ok_if_null_allowed_scopes() { @@ -121,4 +120,4 @@ namespace Ocelot.UnitTests.Infrastructure { } } -} \ No newline at end of file +} diff --git a/test/Ocelot.UnitTests/LoadBalancer/LoadBalancerHouseTests.cs b/test/Ocelot.UnitTests/LoadBalancer/LoadBalancerHouseTests.cs index f5604ab1..2a4d3a24 100644 --- a/test/Ocelot.UnitTests/LoadBalancer/LoadBalancerHouseTests.cs +++ b/test/Ocelot.UnitTests/LoadBalancer/LoadBalancerHouseTests.cs @@ -116,7 +116,6 @@ namespace Ocelot.UnitTests.LoadBalancer _factory.Verify(x => x.Get(_reRoute, _serviceProviderConfig), Times.Once); } - private void GivenThereIsALoadBalancer(DownstreamReRoute reRoute, ILoadBalancer loadBalancer) { _reRoute = reRoute; diff --git a/test/Ocelot.UnitTests/Middleware/SimpleJsonResponseAggregatorTests.cs b/test/Ocelot.UnitTests/Middleware/SimpleJsonResponseAggregatorTests.cs index b5fabaee..27d1b7e0 100644 --- a/test/Ocelot.UnitTests/Middleware/SimpleJsonResponseAggregatorTests.cs +++ b/test/Ocelot.UnitTests/Middleware/SimpleJsonResponseAggregatorTests.cs @@ -42,7 +42,6 @@ namespace Ocelot.UnitTests.Middleware .WithDownstreamReRoutes(downstreamReRoutes) .Build(); - var billDownstreamContext = new DownstreamContext(new DefaultHttpContext()) { DownstreamResponse = diff --git a/test/Ocelot.UnitTests/RateLimit/ClientRateLimitMiddlewareTests.cs b/test/Ocelot.UnitTests/RateLimit/ClientRateLimitMiddlewareTests.cs index 168781bc..57d2fdc8 100644 --- a/test/Ocelot.UnitTests/RateLimit/ClientRateLimitMiddlewareTests.cs +++ b/test/Ocelot.UnitTests/RateLimit/ClientRateLimitMiddlewareTests.cs @@ -19,7 +19,6 @@ namespace Ocelot.UnitTests.RateLimit using Microsoft.Extensions.Caching.Memory; using System.IO; - public class ClientRateLimitMiddlewareTests { private int _responseStatusCode; diff --git a/test/Ocelot.UnitTests/RequestId/ReRouteRequestIdMiddlewareTests.cs b/test/Ocelot.UnitTests/RequestId/ReRouteRequestIdMiddlewareTests.cs index 40276547..c49f2c6a 100644 --- a/test/Ocelot.UnitTests/RequestId/ReRouteRequestIdMiddlewareTests.cs +++ b/test/Ocelot.UnitTests/RequestId/ReRouteRequestIdMiddlewareTests.cs @@ -165,7 +165,6 @@ namespace Ocelot.UnitTests.RequestId _repo.Verify(x => x.Update("RequestId", _value), Times.Once); } - private void GivenTheDownStreamRouteIs(DownstreamRoute downstreamRoute) { _downstreamContext.TemplatePlaceholderNameAndValues = downstreamRoute.TemplatePlaceholderNameAndValues; diff --git a/test/Ocelot.UnitTests/Requester/DelegatingHandlerHandlerProviderFactoryTests.cs b/test/Ocelot.UnitTests/Requester/DelegatingHandlerHandlerProviderFactoryTests.cs index e6942681..c63e04d2 100644 --- a/test/Ocelot.UnitTests/Requester/DelegatingHandlerHandlerProviderFactoryTests.cs +++ b/test/Ocelot.UnitTests/Requester/DelegatingHandlerHandlerProviderFactoryTests.cs @@ -41,7 +41,6 @@ namespace Ocelot.UnitTests.Requester .Returns(qosProvider); } - [Fact] public void should_all_from_all_routes_provider_and_qos() { diff --git a/test/Ocelot.UnitTests/Requester/QosProviderHouseTests.cs b/test/Ocelot.UnitTests/Requester/QosProviderHouseTests.cs index 487a3509..f6095034 100644 --- a/test/Ocelot.UnitTests/Requester/QosProviderHouseTests.cs +++ b/test/Ocelot.UnitTests/Requester/QosProviderHouseTests.cs @@ -111,7 +111,6 @@ namespace Ocelot.UnitTests.Requester _getResult.Data.ShouldBe(_qoSProvider); } - private void GivenThereIsAQoSProvider(DownstreamReRoute reRoute, IQoSProvider qoSProvider) { _reRoute = reRoute; diff --git a/test/Ocelot.UnitTests/Responder/ErrorsToHttpStatusCodeMapperTests.cs b/test/Ocelot.UnitTests/Responder/ErrorsToHttpStatusCodeMapperTests.cs index 9922df6a..977a0b12 100644 --- a/test/Ocelot.UnitTests/Responder/ErrorsToHttpStatusCodeMapperTests.cs +++ b/test/Ocelot.UnitTests/Responder/ErrorsToHttpStatusCodeMapperTests.cs @@ -45,7 +45,6 @@ namespace Ocelot.UnitTests.Responder ShouldMapErrorToStatusCode(OcelotErrorCode.RequestTimedOutError, HttpStatusCode.ServiceUnavailable); } - [Theory] [InlineData(OcelotErrorCode.CannotAddDataError)] [InlineData(OcelotErrorCode.CannotFindDataError)] diff --git a/test/Ocelot.UnitTests/Responder/ResponderMiddlewareTests.cs b/test/Ocelot.UnitTests/Responder/ResponderMiddlewareTests.cs index fb0720b4..28a0707a 100644 --- a/test/Ocelot.UnitTests/Responder/ResponderMiddlewareTests.cs +++ b/test/Ocelot.UnitTests/Responder/ResponderMiddlewareTests.cs @@ -27,7 +27,6 @@ namespace Ocelot.UnitTests.Responder private readonly DownstreamContext _downstreamContext; private OcelotRequestDelegate _next; - public ResponderMiddlewareTests() { _responder = new Mock(); From f24c0a05107ba73040ecaf496db9235956bb0923 Mon Sep 17 00:00:00 2001 From: Philip Wood Date: Sat, 3 Mar 2018 13:29:05 +0000 Subject: [PATCH 16/26] Fix multiple statements on single line SA1107 --- src/Ocelot/Raft/OcelotFiniteStateMachine.cs | 4 ++-- src/Ocelot/Requester/OcelotHttpTracingHandler.cs | 2 +- test/Ocelot.AcceptanceTests/CustomMiddlewareTests.cs | 4 ++-- .../Configuration/ConfigurationFluentValidationTests.cs | 3 ++- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/Ocelot/Raft/OcelotFiniteStateMachine.cs b/src/Ocelot/Raft/OcelotFiniteStateMachine.cs index f63695f2..feecd7d7 100644 --- a/src/Ocelot/Raft/OcelotFiniteStateMachine.cs +++ b/src/Ocelot/Raft/OcelotFiniteStateMachine.cs @@ -19,7 +19,7 @@ namespace Ocelot.Raft //todo - handle an error //hack it to just cast as at the moment we know this is the only command :P var hack = (UpdateFileConfiguration)log.CommandData; - _setter.Set(hack.Configuration).GetAwaiter().GetResult();; + _setter.Set(hack.Configuration).GetAwaiter().GetResult(); } } -} \ No newline at end of file +} diff --git a/src/Ocelot/Requester/OcelotHttpTracingHandler.cs b/src/Ocelot/Requester/OcelotHttpTracingHandler.cs index fbd24fbf..0eb22462 100644 --- a/src/Ocelot/Requester/OcelotHttpTracingHandler.cs +++ b/src/Ocelot/Requester/OcelotHttpTracingHandler.cs @@ -51,7 +51,7 @@ namespace Ocelot.Requester if (!c.Contains(k)) { c.Add(k, v); - }; + } }); span.Log(LogField.CreateNew().ClientSend()); diff --git a/test/Ocelot.AcceptanceTests/CustomMiddlewareTests.cs b/test/Ocelot.AcceptanceTests/CustomMiddlewareTests.cs index 0cf33d4b..341986fe 100644 --- a/test/Ocelot.AcceptanceTests/CustomMiddlewareTests.cs +++ b/test/Ocelot.AcceptanceTests/CustomMiddlewareTests.cs @@ -25,7 +25,7 @@ namespace Ocelot.AcceptanceTests public CustomMiddlewareTests() { _counter = 0; - _steps = new Steps();; + _steps = new Steps(); _configurationPath = "configuration.json"; } @@ -357,7 +357,7 @@ namespace Ocelot.AcceptanceTests } else if(context.Request.Path.Value != basePath) { - context.Response.StatusCode = 404;; + context.Response.StatusCode = 404; } return Task.CompletedTask; diff --git a/test/Ocelot.UnitTests/Configuration/ConfigurationFluentValidationTests.cs b/test/Ocelot.UnitTests/Configuration/ConfigurationFluentValidationTests.cs index b4dc45b0..70f115c1 100644 --- a/test/Ocelot.UnitTests/Configuration/ConfigurationFluentValidationTests.cs +++ b/test/Ocelot.UnitTests/Configuration/ConfigurationFluentValidationTests.cs @@ -588,7 +588,8 @@ namespace Ocelot.UnitTests.Configuration AuthenticationOptions = new FileAuthenticationOptions() { AuthenticationProviderKey = "Test" - } } + } + } } })) .When(x => x.WhenIValidateTheConfiguration()) From b18c8e5f2b0951a10608e476f614117fcae497e7 Mon Sep 17 00:00:00 2001 From: Philip Wood Date: Sat, 3 Mar 2018 13:34:19 +0000 Subject: [PATCH 17/26] Fix single-line comment spacing SA1512, SA1515 --- src/Ocelot/Configuration/File/FileConfiguration.cs | 1 + src/Ocelot/Configuration/File/FileRateLimitRule.cs | 1 + src/Ocelot/Configuration/RateLimitRule.cs | 3 ++- .../Middleware/DownstreamRouteFinderMiddleware.cs | 4 ++-- src/Ocelot/Middleware/DownstreamContext.cs | 2 -- src/Ocelot/Middleware/OcelotMiddlewareExtensions.cs | 8 +++++--- src/Ocelot/Raft/FilePeersProvider.cs | 2 ++ src/Ocelot/Raft/SqlLiteLog.cs | 6 ++++++ .../RateLimit/Middleware/ClientRateLimitMiddleware.cs | 2 ++ src/Ocelot/RateLimit/RateLimitCore.cs | 2 ++ .../Infrastructure/HttpDataRepositoryTests.cs | 6 ++++-- 11 files changed, 27 insertions(+), 10 deletions(-) diff --git a/src/Ocelot/Configuration/File/FileConfiguration.cs b/src/Ocelot/Configuration/File/FileConfiguration.cs index 6d73ce3f..e38ae6cb 100644 --- a/src/Ocelot/Configuration/File/FileConfiguration.cs +++ b/src/Ocelot/Configuration/File/FileConfiguration.cs @@ -12,6 +12,7 @@ namespace Ocelot.Configuration.File } public List ReRoutes { get; set; } + // Seperate field for aggregates because this let's you re-use ReRoutes in multiple Aggregates public List Aggregates { get;set; } public FileGlobalConfiguration GlobalConfiguration { get; set; } diff --git a/src/Ocelot/Configuration/File/FileRateLimitRule.cs b/src/Ocelot/Configuration/File/FileRateLimitRule.cs index 2dda3084..5e1616e6 100644 --- a/src/Ocelot/Configuration/File/FileRateLimitRule.cs +++ b/src/Ocelot/Configuration/File/FileRateLimitRule.cs @@ -26,6 +26,7 @@ namespace Ocelot.Configuration.File public string Period { get; set; } public double PeriodTimespan { get; set; } + /// /// Maximum number of requests that a client can make in a defined period /// diff --git a/src/Ocelot/Configuration/RateLimitRule.cs b/src/Ocelot/Configuration/RateLimitRule.cs index d77919ae..9240087c 100644 --- a/src/Ocelot/Configuration/RateLimitRule.cs +++ b/src/Ocelot/Configuration/RateLimitRule.cs @@ -17,9 +17,10 @@ namespace Ocelot.Configuration public string Period { get; private set; } public double PeriodTimespan { get; private set; } + /// /// Maximum number of requests that a client can make in a defined period /// public long Limit { get; private set; } } -} \ No newline at end of file +} diff --git a/src/Ocelot/DownstreamRouteFinder/Middleware/DownstreamRouteFinderMiddleware.cs b/src/Ocelot/DownstreamRouteFinder/Middleware/DownstreamRouteFinderMiddleware.cs index e5348410..c9da50a4 100644 --- a/src/Ocelot/DownstreamRouteFinder/Middleware/DownstreamRouteFinderMiddleware.cs +++ b/src/Ocelot/DownstreamRouteFinder/Middleware/DownstreamRouteFinderMiddleware.cs @@ -59,8 +59,8 @@ namespace Ocelot.DownstreamRouteFinder.Middleware return; } - //todo - put this back in - // _logger.LogDebug("downstream template is {downstreamRoute.Data.ReRoute.DownstreamPath}", downstreamRoute.Data.ReRoute.DownstreamReRoute.DownstreamPathTemplate); + // todo - put this back in + //// _logger.LogDebug("downstream template is {downstreamRoute.Data.ReRoute.DownstreamPath}", downstreamRoute.Data.ReRoute.DownstreamReRoute.DownstreamPathTemplate); context.TemplatePlaceholderNameAndValues = downstreamRoute.Data.TemplatePlaceholderNameAndValues; diff --git a/src/Ocelot/Middleware/DownstreamContext.cs b/src/Ocelot/Middleware/DownstreamContext.cs index 84ebc77a..1c805deb 100644 --- a/src/Ocelot/Middleware/DownstreamContext.cs +++ b/src/Ocelot/Middleware/DownstreamContext.cs @@ -22,8 +22,6 @@ namespace Ocelot.Middleware public HttpRequestMessage DownstreamRequest { get; set; } public HttpResponseMessage DownstreamResponse { get; set; } public List Errors { get;set; } - //public string RequestId {get;set;} - //public string PreviousRequestId {get;set;} public bool IsError => Errors.Count > 0; } } diff --git a/src/Ocelot/Middleware/OcelotMiddlewareExtensions.cs b/src/Ocelot/Middleware/OcelotMiddlewareExtensions.cs index 541a8e93..cda82bef 100644 --- a/src/Ocelot/Middleware/OcelotMiddlewareExtensions.cs +++ b/src/Ocelot/Middleware/OcelotMiddlewareExtensions.cs @@ -59,9 +59,11 @@ var firstDelegate = pipelineBuilder.Build(); - //inject first delegate into first piece of asp.net middleware..maybe not like this - //then because we are updating the http context in ocelot it comes out correct for - //rest of asp.net.. + /* + inject first delegate into first piece of asp.net middleware..maybe not like this + then because we are updating the http context in ocelot it comes out correct for + rest of asp.net.. + */ builder.Use(async (context, task) => { diff --git a/src/Ocelot/Raft/FilePeersProvider.cs b/src/Ocelot/Raft/FilePeersProvider.cs index 1eddf5e3..d31dc2ca 100644 --- a/src/Ocelot/Raft/FilePeersProvider.cs +++ b/src/Ocelot/Raft/FilePeersProvider.cs @@ -27,11 +27,13 @@ namespace Ocelot.Raft _finder = finder; _options = options; _peers = new List(); + //todo - sort out async nonsense.. var config = _provider.Get().GetAwaiter().GetResult(); foreach (var item in _options.Value.Peers) { var httpClient = new HttpClient(); + //todo what if this errors? var httpPeer = new HttpPeer(item.HostAndPort, httpClient, _finder, config.Data, _identityServerConfig); _peers.Add(httpPeer); diff --git a/src/Ocelot/Raft/SqlLiteLog.cs b/src/Ocelot/Raft/SqlLiteLog.cs index 9ca32af4..aff04bf5 100644 --- a/src/Ocelot/Raft/SqlLiteLog.cs +++ b/src/Ocelot/Raft/SqlLiteLog.cs @@ -133,6 +133,7 @@ namespace Ocelot.Raft TypeNameHandling = TypeNameHandling.All }; var data = JsonConvert.SerializeObject(log, jsonSerializerSettings); + //todo - sql injection dont copy this.. var sql = $"insert into logs (data) values ('{data}')"; using(var command = new SqliteCommand(sql, connection)) @@ -157,6 +158,7 @@ namespace Ocelot.Raft using(var connection = new SqliteConnection($"Data Source={_path};")) { connection.Open(); + //todo - sql injection dont copy this.. var sql = $"select data from logs where id = {index};"; using(var command = new SqliteCommand(sql, connection)) @@ -187,6 +189,7 @@ namespace Ocelot.Raft using(var connection = new SqliteConnection($"Data Source={_path};")) { connection.Open(); + //todo - sql injection dont copy this.. var sql = $"select data from logs where id = {index}"; using(var command = new SqliteCommand(sql, connection)) @@ -211,6 +214,7 @@ namespace Ocelot.Raft using(var connection = new SqliteConnection($"Data Source={_path};")) { connection.Open(); + //todo - sql injection dont copy this.. var sql = $"select id, data from logs where id >= {index}"; using(var command = new SqliteCommand(sql, connection)) @@ -243,6 +247,7 @@ namespace Ocelot.Raft using(var connection = new SqliteConnection($"Data Source={_path};")) { connection.Open(); + //todo - sql injection dont copy this.. var sql = $"select data from logs where id = {index}"; using(var command = new SqliteCommand(sql, connection)) @@ -270,6 +275,7 @@ namespace Ocelot.Raft using(var connection = new SqliteConnection($"Data Source={_path};")) { connection.Open(); + //todo - sql injection dont copy this.. var deleteSql = $"delete from logs where id >= {indexOfCommand};"; using(var deleteCommand = new SqliteCommand(deleteSql, connection)) diff --git a/src/Ocelot/RateLimit/Middleware/ClientRateLimitMiddleware.cs b/src/Ocelot/RateLimit/Middleware/ClientRateLimitMiddleware.cs index 2061decc..4ceb91f8 100644 --- a/src/Ocelot/RateLimit/Middleware/ClientRateLimitMiddleware.cs +++ b/src/Ocelot/RateLimit/Middleware/ClientRateLimitMiddleware.cs @@ -31,6 +31,7 @@ namespace Ocelot.RateLimit.Middleware public async Task Invoke(DownstreamContext context) { var options = context.DownstreamReRoute.RateLimitOptions; + // check if rate limiting is enabled if (!context.DownstreamReRoute.EnableEndpointEndpointRateLimiting) { @@ -66,6 +67,7 @@ namespace Ocelot.RateLimit.Middleware LogBlockedRequest(context.HttpContext, identity, counter, rule, context.DownstreamReRoute); var retrystring = retryAfter.ToString(System.Globalization.CultureInfo.InvariantCulture); + // break execution await ReturnQuotaExceededResponse(context.HttpContext, options, retrystring); diff --git a/src/Ocelot/RateLimit/RateLimitCore.cs b/src/Ocelot/RateLimit/RateLimitCore.cs index cc027dfb..82124c85 100644 --- a/src/Ocelot/RateLimit/RateLimitCore.cs +++ b/src/Ocelot/RateLimit/RateLimitCore.cs @@ -38,6 +38,7 @@ namespace Ocelot.RateLimit { // increment request count var totalRequests = entry.Value.TotalRequests + 1; + // deep copy counter = new RateLimitCounter(entry.Value.Timestamp, totalRequests); } @@ -70,6 +71,7 @@ namespace Ocelot.RateLimit { var counterId = ComputeCounterKey(requestIdentity, option); var rule = option.RateLimitRule; + // stores: id (string) - timestamp (datetime) - total_requests (long) _counterHandler.Set(counterId, counter, expirationTime); } diff --git a/test/Ocelot.UnitTests/Infrastructure/HttpDataRepositoryTests.cs b/test/Ocelot.UnitTests/Infrastructure/HttpDataRepositoryTests.cs index 407e9f47..c9f66009 100644 --- a/test/Ocelot.UnitTests/Infrastructure/HttpDataRepositoryTests.cs +++ b/test/Ocelot.UnitTests/Infrastructure/HttpDataRepositoryTests.cs @@ -21,8 +21,10 @@ namespace Ocelot.UnitTests.Infrastructure _httpDataRepository = new HttpDataRepository(_httpContextAccessor); } - //TODO - Additional tests -> Type mistmatch aka Add string, request int - //TODO - Additional tests -> HttpContent null. This should never happen + /* + TODO - Additional tests -> Type mistmatch aka Add string, request int + TODO - Additional tests -> HttpContent null. This should never happen + */ [Fact] public void get_returns_correct_key_from_http_context() From c7dbfc044fde93d30b7813e53d5811a15f438caa Mon Sep 17 00:00:00 2001 From: Philip Wood Date: Sat, 3 Mar 2018 13:36:09 +0000 Subject: [PATCH 18/26] Fix else statement spacing SA1510 --- test/Ocelot.AcceptanceTests/ConfigurationInConsulTests.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/Ocelot.AcceptanceTests/ConfigurationInConsulTests.cs b/test/Ocelot.AcceptanceTests/ConfigurationInConsulTests.cs index c0dfe1ef..7c9ac239 100644 --- a/test/Ocelot.AcceptanceTests/ConfigurationInConsulTests.cs +++ b/test/Ocelot.AcceptanceTests/ConfigurationInConsulTests.cs @@ -306,8 +306,7 @@ namespace Ocelot.AcceptanceTests var kvp = new FakeConsulGetResponse(base64); await context.Response.WriteJsonAsync(new FakeConsulGetResponse[] { kvp }); - } - + } else if (context.Request.Method.ToLower() == "put" && context.Request.Path.Value == "/v1/kv/OcelotConfiguration") { try From a64e263a266be32cf1287653b1a690edaa728b03 Mon Sep 17 00:00:00 2001 From: Philip Wood Date: Sat, 3 Mar 2018 13:48:30 +0000 Subject: [PATCH 19/26] Fix file names to match class names SA1649 --- ...ion.cs => ServiceProviderConfiguration.cs} | 26 +++++----- ...r.cs => IPlaceholderNameAndValueFinder.cs} | 20 ++++---- ...AndValue.cs => PlaceholderNameAndValue.cs} | 28 +++++------ ...nstreamTemplatePathPlaceholderReplacer.cs} | 48 +++++++++---------- ... => IDownstreamPathPlaceholderReplacer.cs} | 22 ++++----- ...age.cs => ExcludeFromCoverageAttribute.cs} | 12 ++--- src/Ocelot/Requester/ITracingHandler.cs | 6 +++ .../Requester/OcelotHttpTracingHandler.cs | 4 -- src/Ocelot/Responses/ErrorResponseGeneric.cs | 2 + src/Ocelot/Responses/OkResponseGeneric.cs | 4 +- src/Ocelot/Responses/ResponseGeneric.cs | 2 + test/Ocelot.UnitTests/Wait.cs | 10 ++++ test/Ocelot.UnitTests/Waiter.cs | 10 +--- 13 files changed, 102 insertions(+), 92 deletions(-) rename src/Ocelot/Configuration/{ServiceProviderConfiguraion.cs => ServiceProviderConfiguration.cs} (97%) rename src/Ocelot/DownstreamRouteFinder/UrlMatcher/{IUrlPathPlaceholderNameAndValueFinder.cs => IPlaceholderNameAndValueFinder.cs} (96%) rename src/Ocelot/DownstreamRouteFinder/UrlMatcher/{UrlPathPlaceholderNameAndValue.cs => PlaceholderNameAndValue.cs} (96%) rename src/Ocelot/DownstreamUrlCreator/UrlTemplateReplacer/{DownstreamUrlTemplateVariableReplacer.cs => DownstreamTemplatePathPlaceholderReplacer.cs} (97%) rename src/Ocelot/DownstreamUrlCreator/UrlTemplateReplacer/{IDownstreamUrlPathTemplateVariableReplacer.cs => IDownstreamPathPlaceholderReplacer.cs} (97%) rename src/Ocelot/Raft/{ExcludeFromCoverage.cs => ExcludeFromCoverageAttribute.cs} (97%) create mode 100644 src/Ocelot/Requester/ITracingHandler.cs create mode 100644 test/Ocelot.UnitTests/Wait.cs diff --git a/src/Ocelot/Configuration/ServiceProviderConfiguraion.cs b/src/Ocelot/Configuration/ServiceProviderConfiguration.cs similarity index 97% rename from src/Ocelot/Configuration/ServiceProviderConfiguraion.cs rename to src/Ocelot/Configuration/ServiceProviderConfiguration.cs index 272d2205..d5ddea6a 100644 --- a/src/Ocelot/Configuration/ServiceProviderConfiguraion.cs +++ b/src/Ocelot/Configuration/ServiceProviderConfiguration.cs @@ -1,14 +1,14 @@ -namespace Ocelot.Configuration -{ - public class ServiceProviderConfiguration - { - public ServiceProviderConfiguration(string serviceProviderHost, int serviceProviderPort) - { - ServiceProviderHost = serviceProviderHost; - ServiceProviderPort = serviceProviderPort; - } - - public string ServiceProviderHost { get; private set; } - public int ServiceProviderPort { get; private set; } - } +namespace Ocelot.Configuration +{ + public class ServiceProviderConfiguration + { + public ServiceProviderConfiguration(string serviceProviderHost, int serviceProviderPort) + { + ServiceProviderHost = serviceProviderHost; + ServiceProviderPort = serviceProviderPort; + } + + public string ServiceProviderHost { get; private set; } + public int ServiceProviderPort { get; private set; } + } } \ No newline at end of file diff --git a/src/Ocelot/DownstreamRouteFinder/UrlMatcher/IUrlPathPlaceholderNameAndValueFinder.cs b/src/Ocelot/DownstreamRouteFinder/UrlMatcher/IPlaceholderNameAndValueFinder.cs similarity index 96% rename from src/Ocelot/DownstreamRouteFinder/UrlMatcher/IUrlPathPlaceholderNameAndValueFinder.cs rename to src/Ocelot/DownstreamRouteFinder/UrlMatcher/IPlaceholderNameAndValueFinder.cs index d2cb4167..678b1081 100644 --- a/src/Ocelot/DownstreamRouteFinder/UrlMatcher/IUrlPathPlaceholderNameAndValueFinder.cs +++ b/src/Ocelot/DownstreamRouteFinder/UrlMatcher/IPlaceholderNameAndValueFinder.cs @@ -1,10 +1,10 @@ -using System.Collections.Generic; -using Ocelot.Responses; - -namespace Ocelot.DownstreamRouteFinder.UrlMatcher -{ - public interface IPlaceholderNameAndValueFinder - { - Response> Find(string path, string pathTemplate); - } -} +using System.Collections.Generic; +using Ocelot.Responses; + +namespace Ocelot.DownstreamRouteFinder.UrlMatcher +{ + public interface IPlaceholderNameAndValueFinder + { + Response> Find(string path, string pathTemplate); + } +} diff --git a/src/Ocelot/DownstreamRouteFinder/UrlMatcher/UrlPathPlaceholderNameAndValue.cs b/src/Ocelot/DownstreamRouteFinder/UrlMatcher/PlaceholderNameAndValue.cs similarity index 96% rename from src/Ocelot/DownstreamRouteFinder/UrlMatcher/UrlPathPlaceholderNameAndValue.cs rename to src/Ocelot/DownstreamRouteFinder/UrlMatcher/PlaceholderNameAndValue.cs index f91faa1d..90099d58 100644 --- a/src/Ocelot/DownstreamRouteFinder/UrlMatcher/UrlPathPlaceholderNameAndValue.cs +++ b/src/Ocelot/DownstreamRouteFinder/UrlMatcher/PlaceholderNameAndValue.cs @@ -1,14 +1,14 @@ -namespace Ocelot.DownstreamRouteFinder.UrlMatcher -{ - public class PlaceholderNameAndValue - { - public PlaceholderNameAndValue(string name, string value) - { - Name = name; - Value = value; - } - - public string Name {get;private set;} - public string Value {get;private set;} - } -} +namespace Ocelot.DownstreamRouteFinder.UrlMatcher +{ + public class PlaceholderNameAndValue + { + public PlaceholderNameAndValue(string name, string value) + { + Name = name; + Value = value; + } + + public string Name {get;private set;} + public string Value {get;private set;} + } +} diff --git a/src/Ocelot/DownstreamUrlCreator/UrlTemplateReplacer/DownstreamUrlTemplateVariableReplacer.cs b/src/Ocelot/DownstreamUrlCreator/UrlTemplateReplacer/DownstreamTemplatePathPlaceholderReplacer.cs similarity index 97% rename from src/Ocelot/DownstreamUrlCreator/UrlTemplateReplacer/DownstreamUrlTemplateVariableReplacer.cs rename to src/Ocelot/DownstreamUrlCreator/UrlTemplateReplacer/DownstreamTemplatePathPlaceholderReplacer.cs index dfd70eed..1b744819 100644 --- a/src/Ocelot/DownstreamUrlCreator/UrlTemplateReplacer/DownstreamUrlTemplateVariableReplacer.cs +++ b/src/Ocelot/DownstreamUrlCreator/UrlTemplateReplacer/DownstreamTemplatePathPlaceholderReplacer.cs @@ -1,25 +1,25 @@ -using System.Collections.Generic; -using System.Text; -using Ocelot.DownstreamRouteFinder.UrlMatcher; -using Ocelot.Responses; -using Ocelot.Values; - -namespace Ocelot.DownstreamUrlCreator.UrlTemplateReplacer -{ - public class DownstreamTemplatePathPlaceholderReplacer : IDownstreamPathPlaceholderReplacer - { - public Response Replace(PathTemplate downstreamPathTemplate, List urlPathPlaceholderNameAndValues) - { - var downstreamPath = new StringBuilder(); - - downstreamPath.Append(downstreamPathTemplate.Value); - - foreach (var placeholderVariableAndValue in urlPathPlaceholderNameAndValues) - { - downstreamPath.Replace(placeholderVariableAndValue.Name, placeholderVariableAndValue.Value); - } - - return new OkResponse(new DownstreamPath(downstreamPath.ToString())); - } - } +using System.Collections.Generic; +using System.Text; +using Ocelot.DownstreamRouteFinder.UrlMatcher; +using Ocelot.Responses; +using Ocelot.Values; + +namespace Ocelot.DownstreamUrlCreator.UrlTemplateReplacer +{ + public class DownstreamTemplatePathPlaceholderReplacer : IDownstreamPathPlaceholderReplacer + { + public Response Replace(PathTemplate downstreamPathTemplate, List urlPathPlaceholderNameAndValues) + { + var downstreamPath = new StringBuilder(); + + downstreamPath.Append(downstreamPathTemplate.Value); + + foreach (var placeholderVariableAndValue in urlPathPlaceholderNameAndValues) + { + downstreamPath.Replace(placeholderVariableAndValue.Name, placeholderVariableAndValue.Value); + } + + return new OkResponse(new DownstreamPath(downstreamPath.ToString())); + } + } } \ No newline at end of file diff --git a/src/Ocelot/DownstreamUrlCreator/UrlTemplateReplacer/IDownstreamUrlPathTemplateVariableReplacer.cs b/src/Ocelot/DownstreamUrlCreator/UrlTemplateReplacer/IDownstreamPathPlaceholderReplacer.cs similarity index 97% rename from src/Ocelot/DownstreamUrlCreator/UrlTemplateReplacer/IDownstreamUrlPathTemplateVariableReplacer.cs rename to src/Ocelot/DownstreamUrlCreator/UrlTemplateReplacer/IDownstreamPathPlaceholderReplacer.cs index 9e12b580..46e998d4 100644 --- a/src/Ocelot/DownstreamUrlCreator/UrlTemplateReplacer/IDownstreamUrlPathTemplateVariableReplacer.cs +++ b/src/Ocelot/DownstreamUrlCreator/UrlTemplateReplacer/IDownstreamPathPlaceholderReplacer.cs @@ -1,12 +1,12 @@ -using System.Collections.Generic; -using Ocelot.DownstreamRouteFinder.UrlMatcher; -using Ocelot.Responses; -using Ocelot.Values; - -namespace Ocelot.DownstreamUrlCreator.UrlTemplateReplacer -{ - public interface IDownstreamPathPlaceholderReplacer - { - Response Replace(PathTemplate downstreamPathTemplate, List urlPathPlaceholderNameAndValues); - } +using System.Collections.Generic; +using Ocelot.DownstreamRouteFinder.UrlMatcher; +using Ocelot.Responses; +using Ocelot.Values; + +namespace Ocelot.DownstreamUrlCreator.UrlTemplateReplacer +{ + public interface IDownstreamPathPlaceholderReplacer + { + Response Replace(PathTemplate downstreamPathTemplate, List urlPathPlaceholderNameAndValues); + } } \ No newline at end of file diff --git a/src/Ocelot/Raft/ExcludeFromCoverage.cs b/src/Ocelot/Raft/ExcludeFromCoverageAttribute.cs similarity index 97% rename from src/Ocelot/Raft/ExcludeFromCoverage.cs rename to src/Ocelot/Raft/ExcludeFromCoverageAttribute.cs index 70d42167..9ea5544a 100644 --- a/src/Ocelot/Raft/ExcludeFromCoverage.cs +++ b/src/Ocelot/Raft/ExcludeFromCoverageAttribute.cs @@ -1,7 +1,7 @@ -using System; - -namespace Ocelot.Raft -{ - [AttributeUsage(AttributeTargets.Class|AttributeTargets.Method|AttributeTargets.Property)] - public class ExcludeFromCoverageAttribute : Attribute{} +using System; + +namespace Ocelot.Raft +{ + [AttributeUsage(AttributeTargets.Class|AttributeTargets.Method|AttributeTargets.Property)] + public class ExcludeFromCoverageAttribute : Attribute{} } \ No newline at end of file diff --git a/src/Ocelot/Requester/ITracingHandler.cs b/src/Ocelot/Requester/ITracingHandler.cs new file mode 100644 index 00000000..87593303 --- /dev/null +++ b/src/Ocelot/Requester/ITracingHandler.cs @@ -0,0 +1,6 @@ +namespace Ocelot.Requester +{ + public interface ITracingHandler + { + } +} diff --git a/src/Ocelot/Requester/OcelotHttpTracingHandler.cs b/src/Ocelot/Requester/OcelotHttpTracingHandler.cs index 0eb22462..33bd4caf 100644 --- a/src/Ocelot/Requester/OcelotHttpTracingHandler.cs +++ b/src/Ocelot/Requester/OcelotHttpTracingHandler.cs @@ -8,10 +8,6 @@ using Butterfly.OpenTracing; namespace Ocelot.Requester { - public interface ITracingHandler - { - } - public class OcelotHttpTracingHandler : DelegatingHandler, ITracingHandler { private readonly IServiceTracer _tracer; diff --git a/src/Ocelot/Responses/ErrorResponseGeneric.cs b/src/Ocelot/Responses/ErrorResponseGeneric.cs index 90a16cdd..f57de97f 100644 --- a/src/Ocelot/Responses/ErrorResponseGeneric.cs +++ b/src/Ocelot/Responses/ErrorResponseGeneric.cs @@ -3,7 +3,9 @@ using Ocelot.Errors; namespace Ocelot.Responses { +#pragma warning disable SA1649 // File name must match first type name public class ErrorResponse : Response +#pragma warning restore SA1649 // File name must match first type name { public ErrorResponse(Error error) : base(new List {error}) diff --git a/src/Ocelot/Responses/OkResponseGeneric.cs b/src/Ocelot/Responses/OkResponseGeneric.cs index 7445d2d9..73fcf1e2 100644 --- a/src/Ocelot/Responses/OkResponseGeneric.cs +++ b/src/Ocelot/Responses/OkResponseGeneric.cs @@ -1,9 +1,11 @@ namespace Ocelot.Responses { +#pragma warning disable SA1649 // File name must match first type name public class OkResponse : Response +#pragma warning restore SA1649 // File name must match first type name { public OkResponse(T data) : base(data) { } } -} \ No newline at end of file +} diff --git a/src/Ocelot/Responses/ResponseGeneric.cs b/src/Ocelot/Responses/ResponseGeneric.cs index d06314bf..0b2514e9 100644 --- a/src/Ocelot/Responses/ResponseGeneric.cs +++ b/src/Ocelot/Responses/ResponseGeneric.cs @@ -3,7 +3,9 @@ using Ocelot.Errors; namespace Ocelot.Responses { +#pragma warning disable SA1649 // File name must match first type name public abstract class Response : Response +#pragma warning restore SA1649 // File name must match first type name { protected Response(T data) { diff --git a/test/Ocelot.UnitTests/Wait.cs b/test/Ocelot.UnitTests/Wait.cs new file mode 100644 index 00000000..d8fd3a88 --- /dev/null +++ b/test/Ocelot.UnitTests/Wait.cs @@ -0,0 +1,10 @@ +namespace Ocelot.UnitTests +{ + public class Wait + { + public static Waiter WaitFor(int milliSeconds) + { + return new Waiter(milliSeconds); + } + } +} \ No newline at end of file diff --git a/test/Ocelot.UnitTests/Waiter.cs b/test/Ocelot.UnitTests/Waiter.cs index 8fb51ae5..8847c5b9 100644 --- a/test/Ocelot.UnitTests/Waiter.cs +++ b/test/Ocelot.UnitTests/Waiter.cs @@ -3,14 +3,6 @@ using System.Diagnostics; namespace Ocelot.UnitTests { - public class Wait - { - public static Waiter WaitFor(int milliSeconds) - { - return new Waiter(milliSeconds); - } - } - public class Waiter { private readonly int _milliSeconds; @@ -52,4 +44,4 @@ namespace Ocelot.UnitTests return passed; } } -} \ No newline at end of file +} From 50980fda9391e0733fd1f8f962d0d45e07478d2f Mon Sep 17 00:00:00 2001 From: Philip Wood Date: Sat, 3 Mar 2018 14:08:52 +0000 Subject: [PATCH 20/26] Fix various violations SA1216, CS0105, CS0169, CS0414, CS0649 --- src/Ocelot/Raft/HttpPeer.cs | 3 ++- test/Ocelot.AcceptanceTests/AggregateTests.cs | 2 -- test/Ocelot.AcceptanceTests/CannotStartOcelotTests.cs | 5 ----- test/Ocelot.AcceptanceTests/Steps.cs | 8 -------- .../Authentication/AuthenticationMiddlewareTests.cs | 7 ------- .../Cache/OutputCacheMiddlewareRealCacheTests.cs | 8 -------- .../Claims/ClaimsBuilderMiddlewareTests.cs | 2 -- .../Configuration/ConsulFileConfigurationPollerTests.cs | 2 +- .../DependencyInjection/OcelotBuilderTests.cs | 1 - .../LoadBalancer/LoadBalancerHouseTests.cs | 2 -- .../LoadBalancer/LoadBalancerMiddlewareTests.cs | 6 ------ .../Middleware/OcelotPiplineBuilderTests.cs | 3 --- .../RequestId/ReRouteRequestIdMiddlewareTests.cs | 2 -- test/Ocelot.UnitTests/Requester/HttpClientBuilderTests.cs | 1 - test/Ocelot.UnitTests/Requester/QosProviderHouseTests.cs | 1 - .../Responder/ErrorsToHttpStatusCodeMapperTests.cs | 2 +- .../Responder/ResponderMiddlewareTests.cs | 3 --- 17 files changed, 4 insertions(+), 54 deletions(-) diff --git a/src/Ocelot/Raft/HttpPeer.cs b/src/Ocelot/Raft/HttpPeer.cs index 34a94b27..cd5ceef5 100644 --- a/src/Ocelot/Raft/HttpPeer.cs +++ b/src/Ocelot/Raft/HttpPeer.cs @@ -89,7 +89,8 @@ namespace Ocelot.Raft } } - public Response Request(T command) where T : ICommand + public Response Request(T command) + where T : ICommand { if(_token == null) { diff --git a/test/Ocelot.AcceptanceTests/AggregateTests.cs b/test/Ocelot.AcceptanceTests/AggregateTests.cs index 8510fd1b..3944adfc 100644 --- a/test/Ocelot.AcceptanceTests/AggregateTests.cs +++ b/test/Ocelot.AcceptanceTests/AggregateTests.cs @@ -15,7 +15,6 @@ namespace Ocelot.AcceptanceTests public class AggregateTests : IDisposable { private IWebHost _serviceOneBuilder; - private IWebHost _serviceTwoBuilder; private readonly Steps _steps; private string _downstreamPathOne; private string _downstreamPathTwo; @@ -364,7 +363,6 @@ namespace Ocelot.AcceptanceTests public void Dispose() { _serviceOneBuilder?.Dispose(); - _serviceTwoBuilder?.Dispose(); _steps.Dispose(); } } diff --git a/test/Ocelot.AcceptanceTests/CannotStartOcelotTests.cs b/test/Ocelot.AcceptanceTests/CannotStartOcelotTests.cs index f6c77b1c..e555ade7 100644 --- a/test/Ocelot.AcceptanceTests/CannotStartOcelotTests.cs +++ b/test/Ocelot.AcceptanceTests/CannotStartOcelotTests.cs @@ -1,18 +1,14 @@ using System; using System.Collections.Generic; -using Microsoft.AspNetCore.Hosting; using Ocelot.Configuration.File; using Shouldly; -using TestStack.BDDfy; using Xunit; namespace Ocelot.AcceptanceTests { public class CannotStartOcelotTests : IDisposable { - private IWebHost _builder; private readonly Steps _steps; - private string _downstreamPath; public CannotStartOcelotTests() { @@ -50,7 +46,6 @@ namespace Ocelot.AcceptanceTests public void Dispose() { - _builder?.Dispose(); _steps.Dispose(); } } diff --git a/test/Ocelot.AcceptanceTests/Steps.cs b/test/Ocelot.AcceptanceTests/Steps.cs index 09f68998..61a01059 100644 --- a/test/Ocelot.AcceptanceTests/Steps.cs +++ b/test/Ocelot.AcceptanceTests/Steps.cs @@ -1,7 +1,5 @@ using System; -using System.Collections.Concurrent; using System.Collections.Generic; -using System.Diagnostics; using System.IO; using System.Linq; using System.Net; @@ -19,15 +17,11 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Newtonsoft.Json; using Ocelot.Configuration.File; -using Ocelot.Configuration.Repository; using Ocelot.DependencyInjection; using Ocelot.Middleware; -using Ocelot.ServiceDiscovery; using Shouldly; using ConfigurationBuilder = Microsoft.Extensions.Configuration.ConfigurationBuilder; using Ocelot.AcceptanceTests.Caching; -using Butterfly.Client.AspNetCore; -using Butterfly.Client.Tracing; namespace Ocelot.AcceptanceTests { @@ -42,11 +36,9 @@ namespace Ocelot.AcceptanceTests public string RequestIdKey = "OcRequestId"; private readonly Random _random; private IWebHostBuilder _webHostBuilder; - private readonly string _baseUrl; public Steps() { - _baseUrl = "http://localhost:5000"; _random = new Random(); } diff --git a/test/Ocelot.UnitTests/Authentication/AuthenticationMiddlewareTests.cs b/test/Ocelot.UnitTests/Authentication/AuthenticationMiddlewareTests.cs index 1ab81895..e5cb64ae 100644 --- a/test/Ocelot.UnitTests/Authentication/AuthenticationMiddlewareTests.cs +++ b/test/Ocelot.UnitTests/Authentication/AuthenticationMiddlewareTests.cs @@ -6,24 +6,17 @@ namespace Ocelot.UnitTests.Authentication using System.Collections.Generic; using System.IO; using System.Text; - using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http; - using Microsoft.Extensions.DependencyInjection; using Moq; using Ocelot.Authentication.Middleware; using Ocelot.Configuration.Builder; - using Ocelot.DownstreamRouteFinder; - using Ocelot.DownstreamRouteFinder.Middleware; - using Ocelot.DownstreamRouteFinder.UrlMatcher; using Ocelot.Logging; - using Ocelot.Responses; using Shouldly; using TestStack.BDDfy; using Xunit; public class AuthenticationMiddlewareTests { - private OkResponse _downstreamRoute; private AuthenticationMiddleware _middleware; private Mock _factory; private Mock _logger; diff --git a/test/Ocelot.UnitTests/Cache/OutputCacheMiddlewareRealCacheTests.cs b/test/Ocelot.UnitTests/Cache/OutputCacheMiddlewareRealCacheTests.cs index 4e9ef04d..c0a76b2a 100644 --- a/test/Ocelot.UnitTests/Cache/OutputCacheMiddlewareRealCacheTests.cs +++ b/test/Ocelot.UnitTests/Cache/OutputCacheMiddlewareRealCacheTests.cs @@ -1,5 +1,4 @@ using Ocelot.Errors; -using Ocelot.Infrastructure.RequestData; using Ocelot.Middleware; namespace Ocelot.UnitTests.Cache @@ -11,26 +10,19 @@ namespace Ocelot.UnitTests.Cache using Shouldly; using System.Collections.Generic; using System.Net.Http; - using Microsoft.AspNetCore.Builder; - using Microsoft.Extensions.DependencyInjection; using Moq; using Ocelot.Cache; using Ocelot.Cache.Middleware; using Ocelot.Configuration; using Ocelot.Configuration.Builder; - using Ocelot.DownstreamRouteFinder; - using Ocelot.DownstreamRouteFinder.UrlMatcher; using Ocelot.Logging; - using Ocelot.Responses; using TestStack.BDDfy; using Xunit; - using Ocelot.DownstreamRouteFinder.Middleware; using Microsoft.AspNetCore.Http; public class OutputCacheMiddlewareRealCacheTests { private IOcelotCache _cacheManager; - private CachedResponse _response; private OutputCacheMiddleware _middleware; private DownstreamContext _downstreamContext; private OcelotRequestDelegate _next; diff --git a/test/Ocelot.UnitTests/Claims/ClaimsBuilderMiddlewareTests.cs b/test/Ocelot.UnitTests/Claims/ClaimsBuilderMiddlewareTests.cs index 5b5e386c..f6bf052c 100644 --- a/test/Ocelot.UnitTests/Claims/ClaimsBuilderMiddlewareTests.cs +++ b/test/Ocelot.UnitTests/Claims/ClaimsBuilderMiddlewareTests.cs @@ -15,12 +15,10 @@ namespace Ocelot.UnitTests.Claims using Ocelot.Responses; using TestStack.BDDfy; using Xunit; - using Ocelot.DownstreamRouteFinder.Middleware; public class ClaimsBuilderMiddlewareTests { private readonly Mock _addHeaders; - private Response _downstreamRoute; private Mock _loggerFactory; private Mock _logger; private readonly ClaimsBuilderMiddleware _middleware; diff --git a/test/Ocelot.UnitTests/Configuration/ConsulFileConfigurationPollerTests.cs b/test/Ocelot.UnitTests/Configuration/ConsulFileConfigurationPollerTests.cs index b743b598..4a6faba2 100644 --- a/test/Ocelot.UnitTests/Configuration/ConsulFileConfigurationPollerTests.cs +++ b/test/Ocelot.UnitTests/Configuration/ConsulFileConfigurationPollerTests.cs @@ -83,7 +83,7 @@ namespace Ocelot.UnitTests.Configuration _setter.Verify(x => x.Set(fileConfig), Times.Once); return true; } - catch(Exception ex) + catch(Exception) { return false; } diff --git a/test/Ocelot.UnitTests/DependencyInjection/OcelotBuilderTests.cs b/test/Ocelot.UnitTests/DependencyInjection/OcelotBuilderTests.cs index 8ed1a327..c2f35990 100644 --- a/test/Ocelot.UnitTests/DependencyInjection/OcelotBuilderTests.cs +++ b/test/Ocelot.UnitTests/DependencyInjection/OcelotBuilderTests.cs @@ -15,7 +15,6 @@ using Ocelot.DependencyInjection; using Ocelot.Requester; using Ocelot.UnitTests.Requester; using Shouldly; -using System; using IdentityServer4.AccessTokenValidation; using TestStack.BDDfy; using Xunit; diff --git a/test/Ocelot.UnitTests/LoadBalancer/LoadBalancerHouseTests.cs b/test/Ocelot.UnitTests/LoadBalancer/LoadBalancerHouseTests.cs index 2a4d3a24..e8808f17 100644 --- a/test/Ocelot.UnitTests/LoadBalancer/LoadBalancerHouseTests.cs +++ b/test/Ocelot.UnitTests/LoadBalancer/LoadBalancerHouseTests.cs @@ -17,9 +17,7 @@ namespace Ocelot.UnitTests.LoadBalancer private DownstreamReRoute _reRoute; private ILoadBalancer _loadBalancer; private readonly LoadBalancerHouse _loadBalancerHouse; - private Response _addResult; private Response _getResult; - private string _key; private readonly Mock _factory; private ServiceProviderConfiguration _serviceProviderConfig; diff --git a/test/Ocelot.UnitTests/LoadBalancer/LoadBalancerMiddlewareTests.cs b/test/Ocelot.UnitTests/LoadBalancer/LoadBalancerMiddlewareTests.cs index 0af8b3af..242463a2 100644 --- a/test/Ocelot.UnitTests/LoadBalancer/LoadBalancerMiddlewareTests.cs +++ b/test/Ocelot.UnitTests/LoadBalancer/LoadBalancerMiddlewareTests.cs @@ -4,15 +4,10 @@ namespace Ocelot.UnitTests.LoadBalancer { using System.Collections.Generic; using System.Net.Http; - using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http; - using Microsoft.Extensions.DependencyInjection; using Moq; using Ocelot.Configuration; using Ocelot.Configuration.Builder; - using Ocelot.Configuration.Provider; - using Ocelot.DownstreamRouteFinder; - using Ocelot.DownstreamRouteFinder.Middleware; using Ocelot.Errors; using Ocelot.LoadBalancer.LoadBalancers; using Ocelot.LoadBalancer.Middleware; @@ -28,7 +23,6 @@ namespace Ocelot.UnitTests.LoadBalancer private readonly Mock _loadBalancerHouse; private readonly Mock _loadBalancer; private ServiceHostAndPort _hostAndPort; - private OkResponse _downstreamRoute; private ErrorResponse _getLoadBalancerHouseError; private ErrorResponse _getHostAndPortError; private HttpRequestMessage _downstreamRequest; diff --git a/test/Ocelot.UnitTests/Middleware/OcelotPiplineBuilderTests.cs b/test/Ocelot.UnitTests/Middleware/OcelotPiplineBuilderTests.cs index dbb0ae63..988d0b21 100644 --- a/test/Ocelot.UnitTests/Middleware/OcelotPiplineBuilderTests.cs +++ b/test/Ocelot.UnitTests/Middleware/OcelotPiplineBuilderTests.cs @@ -1,6 +1,5 @@ namespace Ocelot.UnitTests.Middleware { - using System; using System.Collections.Generic; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting.Internal; @@ -17,9 +16,7 @@ public class OcelotPiplineBuilderTests { private readonly IServiceCollection _services; - private IServiceProvider _serviceProvider; private readonly IConfiguration _configRoot; - private IOcelotBuilder _ocelotBuilder; private DownstreamContext _downstreamContext; private int _counter; diff --git a/test/Ocelot.UnitTests/RequestId/ReRouteRequestIdMiddlewareTests.cs b/test/Ocelot.UnitTests/RequestId/ReRouteRequestIdMiddlewareTests.cs index c49f2c6a..f6bf4eb7 100644 --- a/test/Ocelot.UnitTests/RequestId/ReRouteRequestIdMiddlewareTests.cs +++ b/test/Ocelot.UnitTests/RequestId/ReRouteRequestIdMiddlewareTests.cs @@ -4,7 +4,6 @@ namespace Ocelot.UnitTests.RequestId { using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Primitives; - using Ocelot.DownstreamRouteFinder.Middleware; using Ocelot.Infrastructure.RequestData; using System; using System.Collections.Generic; @@ -24,7 +23,6 @@ namespace Ocelot.UnitTests.RequestId public class ReRouteRequestIdMiddlewareTests { private readonly HttpRequestMessage _downstreamRequest; - private Response _downstreamRoute; private string _value; private string _key; private Mock _loggerFactory; diff --git a/test/Ocelot.UnitTests/Requester/HttpClientBuilderTests.cs b/test/Ocelot.UnitTests/Requester/HttpClientBuilderTests.cs index b5d7e1e6..b788c826 100644 --- a/test/Ocelot.UnitTests/Requester/HttpClientBuilderTests.cs +++ b/test/Ocelot.UnitTests/Requester/HttpClientBuilderTests.cs @@ -17,7 +17,6 @@ namespace Ocelot.UnitTests.Requester private readonly HttpClientBuilder _builder; private readonly Mock _house; private readonly Mock _provider; - private IHttpClientBuilder _builderResult; private IHttpClient _httpClient; private HttpResponseMessage _response; private DownstreamReRoute _request; diff --git a/test/Ocelot.UnitTests/Requester/QosProviderHouseTests.cs b/test/Ocelot.UnitTests/Requester/QosProviderHouseTests.cs index f6095034..ae027143 100644 --- a/test/Ocelot.UnitTests/Requester/QosProviderHouseTests.cs +++ b/test/Ocelot.UnitTests/Requester/QosProviderHouseTests.cs @@ -13,7 +13,6 @@ namespace Ocelot.UnitTests.Requester { private IQoSProvider _qoSProvider; private readonly QosProviderHouse _qosProviderHouse; - private Response _addResult; private Response _getResult; private DownstreamReRoute _reRoute; private readonly Mock _factory; diff --git a/test/Ocelot.UnitTests/Responder/ErrorsToHttpStatusCodeMapperTests.cs b/test/Ocelot.UnitTests/Responder/ErrorsToHttpStatusCodeMapperTests.cs index 977a0b12..9800ffef 100644 --- a/test/Ocelot.UnitTests/Responder/ErrorsToHttpStatusCodeMapperTests.cs +++ b/test/Ocelot.UnitTests/Responder/ErrorsToHttpStatusCodeMapperTests.cs @@ -42,7 +42,7 @@ namespace Ocelot.UnitTests.Responder [InlineData(OcelotErrorCode.RequestTimedOutError)] public void should_return_service_unavailable(OcelotErrorCode errorCode) { - ShouldMapErrorToStatusCode(OcelotErrorCode.RequestTimedOutError, HttpStatusCode.ServiceUnavailable); + ShouldMapErrorToStatusCode(errorCode, HttpStatusCode.ServiceUnavailable); } [Theory] diff --git a/test/Ocelot.UnitTests/Responder/ResponderMiddlewareTests.cs b/test/Ocelot.UnitTests/Responder/ResponderMiddlewareTests.cs index 28a0707a..54b795a2 100644 --- a/test/Ocelot.UnitTests/Responder/ResponderMiddlewareTests.cs +++ b/test/Ocelot.UnitTests/Responder/ResponderMiddlewareTests.cs @@ -4,7 +4,6 @@ using Ocelot.Middleware; namespace Ocelot.UnitTests.Responder { using Microsoft.AspNetCore.Http; - using Ocelot.DownstreamRouteFinder.Middleware; using System.Net.Http; using Moq; using Ocelot.DownstreamRouteFinder.Finder; @@ -12,7 +11,6 @@ namespace Ocelot.UnitTests.Responder using Ocelot.Logging; using Ocelot.Responder; using Ocelot.Responder.Middleware; - using Ocelot.Responses; using TestStack.BDDfy; using Xunit; @@ -20,7 +18,6 @@ namespace Ocelot.UnitTests.Responder { private readonly Mock _responder; private readonly Mock _codeMapper; - private OkResponse _response; private Mock _loggerFactory; private Mock _logger; private readonly ResponderMiddleware _middleware; From 01fe4ef9aaf454744d35931c109bef9f4f1fdce5 Mon Sep 17 00:00:00 2001 From: Philip Wood Date: Sat, 3 Mar 2018 14:15:39 +0000 Subject: [PATCH 21/26] Turn off a few more rules --- Ocelot.sln | 1 + codeanalysis.ruleset | 3 +++ 2 files changed, 4 insertions(+) diff --git a/Ocelot.sln b/Ocelot.sln index 6aa429fe..c9ac2782 100644 --- a/Ocelot.sln +++ b/Ocelot.sln @@ -12,6 +12,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution build-and-run-tests.ps1 = build-and-run-tests.ps1 build.cake = build.cake build.ps1 = build.ps1 + codeanalysis.ruleset = codeanalysis.ruleset GitVersion.yml = GitVersion.yml global.json = global.json LICENSE.md = LICENSE.md diff --git a/codeanalysis.ruleset b/codeanalysis.ruleset index e867f4e5..ee66e99d 100644 --- a/codeanalysis.ruleset +++ b/codeanalysis.ruleset @@ -99,6 +99,7 @@ + @@ -113,12 +114,14 @@ + + From 454ba3f9a03d79dfd493d67d6a02c0a2eb1d0c4b Mon Sep 17 00:00:00 2001 From: Tom Pallister Date: Sat, 3 Mar 2018 15:24:05 +0000 Subject: [PATCH 22/26] Make Ocelot work with service fabric DNS and naming service for guest exe and stateless (#242) * test for issue * added service fabric sample * working!! * changed sample naming to Ocelot * removed files we dont need * removed files we dont need * updated sample gitignore * updated sample gitignore * getting ocelot to work with service fabric using the reverse proxy * #238 - added support for service fabric discovery provider, proxies requests through naming service, wont work on partioned service fabric services yet * #238 - Manually tested service fabric using sample..all seems OK. Made some changes after testing, added docs * #238 - added docs for servic fabric --- Ocelot.sln | 19 + docs/features/servicediscovery.rst | 14 +- docs/features/servicefabric.rst | 35 + docs/index.rst | 1 + .../ocelot.postman_collection.json | 626 +++++++++--------- samples/OcelotServiceFabric/.gitignore | 269 ++++++++ samples/OcelotServiceFabric/CONTRIBUTING.md | 11 + samples/OcelotServiceFabric/LICENSE.md | 21 + .../OcelotApplication/ApplicationManifest.xml | 39 ++ .../Code/entryPoint.cmd | 2 + .../Code/entryPoint.sh | 17 + .../Config/Settings.xml | 9 + .../Config/_readme.txt | 12 + .../Data/_readme.txt | 5 + .../ServiceManifest-Linux.xml | 35 + .../ServiceManifest-Windows.xml | 35 + .../ServiceManifest.xml | 35 + .../Code/entryPoint.cmd | 2 + .../Code/entryPoint.sh | 15 + .../Config/Settings.xml | 9 + .../Config/_readme.txt | 12 + .../Data/_readme.txt | 5 + .../ServiceManifest-Linux.xml | 32 + .../ServiceManifest-Windows.xml | 32 + .../ServiceManifest.xml | 32 + samples/OcelotServiceFabric/README.md | 51 ++ samples/OcelotServiceFabric/build.bat | 12 + samples/OcelotServiceFabric/build.sh | 15 + samples/OcelotServiceFabric/dotnet-include.sh | 12 + samples/OcelotServiceFabric/install.ps1 | 20 + samples/OcelotServiceFabric/install.sh | 22 + .../OcelotApplicationApiGateway.cs | 31 + .../OcelotApplicationApiGateway.csproj | 22 + .../OcelotApplicationApiGateway/Program.cs | 51 ++ .../Properties/launchSettings.json | 27 + .../ServiceEventListener.cs | 94 +++ .../ServiceEventSource.cs | 86 +++ .../WebCommunicationListener.cs | 125 ++++ .../appsettings.json | 10 + .../configuration.json | 22 + .../OcelotApplicationService/ApiGateway.cs | 59 ++ .../Controllers/ValuesController.cs | 44 ++ .../OcelotApplicationService.csproj | 21 + .../src/OcelotApplicationService/Program.cs | 38 ++ .../ServiceEventSource.cs | 189 ++++++ .../src/OcelotApplicationService/Startup.cs | 40 ++ samples/OcelotServiceFabric/src/global.json | 6 + samples/OcelotServiceFabric/uninstall.ps1 | 2 + samples/OcelotServiceFabric/uninstall.sh | 5 + .../Builder/DownstreamReRouteBuilder.cs | 1 - .../ServiceProviderConfigurationBuilder.cs | 11 +- .../ServiceProviderConfigurationCreator.cs | 10 +- .../File/FileServiceDiscoveryProvider.cs | 3 +- .../ConsulFileConfigurationRepository.cs | 6 +- .../ServiceProviderConfiguraion.cs | 14 +- .../FileConfigurationFluentValidator.cs | 2 +- .../DependencyInjection/OcelotBuilder.cs | 1 - .../DownstreamUrlCreator/IUrlBuilder.cs | 4 +- .../DownstreamUrlCreatorMiddleware.cs | 35 +- src/Ocelot/DownstreamUrlCreator/UrlBuilder.cs | 7 +- .../LoadBalancers/NoLoadBalancer.cs | 1 + .../ServiceDiscoveryProviderFactory.cs | 12 +- .../ServiceFabricConfiguration.cs | 16 + .../ServiceFabricServiceDiscoveryProvider.cs | 29 + .../ServiceFabricTests.cs | 112 ++++ .../ConfigurationFluentValidationTests.cs | 2 +- .../ServiceProviderCreatorTests.cs | 10 +- .../DownstreamUrlCreatorMiddlewareTests.cs | 76 ++- .../DownstreamUrlCreator/UrlBuilderTests.cs | 122 ---- ...viceFabricServiceDiscoveryProviderTests.cs | 58 ++ .../ServiceProviderFactoryTests.cs | 18 + 71 files changed, 2394 insertions(+), 484 deletions(-) create mode 100644 docs/features/servicefabric.rst rename ocelot.postman_collection.json => postman/ocelot.postman_collection.json (96%) create mode 100644 samples/OcelotServiceFabric/.gitignore create mode 100644 samples/OcelotServiceFabric/CONTRIBUTING.md create mode 100644 samples/OcelotServiceFabric/LICENSE.md create mode 100644 samples/OcelotServiceFabric/OcelotApplication/ApplicationManifest.xml create mode 100644 samples/OcelotServiceFabric/OcelotApplication/OcelotApplicationApiGatewayPkg/Code/entryPoint.cmd create mode 100644 samples/OcelotServiceFabric/OcelotApplication/OcelotApplicationApiGatewayPkg/Code/entryPoint.sh create mode 100644 samples/OcelotServiceFabric/OcelotApplication/OcelotApplicationApiGatewayPkg/Config/Settings.xml create mode 100644 samples/OcelotServiceFabric/OcelotApplication/OcelotApplicationApiGatewayPkg/Config/_readme.txt create mode 100644 samples/OcelotServiceFabric/OcelotApplication/OcelotApplicationApiGatewayPkg/Data/_readme.txt create mode 100644 samples/OcelotServiceFabric/OcelotApplication/OcelotApplicationApiGatewayPkg/ServiceManifest-Linux.xml create mode 100644 samples/OcelotServiceFabric/OcelotApplication/OcelotApplicationApiGatewayPkg/ServiceManifest-Windows.xml create mode 100644 samples/OcelotServiceFabric/OcelotApplication/OcelotApplicationApiGatewayPkg/ServiceManifest.xml create mode 100644 samples/OcelotServiceFabric/OcelotApplication/OcelotApplicationServicePkg/Code/entryPoint.cmd create mode 100644 samples/OcelotServiceFabric/OcelotApplication/OcelotApplicationServicePkg/Code/entryPoint.sh create mode 100644 samples/OcelotServiceFabric/OcelotApplication/OcelotApplicationServicePkg/Config/Settings.xml create mode 100644 samples/OcelotServiceFabric/OcelotApplication/OcelotApplicationServicePkg/Config/_readme.txt create mode 100644 samples/OcelotServiceFabric/OcelotApplication/OcelotApplicationServicePkg/Data/_readme.txt create mode 100644 samples/OcelotServiceFabric/OcelotApplication/OcelotApplicationServicePkg/ServiceManifest-Linux.xml create mode 100644 samples/OcelotServiceFabric/OcelotApplication/OcelotApplicationServicePkg/ServiceManifest-Windows.xml create mode 100644 samples/OcelotServiceFabric/OcelotApplication/OcelotApplicationServicePkg/ServiceManifest.xml create mode 100644 samples/OcelotServiceFabric/README.md create mode 100644 samples/OcelotServiceFabric/build.bat create mode 100644 samples/OcelotServiceFabric/build.sh create mode 100644 samples/OcelotServiceFabric/dotnet-include.sh create mode 100644 samples/OcelotServiceFabric/install.ps1 create mode 100644 samples/OcelotServiceFabric/install.sh create mode 100644 samples/OcelotServiceFabric/src/OcelotApplicationApiGateway/OcelotApplicationApiGateway.cs create mode 100644 samples/OcelotServiceFabric/src/OcelotApplicationApiGateway/OcelotApplicationApiGateway.csproj create mode 100644 samples/OcelotServiceFabric/src/OcelotApplicationApiGateway/Program.cs create mode 100644 samples/OcelotServiceFabric/src/OcelotApplicationApiGateway/Properties/launchSettings.json create mode 100644 samples/OcelotServiceFabric/src/OcelotApplicationApiGateway/ServiceEventListener.cs create mode 100644 samples/OcelotServiceFabric/src/OcelotApplicationApiGateway/ServiceEventSource.cs create mode 100644 samples/OcelotServiceFabric/src/OcelotApplicationApiGateway/WebCommunicationListener.cs create mode 100644 samples/OcelotServiceFabric/src/OcelotApplicationApiGateway/appsettings.json create mode 100644 samples/OcelotServiceFabric/src/OcelotApplicationApiGateway/configuration.json create mode 100644 samples/OcelotServiceFabric/src/OcelotApplicationService/ApiGateway.cs create mode 100644 samples/OcelotServiceFabric/src/OcelotApplicationService/Controllers/ValuesController.cs create mode 100644 samples/OcelotServiceFabric/src/OcelotApplicationService/OcelotApplicationService.csproj create mode 100644 samples/OcelotServiceFabric/src/OcelotApplicationService/Program.cs create mode 100644 samples/OcelotServiceFabric/src/OcelotApplicationService/ServiceEventSource.cs create mode 100644 samples/OcelotServiceFabric/src/OcelotApplicationService/Startup.cs create mode 100644 samples/OcelotServiceFabric/src/global.json create mode 100644 samples/OcelotServiceFabric/uninstall.ps1 create mode 100644 samples/OcelotServiceFabric/uninstall.sh create mode 100644 src/Ocelot/ServiceDiscovery/ServiceFabricConfiguration.cs create mode 100644 src/Ocelot/ServiceDiscovery/ServiceFabricServiceDiscoveryProvider.cs create mode 100644 test/Ocelot.AcceptanceTests/ServiceFabricTests.cs delete mode 100644 test/Ocelot.UnitTests/DownstreamUrlCreator/UrlBuilderTests.cs create mode 100644 test/Ocelot.UnitTests/ServiceDiscovery/ServiceFabricServiceDiscoveryProviderTests.cs diff --git a/Ocelot.sln b/Ocelot.sln index 6aa429fe..e966a5ae 100644 --- a/Ocelot.sln +++ b/Ocelot.sln @@ -39,6 +39,14 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ocelot.Benchmarks", "test\O EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ocelot.IntegrationTests", "test\Ocelot.IntegrationTests\Ocelot.IntegrationTests.csproj", "{D4575572-99CA-4530-8737-C296EDA326F8}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{E78EF991-3401-459A-94FE-EC4F4E5BD702}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OcelotApplicationApiGateway", "samples\OcelotServiceFabric\src\OcelotApplicationApiGateway\OcelotApplicationApiGateway.csproj", "{1A3A3D97-33AB-48FB-8A9F-92905A15DF74}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OcelotApplicationService", "samples\OcelotServiceFabric\src\OcelotApplicationService\OcelotApplicationService.csproj", "{272DD79B-7D04-4DFB-BB64-B1C098CE8050}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "OcelotServiceFabric", "OcelotServiceFabric", "{98424512-BCF5-4F42-ACB2-6D7040D92487}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -69,6 +77,14 @@ Global {D4575572-99CA-4530-8737-C296EDA326F8}.Debug|Any CPU.Build.0 = Debug|Any CPU {D4575572-99CA-4530-8737-C296EDA326F8}.Release|Any CPU.ActiveCfg = Release|Any CPU {D4575572-99CA-4530-8737-C296EDA326F8}.Release|Any CPU.Build.0 = Release|Any CPU + {1A3A3D97-33AB-48FB-8A9F-92905A15DF74}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1A3A3D97-33AB-48FB-8A9F-92905A15DF74}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1A3A3D97-33AB-48FB-8A9F-92905A15DF74}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1A3A3D97-33AB-48FB-8A9F-92905A15DF74}.Release|Any CPU.Build.0 = Release|Any CPU + {272DD79B-7D04-4DFB-BB64-B1C098CE8050}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {272DD79B-7D04-4DFB-BB64-B1C098CE8050}.Debug|Any CPU.Build.0 = Debug|Any CPU + {272DD79B-7D04-4DFB-BB64-B1C098CE8050}.Release|Any CPU.ActiveCfg = Release|Any CPU + {272DD79B-7D04-4DFB-BB64-B1C098CE8050}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -80,6 +96,9 @@ Global {02BBF4C5-517E-4157-8D21-4B8B9E118B7A} = {5B401523-36DA-4491-B73A-7590A26E420B} {106B49E6-95F6-4A7B-B81C-96BFA74AF035} = {5B401523-36DA-4491-B73A-7590A26E420B} {D4575572-99CA-4530-8737-C296EDA326F8} = {5B401523-36DA-4491-B73A-7590A26E420B} + {1A3A3D97-33AB-48FB-8A9F-92905A15DF74} = {98424512-BCF5-4F42-ACB2-6D7040D92487} + {272DD79B-7D04-4DFB-BB64-B1C098CE8050} = {98424512-BCF5-4F42-ACB2-6D7040D92487} + {98424512-BCF5-4F42-ACB2-6D7040D92487} = {E78EF991-3401-459A-94FE-EC4F4E5BD702} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {21476EFF-778A-4F97-8A56-D1AF1CEC0C48} diff --git a/docs/features/servicediscovery.rst b/docs/features/servicediscovery.rst index 28728db3..f8cadd2e 100644 --- a/docs/features/servicediscovery.rst +++ b/docs/features/servicediscovery.rst @@ -6,16 +6,18 @@ for the downstream service Ocelot is forwarding a request to. At the moment this GlobalConfiguration section which means the same service discovery provider will be used for all ReRoutes you specify a ServiceName for at ReRoute level. -At the moment the only supported service discovery provider is Consul. The following is required in the -GlobalConfiguration. The Provider is required and if you do not specify a host and port the Consul default +Consul +^^^^^^ + +The following is required in the GlobalConfiguration. The Provider is required and if you do not specify a host and port the Consul default will be used. .. code-block:: json "ServiceDiscoveryProvider": { - "Host": "localhost", - "Port": 9500 - } + "Host": "localhost", + "Port": 9500 + } In the future we can add a feature that allows ReRoute specfic configuration. @@ -35,4 +37,4 @@ and LeastConnection algorithm you can use. If no load balancer is specified Ocel "UseServiceDiscovery": true } -When this is set up Ocelot will lookup the downstream host and port from the service discover provider and load balance requests across any available services. \ No newline at end of file +When this is set up Ocelot will lookup the downstream host and port from the service discover provider and load balance requests across any available services. diff --git a/docs/features/servicefabric.rst b/docs/features/servicefabric.rst new file mode 100644 index 00000000..e6f69983 --- /dev/null +++ b/docs/features/servicefabric.rst @@ -0,0 +1,35 @@ +Service Fabric +============== + +If you have services deployed in Service Fabric you will normally use the naming service to access them. + +The following example shows how to set up a ReRoute that will work in Service Fabric. The most important thing is the ServiceName which is made up of the +Service Fabric application name then the specific service name. We also need to set UseServiceDiscovery as true and set up the ServiceDiscoveryProvider in +GlobalConfiguration. The example here shows a typical configuration. It assumes service fabric is running on localhost and that the naming service is on port 19081. + +The example below is taken from the samples folder so please check it if this doesnt make sense! + +.. code-block:: json + + { + "ReRoutes": [ + { + "DownstreamPathTemplate": "/api/values", + "UpstreamPathTemplate": "/EquipmentInterfaces", + "UpstreamHttpMethod": [ + "Get" + ], + "DownstreamScheme": "http", + "ServiceName": "OcelotServiceApplication/OcelotApplicationService", + "UseServiceDiscovery" : true + } + ], + "GlobalConfiguration": { + "RequestIdKey": "OcRequestId", + "ServiceDiscoveryProvider": { + "Host": "localhost", + "Port": 19081, + "Type": "ServiceFabric" + } + } + } diff --git a/docs/index.rst b/docs/index.rst index 258085ef..43a6c436 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -22,6 +22,7 @@ Thanks for taking a look at the Ocelot documentation. Please use the left hand n features/routing features/requestaggregation features/servicediscovery + features/servicefabric features/authentication features/authorisation features/administration diff --git a/ocelot.postman_collection.json b/postman/ocelot.postman_collection.json similarity index 96% rename from ocelot.postman_collection.json rename to postman/ocelot.postman_collection.json index 2dc33d33..28bbeb0c 100644 --- a/ocelot.postman_collection.json +++ b/postman/ocelot.postman_collection.json @@ -1,314 +1,314 @@ -{ - "id": "4dbde9fe-89f5-be35-bb9f-d3b438e16375", - "name": "Ocelot", - "description": "", - "order": [ - "a1c95935-ed18-d5dc-bcb8-a3db8ba1934f", - "ea0ed57a-2cb9-8acc-47dd-006b8db2f1b2", - "c4494401-3985-a5bf-71fb-6e4171384ac6", - "09af8dda-a9cb-20d2-5ee3-0a3023773a1a", - "e8825dc3-4137-99a7-0000-ef5786610dc3", - "fddfc4fa-5114-69e3-4744-203ed71a526b", - "c45d30d7-d9c4-fa05-8110-d6e769bb6ff9", - "4684c2fa-f38c-c193-5f55-bf563a1978c6", - "5f308240-79e3-cf74-7a6b-fe462f0d54f1", - "178f16da-c61b-c881-1c33-9d64a56851a4", - "26a08569-85f6-7f9a-726f-61be419c7a34" - ], - "folders": [], - "timestamp": 0, - "owner": "212120", - "public": false, - "requests": [ - { - "folder": null, - "id": "09af8dda-a9cb-20d2-5ee3-0a3023773a1a", - "name": "GET http://localhost:5000/comments?postId=1", - "dataMode": "params", - "data": null, - "rawModeData": null, - "descriptionFormat": "html", - "description": "", - "headers": "", - "method": "GET", - "pathVariables": {}, - "url": "http://localhost:5000/comments?postId=1", - "preRequestScript": null, - "tests": null, - "currentHelper": "normal", - "helperAttributes": {}, - "collectionId": "4dbde9fe-89f5-be35-bb9f-d3b438e16375" - }, - { - "id": "178f16da-c61b-c881-1c33-9d64a56851a4", - "headers": "Authorization: Bearer {{AccessToken}}\n", - "url": "http://localhost:5000/administration/configuration", - "preRequestScript": null, - "pathVariables": {}, - "method": "GET", - "data": null, - "dataMode": "params", - "tests": null, - "currentHelper": "normal", - "helperAttributes": {}, - "time": 1508914722969, - "name": "GET http://localhost:5000/admin/configuration", - "description": "", - "collectionId": "4dbde9fe-89f5-be35-bb9f-d3b438e16375" - }, - { - "id": "26a08569-85f6-7f9a-726f-61be419c7a34", - "headers": "", - "url": "http://localhost:5000/administration/connect/token", - "preRequestScript": null, - "pathVariables": {}, - "method": "POST", - "data": [ - { - "key": "client_id", - "value": "raft", - "type": "text", - "enabled": true - }, - { - "key": "client_secret", - "value": "REALLYHARDPASSWORD", - "type": "text", - "enabled": true - }, - { - "key": "scope", - "value": "admin raft ", - "type": "text", - "enabled": true - }, - { - "key": "username", - "value": "admin", - "type": "text", - "enabled": false - }, - { - "key": "password", - "value": "secret", - "type": "text", - "enabled": false - }, - { - "key": "grant_type", - "value": "client_credentials", - "type": "text", - "enabled": true - } - ], - "dataMode": "params", - "tests": "var jsonData = JSON.parse(responseBody);\npostman.setGlobalVariable(\"AccessToken\", jsonData.access_token);\npostman.setGlobalVariable(\"RefreshToken\", jsonData.refresh_token);", - "currentHelper": "normal", - "helperAttributes": {}, - "time": 1513240031907, - "name": "POST http://localhost:5000/admin/connect/token copy copy", - "description": "", - "collectionId": "4dbde9fe-89f5-be35-bb9f-d3b438e16375" - }, - { - "folder": null, - "id": "4684c2fa-f38c-c193-5f55-bf563a1978c6", - "name": "DELETE http://localhost:5000/posts/1", - "dataMode": "params", - "data": null, - "rawModeData": null, - "descriptionFormat": "html", - "description": "", - "headers": "", - "method": "DELETE", - "pathVariables": {}, - "url": "http://localhost:5000/posts/1", - "preRequestScript": null, - "tests": null, - "currentHelper": "normal", - "helperAttributes": {}, - "collectionId": "4dbde9fe-89f5-be35-bb9f-d3b438e16375" - }, - { - "id": "5f308240-79e3-cf74-7a6b-fe462f0d54f1", - "headers": "Authorization: Bearer {{AccessToken}}\n", - "url": "http://localhost:5000/administration/.well-known/openid-configuration", - "preRequestScript": null, - "pathVariables": {}, - "method": "GET", - "data": null, - "dataMode": "params", - "tests": null, - "currentHelper": "normal", - "helperAttributes": "{}", - "time": 1488038888813, - "name": "GET http://localhost:5000/admin/.well-known/openid-configuration", - "description": "", - "collectionId": "4dbde9fe-89f5-be35-bb9f-d3b438e16375", - "folder": null, - "rawModeData": null, - "descriptionFormat": null, - "queryParams": [], - "headerData": [ - { - "key": "Authorization", - "value": "Bearer {{AccessToken}}", - "description": "", - "enabled": true - } - ], - "pathVariableData": [] - }, - { - "id": "a1c95935-ed18-d5dc-bcb8-a3db8ba1934f", - "folder": null, - "name": "GET http://localhost:5000/posts", - "dataMode": "params", - "data": [ - { - "key": "client_id", - "value": "admin", - "type": "text", - "enabled": true - }, - { - "key": "client_secret", - "value": "secret", - "type": "text", - "enabled": true - }, - { - "key": "scope", - "value": "admin", - "type": "text", - "enabled": true - }, - { - "key": "username", - "value": "admin", - "type": "text", - "enabled": true - }, - { - "key": "password", - "value": "admin", - "type": "text", - "enabled": true - }, - { - "key": "grant_type", - "value": "password", - "type": "text", - "enabled": true - } - ], - "rawModeData": null, - "descriptionFormat": "html", - "description": "", - "headers": "", - "method": "POST", - "pathVariables": {}, - "url": "http://localhost:5000/admin/configuration", - "preRequestScript": null, - "tests": null, - "currentHelper": "normal", - "helperAttributes": "{}", - "collectionId": "4dbde9fe-89f5-be35-bb9f-d3b438e16375" - }, - { - "folder": null, - "id": "c4494401-3985-a5bf-71fb-6e4171384ac6", - "name": "GET http://localhost:5000/posts/1/comments", - "dataMode": "params", - "data": null, - "rawModeData": null, - "descriptionFormat": "html", - "description": "", - "headers": "", - "method": "GET", - "pathVariables": {}, - "url": "http://localhost:5000/posts/1/comments", - "preRequestScript": null, - "tests": null, - "currentHelper": "normal", - "helperAttributes": {}, - "collectionId": "4dbde9fe-89f5-be35-bb9f-d3b438e16375" - }, - { - "folder": null, - "id": "c45d30d7-d9c4-fa05-8110-d6e769bb6ff9", - "name": "PATCH http://localhost:5000/posts/1", - "dataMode": "raw", - "data": [], - "descriptionFormat": "html", - "description": "", - "headers": "", - "method": "PATCH", - "pathVariables": {}, - "url": "http://localhost:5000/posts/1", - "preRequestScript": null, - "tests": null, - "currentHelper": "normal", - "helperAttributes": {}, - "collectionId": "4dbde9fe-89f5-be35-bb9f-d3b438e16375", - "rawModeData": "{\n \"title\": \"gfdgsgsdgsdfgsdfgdfg\",\n}" - }, - { - "folder": null, - "id": "e8825dc3-4137-99a7-0000-ef5786610dc3", - "name": "POST http://localhost:5000/posts/1", - "dataMode": "raw", - "data": [], - "descriptionFormat": "html", - "description": "", - "headers": "", - "method": "POST", - "pathVariables": {}, - "url": "http://localhost:5000/posts", - "preRequestScript": null, - "tests": null, - "currentHelper": "normal", - "helperAttributes": {}, - "collectionId": "4dbde9fe-89f5-be35-bb9f-d3b438e16375", - "rawModeData": "{\n \"userId\": 1,\n \"title\": \"test\",\n \"body\": \"test\"\n}" - }, - { - "folder": null, - "id": "ea0ed57a-2cb9-8acc-47dd-006b8db2f1b2", - "name": "GET http://localhost:5000/posts/1", - "dataMode": "params", - "data": null, - "rawModeData": null, - "descriptionFormat": "html", - "description": "", - "headers": "", - "method": "GET", - "pathVariables": {}, - "url": "http://localhost:5000/posts/1", - "preRequestScript": null, - "tests": null, - "currentHelper": "normal", - "helperAttributes": {}, - "collectionId": "4dbde9fe-89f5-be35-bb9f-d3b438e16375" - }, - { - "folder": null, - "id": "fddfc4fa-5114-69e3-4744-203ed71a526b", - "name": "PUT http://localhost:5000/posts/1", - "dataMode": "raw", - "data": [], - "descriptionFormat": "html", - "description": "", - "headers": "", - "method": "PUT", - "pathVariables": {}, - "url": "http://localhost:5000/posts/1", - "preRequestScript": null, - "tests": null, - "currentHelper": "normal", - "helperAttributes": {}, - "collectionId": "4dbde9fe-89f5-be35-bb9f-d3b438e16375", - "rawModeData": "{\n \"userId\": 1,\n \"title\": \"test\",\n \"body\": \"test\"\n}" - } - ] +{ + "id": "4dbde9fe-89f5-be35-bb9f-d3b438e16375", + "name": "Ocelot", + "description": "", + "order": [ + "a1c95935-ed18-d5dc-bcb8-a3db8ba1934f", + "ea0ed57a-2cb9-8acc-47dd-006b8db2f1b2", + "c4494401-3985-a5bf-71fb-6e4171384ac6", + "09af8dda-a9cb-20d2-5ee3-0a3023773a1a", + "e8825dc3-4137-99a7-0000-ef5786610dc3", + "fddfc4fa-5114-69e3-4744-203ed71a526b", + "c45d30d7-d9c4-fa05-8110-d6e769bb6ff9", + "4684c2fa-f38c-c193-5f55-bf563a1978c6", + "5f308240-79e3-cf74-7a6b-fe462f0d54f1", + "178f16da-c61b-c881-1c33-9d64a56851a4", + "26a08569-85f6-7f9a-726f-61be419c7a34" + ], + "folders": [], + "timestamp": 0, + "owner": "212120", + "public": false, + "requests": [ + { + "folder": null, + "id": "09af8dda-a9cb-20d2-5ee3-0a3023773a1a", + "name": "GET http://localhost:5000/comments?postId=1", + "dataMode": "params", + "data": null, + "rawModeData": null, + "descriptionFormat": "html", + "description": "", + "headers": "", + "method": "GET", + "pathVariables": {}, + "url": "http://localhost:5000/comments?postId=1", + "preRequestScript": null, + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "collectionId": "4dbde9fe-89f5-be35-bb9f-d3b438e16375" + }, + { + "id": "178f16da-c61b-c881-1c33-9d64a56851a4", + "headers": "Authorization: Bearer {{AccessToken}}\n", + "url": "http://localhost:5000/administration/configuration", + "preRequestScript": null, + "pathVariables": {}, + "method": "GET", + "data": null, + "dataMode": "params", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1508914722969, + "name": "GET http://localhost:5000/admin/configuration", + "description": "", + "collectionId": "4dbde9fe-89f5-be35-bb9f-d3b438e16375" + }, + { + "id": "26a08569-85f6-7f9a-726f-61be419c7a34", + "headers": "", + "url": "http://localhost:5000/administration/connect/token", + "preRequestScript": null, + "pathVariables": {}, + "method": "POST", + "data": [ + { + "key": "client_id", + "value": "raft", + "type": "text", + "enabled": true + }, + { + "key": "client_secret", + "value": "REALLYHARDPASSWORD", + "type": "text", + "enabled": true + }, + { + "key": "scope", + "value": "admin raft ", + "type": "text", + "enabled": true + }, + { + "key": "username", + "value": "admin", + "type": "text", + "enabled": false + }, + { + "key": "password", + "value": "secret", + "type": "text", + "enabled": false + }, + { + "key": "grant_type", + "value": "client_credentials", + "type": "text", + "enabled": true + } + ], + "dataMode": "params", + "tests": "var jsonData = JSON.parse(responseBody);\npostman.setGlobalVariable(\"AccessToken\", jsonData.access_token);\npostman.setGlobalVariable(\"RefreshToken\", jsonData.refresh_token);", + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1513240031907, + "name": "POST http://localhost:5000/admin/connect/token copy copy", + "description": "", + "collectionId": "4dbde9fe-89f5-be35-bb9f-d3b438e16375" + }, + { + "folder": null, + "id": "4684c2fa-f38c-c193-5f55-bf563a1978c6", + "name": "DELETE http://localhost:5000/posts/1", + "dataMode": "params", + "data": null, + "rawModeData": null, + "descriptionFormat": "html", + "description": "", + "headers": "", + "method": "DELETE", + "pathVariables": {}, + "url": "http://localhost:5000/posts/1", + "preRequestScript": null, + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "collectionId": "4dbde9fe-89f5-be35-bb9f-d3b438e16375" + }, + { + "id": "5f308240-79e3-cf74-7a6b-fe462f0d54f1", + "headers": "Authorization: Bearer {{AccessToken}}\n", + "url": "http://localhost:5000/administration/.well-known/openid-configuration", + "preRequestScript": null, + "pathVariables": {}, + "method": "GET", + "data": null, + "dataMode": "params", + "tests": null, + "currentHelper": "normal", + "helperAttributes": "{}", + "time": 1488038888813, + "name": "GET http://localhost:5000/admin/.well-known/openid-configuration", + "description": "", + "collectionId": "4dbde9fe-89f5-be35-bb9f-d3b438e16375", + "folder": null, + "rawModeData": null, + "descriptionFormat": null, + "queryParams": [], + "headerData": [ + { + "key": "Authorization", + "value": "Bearer {{AccessToken}}", + "description": "", + "enabled": true + } + ], + "pathVariableData": [] + }, + { + "id": "a1c95935-ed18-d5dc-bcb8-a3db8ba1934f", + "folder": null, + "name": "GET http://localhost:5000/posts", + "dataMode": "params", + "data": [ + { + "key": "client_id", + "value": "admin", + "type": "text", + "enabled": true + }, + { + "key": "client_secret", + "value": "secret", + "type": "text", + "enabled": true + }, + { + "key": "scope", + "value": "admin", + "type": "text", + "enabled": true + }, + { + "key": "username", + "value": "admin", + "type": "text", + "enabled": true + }, + { + "key": "password", + "value": "admin", + "type": "text", + "enabled": true + }, + { + "key": "grant_type", + "value": "password", + "type": "text", + "enabled": true + } + ], + "rawModeData": null, + "descriptionFormat": "html", + "description": "", + "headers": "", + "method": "POST", + "pathVariables": {}, + "url": "http://localhost:5000/admin/configuration", + "preRequestScript": null, + "tests": null, + "currentHelper": "normal", + "helperAttributes": "{}", + "collectionId": "4dbde9fe-89f5-be35-bb9f-d3b438e16375" + }, + { + "folder": null, + "id": "c4494401-3985-a5bf-71fb-6e4171384ac6", + "name": "GET http://localhost:5000/posts/1/comments", + "dataMode": "params", + "data": null, + "rawModeData": null, + "descriptionFormat": "html", + "description": "", + "headers": "", + "method": "GET", + "pathVariables": {}, + "url": "http://localhost:5000/posts/1/comments", + "preRequestScript": null, + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "collectionId": "4dbde9fe-89f5-be35-bb9f-d3b438e16375" + }, + { + "folder": null, + "id": "c45d30d7-d9c4-fa05-8110-d6e769bb6ff9", + "name": "PATCH http://localhost:5000/posts/1", + "dataMode": "raw", + "data": [], + "descriptionFormat": "html", + "description": "", + "headers": "", + "method": "PATCH", + "pathVariables": {}, + "url": "http://localhost:5000/posts/1", + "preRequestScript": null, + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "collectionId": "4dbde9fe-89f5-be35-bb9f-d3b438e16375", + "rawModeData": "{\n \"title\": \"gfdgsgsdgsdfgsdfgdfg\",\n}" + }, + { + "folder": null, + "id": "e8825dc3-4137-99a7-0000-ef5786610dc3", + "name": "POST http://localhost:5000/posts/1", + "dataMode": "raw", + "data": [], + "descriptionFormat": "html", + "description": "", + "headers": "", + "method": "POST", + "pathVariables": {}, + "url": "http://localhost:5000/posts", + "preRequestScript": null, + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "collectionId": "4dbde9fe-89f5-be35-bb9f-d3b438e16375", + "rawModeData": "{\n \"userId\": 1,\n \"title\": \"test\",\n \"body\": \"test\"\n}" + }, + { + "folder": null, + "id": "ea0ed57a-2cb9-8acc-47dd-006b8db2f1b2", + "name": "GET http://localhost:5000/posts/1", + "dataMode": "params", + "data": null, + "rawModeData": null, + "descriptionFormat": "html", + "description": "", + "headers": "", + "method": "GET", + "pathVariables": {}, + "url": "http://localhost:5000/posts/1", + "preRequestScript": null, + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "collectionId": "4dbde9fe-89f5-be35-bb9f-d3b438e16375" + }, + { + "folder": null, + "id": "fddfc4fa-5114-69e3-4744-203ed71a526b", + "name": "PUT http://localhost:5000/posts/1", + "dataMode": "raw", + "data": [], + "descriptionFormat": "html", + "description": "", + "headers": "", + "method": "PUT", + "pathVariables": {}, + "url": "http://localhost:5000/posts/1", + "preRequestScript": null, + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "collectionId": "4dbde9fe-89f5-be35-bb9f-d3b438e16375", + "rawModeData": "{\n \"userId\": 1,\n \"title\": \"test\",\n \"body\": \"test\"\n}" + } + ] } \ No newline at end of file diff --git a/samples/OcelotServiceFabric/.gitignore b/samples/OcelotServiceFabric/.gitignore new file mode 100644 index 00000000..733dbb07 --- /dev/null +++ b/samples/OcelotServiceFabric/.gitignore @@ -0,0 +1,269 @@ +## 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 + +# Service fabric +OcelotApplicationApiGatewayPkg/Code +OcelotApplication/OcelotApplicationApiGatewayPkg/Code/appsettings.json +OcelotApplication/OcelotApplicationApiGatewayPkg/Code/configuration.json +OcelotApplication/OcelotApplicationApiGatewayPkg/Code/runtimes/ +OcelotApplicationServicePkg/Code +OcelotApplication/OcelotApplicationApiGatewayPkg/Code/web.config +OcelotApplication/OcelotApplicationServicePkg/Code/runtimes/ +!entryPoint.cmd +!entryPoint.sh + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ + +# 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 +*.VC.db +*.VC.VC.opendb + +# 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 + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# 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 +# NuGet v3's project.json files produces more ignoreable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt + +# 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 + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# 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 +paket-files/ + +# FAKE - F# Make +.fake/ + +# JetBrains Rider +.idea/ +*.sln.iml + +# Dotnet generated files +*.dll +*.pdb +*.deps.json +*.runtimeconfig.json diff --git a/samples/OcelotServiceFabric/CONTRIBUTING.md b/samples/OcelotServiceFabric/CONTRIBUTING.md new file mode 100644 index 00000000..5577d2d7 --- /dev/null +++ b/samples/OcelotServiceFabric/CONTRIBUTING.md @@ -0,0 +1,11 @@ +# Contributing to Azure samples + +Thank you for your interest in contributing to Azure samples! + +## Ways to contribute + +You can contribute to [Azure samples](https://azure.microsoft.com/documentation/samples/) in a few different ways: + +- Submit feedback on [this sample page](https://azure.microsoft.com/documentation/samples/service-fabric-dotnet-web-reference-app/) whether it was helpful or not. +- Submit issues through [issue tracker](https://github.com/Azure-Samples/service-fabric-dotnet-web-reference-app/issues) on GitHub. We are actively monitoring the issues and improving our samples. +- If you wish to make code changes to samples, or contribute something new, please follow the [GitHub Forks / Pull requests model](https://help.github.com/articles/fork-a-repo/): Fork the sample repo, make the change and propose it back by submitting a pull request. diff --git a/samples/OcelotServiceFabric/LICENSE.md b/samples/OcelotServiceFabric/LICENSE.md new file mode 100644 index 00000000..70aed34a --- /dev/null +++ b/samples/OcelotServiceFabric/LICENSE.md @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2016 Azure Samples + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/samples/OcelotServiceFabric/OcelotApplication/ApplicationManifest.xml b/samples/OcelotServiceFabric/OcelotApplication/ApplicationManifest.xml new file mode 100644 index 00000000..d002e811 --- /dev/null +++ b/samples/OcelotServiceFabric/OcelotApplication/ApplicationManifest.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/samples/OcelotServiceFabric/OcelotApplication/OcelotApplicationApiGatewayPkg/Code/entryPoint.cmd b/samples/OcelotServiceFabric/OcelotApplication/OcelotApplicationApiGatewayPkg/Code/entryPoint.cmd new file mode 100644 index 00000000..c93389bd --- /dev/null +++ b/samples/OcelotServiceFabric/OcelotApplication/OcelotApplicationApiGatewayPkg/Code/entryPoint.cmd @@ -0,0 +1,2 @@ +dotnet %~dp0\OcelotApplicationApiGateway.dll +exit /b %errorlevel% \ No newline at end of file diff --git a/samples/OcelotServiceFabric/OcelotApplication/OcelotApplicationApiGatewayPkg/Code/entryPoint.sh b/samples/OcelotServiceFabric/OcelotApplication/OcelotApplicationApiGatewayPkg/Code/entryPoint.sh new file mode 100644 index 00000000..9cc67287 --- /dev/null +++ b/samples/OcelotServiceFabric/OcelotApplication/OcelotApplicationApiGatewayPkg/Code/entryPoint.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env bash +check_errs() +{ + # Function. Parameter 1 is the return code + if [ "${1}" -ne "0" ]; then + # make our script exit with the right error code. + exit ${1} + fi +} + +DIR=`dirname $0` + +echo 0x3f > /proc/self/coredump_filter + +source $DIR/dotnet-include.sh +dotnet $DIR/OcelotApplicationApiGateway.dll $@ +check_errs $? diff --git a/samples/OcelotServiceFabric/OcelotApplication/OcelotApplicationApiGatewayPkg/Config/Settings.xml b/samples/OcelotServiceFabric/OcelotApplication/OcelotApplicationApiGatewayPkg/Config/Settings.xml new file mode 100644 index 00000000..902c747a --- /dev/null +++ b/samples/OcelotServiceFabric/OcelotApplication/OcelotApplicationApiGatewayPkg/Config/Settings.xml @@ -0,0 +1,9 @@ + + + + + diff --git a/samples/OcelotServiceFabric/OcelotApplication/OcelotApplicationApiGatewayPkg/Config/_readme.txt b/samples/OcelotServiceFabric/OcelotApplication/OcelotApplicationApiGatewayPkg/Config/_readme.txt new file mode 100644 index 00000000..f5e5e287 --- /dev/null +++ b/samples/OcelotServiceFabric/OcelotApplication/OcelotApplicationApiGatewayPkg/Config/_readme.txt @@ -0,0 +1,12 @@ +contains a Settings.xml file, that can specify parameters for the service + +Configuration packages describe user-defined, application-overridable configuration settings (sections of key-value pairs) +required for running service replicas/instances of service types specified in the ser-vice manifest. The configuration settings +must be stored in Settings.xml in the config package folder. + +The service developer uses Service Fabric APIs to locate the package folders and read applica-tion-overridable configuration settings. +The service developer can also register callbacks that are in-voked when any of the configuration packages specified in the +service manifest are upgraded and re-reads new configuration settings inside that callback. + +This means that Service Fabric will not recycle EXEs and DLLHOSTs specified in the host and support packages when +configuration packages are up-graded. \ No newline at end of file diff --git a/samples/OcelotServiceFabric/OcelotApplication/OcelotApplicationApiGatewayPkg/Data/_readme.txt b/samples/OcelotServiceFabric/OcelotApplication/OcelotApplicationApiGatewayPkg/Data/_readme.txt new file mode 100644 index 00000000..de32b7d3 --- /dev/null +++ b/samples/OcelotServiceFabric/OcelotApplication/OcelotApplicationApiGatewayPkg/Data/_readme.txt @@ -0,0 +1,5 @@ +Data packages contain data files like custom dictionaries, +non-overridable configuration files, custom initialized data files, etc. + +Service Fabric will recycle all EXEs and DLLHOSTs specified in the host and support packages when any of the data packages +specified inside service manifest are upgraded. \ No newline at end of file diff --git a/samples/OcelotServiceFabric/OcelotApplication/OcelotApplicationApiGatewayPkg/ServiceManifest-Linux.xml b/samples/OcelotServiceFabric/OcelotApplication/OcelotApplicationApiGatewayPkg/ServiceManifest-Linux.xml new file mode 100644 index 00000000..c1990112 --- /dev/null +++ b/samples/OcelotServiceFabric/OcelotApplication/OcelotApplicationApiGatewayPkg/ServiceManifest-Linux.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + entryPoint.sh + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/samples/OcelotServiceFabric/OcelotApplication/OcelotApplicationApiGatewayPkg/ServiceManifest-Windows.xml b/samples/OcelotServiceFabric/OcelotApplication/OcelotApplicationApiGatewayPkg/ServiceManifest-Windows.xml new file mode 100644 index 00000000..a96730d3 --- /dev/null +++ b/samples/OcelotServiceFabric/OcelotApplication/OcelotApplicationApiGatewayPkg/ServiceManifest-Windows.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + entryPoint.cmd + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/samples/OcelotServiceFabric/OcelotApplication/OcelotApplicationApiGatewayPkg/ServiceManifest.xml b/samples/OcelotServiceFabric/OcelotApplication/OcelotApplicationApiGatewayPkg/ServiceManifest.xml new file mode 100644 index 00000000..a96730d3 --- /dev/null +++ b/samples/OcelotServiceFabric/OcelotApplication/OcelotApplicationApiGatewayPkg/ServiceManifest.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + entryPoint.cmd + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/samples/OcelotServiceFabric/OcelotApplication/OcelotApplicationServicePkg/Code/entryPoint.cmd b/samples/OcelotServiceFabric/OcelotApplication/OcelotApplicationServicePkg/Code/entryPoint.cmd new file mode 100644 index 00000000..9b71795b --- /dev/null +++ b/samples/OcelotServiceFabric/OcelotApplication/OcelotApplicationServicePkg/Code/entryPoint.cmd @@ -0,0 +1,2 @@ +dotnet %~dp0\OcelotApplicationService.dll +exit /b %errorlevel% \ No newline at end of file diff --git a/samples/OcelotServiceFabric/OcelotApplication/OcelotApplicationServicePkg/Code/entryPoint.sh b/samples/OcelotServiceFabric/OcelotApplication/OcelotApplicationServicePkg/Code/entryPoint.sh new file mode 100644 index 00000000..9e187faa --- /dev/null +++ b/samples/OcelotServiceFabric/OcelotApplication/OcelotApplicationServicePkg/Code/entryPoint.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash +check_errs() +{ + # Function. Parameter 1 is the return code + if [ "${1}" -ne "0" ]; then + # make our script exit with the right error code. + exit ${1} + fi +} + +DIR=`dirname $0` +source $DIR/dotnet-include.sh + +dotnet $DIR/OcelotApplicationService.dll $@ +check_errs $? diff --git a/samples/OcelotServiceFabric/OcelotApplication/OcelotApplicationServicePkg/Config/Settings.xml b/samples/OcelotServiceFabric/OcelotApplication/OcelotApplicationServicePkg/Config/Settings.xml new file mode 100644 index 00000000..902c747a --- /dev/null +++ b/samples/OcelotServiceFabric/OcelotApplication/OcelotApplicationServicePkg/Config/Settings.xml @@ -0,0 +1,9 @@ + + + + + diff --git a/samples/OcelotServiceFabric/OcelotApplication/OcelotApplicationServicePkg/Config/_readme.txt b/samples/OcelotServiceFabric/OcelotApplication/OcelotApplicationServicePkg/Config/_readme.txt new file mode 100644 index 00000000..f5e5e287 --- /dev/null +++ b/samples/OcelotServiceFabric/OcelotApplication/OcelotApplicationServicePkg/Config/_readme.txt @@ -0,0 +1,12 @@ +contains a Settings.xml file, that can specify parameters for the service + +Configuration packages describe user-defined, application-overridable configuration settings (sections of key-value pairs) +required for running service replicas/instances of service types specified in the ser-vice manifest. The configuration settings +must be stored in Settings.xml in the config package folder. + +The service developer uses Service Fabric APIs to locate the package folders and read applica-tion-overridable configuration settings. +The service developer can also register callbacks that are in-voked when any of the configuration packages specified in the +service manifest are upgraded and re-reads new configuration settings inside that callback. + +This means that Service Fabric will not recycle EXEs and DLLHOSTs specified in the host and support packages when +configuration packages are up-graded. \ No newline at end of file diff --git a/samples/OcelotServiceFabric/OcelotApplication/OcelotApplicationServicePkg/Data/_readme.txt b/samples/OcelotServiceFabric/OcelotApplication/OcelotApplicationServicePkg/Data/_readme.txt new file mode 100644 index 00000000..e51dae93 --- /dev/null +++ b/samples/OcelotServiceFabric/OcelotApplication/OcelotApplicationServicePkg/Data/_readme.txt @@ -0,0 +1,5 @@ +Data packages contain data files like custom dictionaries, +non-overridable configuration files, custom initialized data files, etc. + +Service Fabric will recycle all EXEs and DLLHOSTs specified in the host and support packages when any of the data packages +specified inside service manifest are upgraded. \ No newline at end of file diff --git a/samples/OcelotServiceFabric/OcelotApplication/OcelotApplicationServicePkg/ServiceManifest-Linux.xml b/samples/OcelotServiceFabric/OcelotApplication/OcelotApplicationServicePkg/ServiceManifest-Linux.xml new file mode 100644 index 00000000..e94651cb --- /dev/null +++ b/samples/OcelotServiceFabric/OcelotApplication/OcelotApplicationServicePkg/ServiceManifest-Linux.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + entryPoint.sh + + + + + + + + + + + + + + diff --git a/samples/OcelotServiceFabric/OcelotApplication/OcelotApplicationServicePkg/ServiceManifest-Windows.xml b/samples/OcelotServiceFabric/OcelotApplication/OcelotApplicationServicePkg/ServiceManifest-Windows.xml new file mode 100644 index 00000000..61c7ac80 --- /dev/null +++ b/samples/OcelotServiceFabric/OcelotApplication/OcelotApplicationServicePkg/ServiceManifest-Windows.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + entryPoint.cmd + + + + + + + + + + + + + + diff --git a/samples/OcelotServiceFabric/OcelotApplication/OcelotApplicationServicePkg/ServiceManifest.xml b/samples/OcelotServiceFabric/OcelotApplication/OcelotApplicationServicePkg/ServiceManifest.xml new file mode 100644 index 00000000..61c7ac80 --- /dev/null +++ b/samples/OcelotServiceFabric/OcelotApplication/OcelotApplicationServicePkg/ServiceManifest.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + entryPoint.cmd + + + + + + + + + + + + + + diff --git a/samples/OcelotServiceFabric/README.md b/samples/OcelotServiceFabric/README.md new file mode 100644 index 00000000..099348c6 --- /dev/null +++ b/samples/OcelotServiceFabric/README.md @@ -0,0 +1,51 @@ +--- +services: service-fabric +platforms: dotnet +author: raunakpandya edited by Tom Pallister for Ocelot +--- + +# Ocelot Service Fabric example + +This shows a service fabric cluster with Ocelot exposed over HTTP accessing services in the cluster via the naming service. If you want to try and use Ocelot with +Service Fabric I reccomend using this as a starting point. + +Ocelot does not support partitioned services (stateful & actors) at the moment. + +I have not tested this sample on Service Fabric hosted on Linux just a Windows dev cluster. This sample assumes a good understanding of Service Fabric. + +The rest of this document is from the Microsoft asp.net core service fabric getting started guide. + +# Getting started with Service Fabric with .NET Core + +This repository contains a set of simple sample projects to help you getting started with Service Fabric on Linux with .NET Core as the framework. As a pre requisite ensure you have the Service Fabric C# SDK installed on ubuntu box. Follow these instruction to [prepare your development environment on Linux][service-fabric-Linux-getting-started] + +### Folder Hierarchy +* src/ - Source of the application divided by different modules by sub-folders. +* <application package folder>/ - Service Fabric Application folder heirarchy. After compilation the executables are placed in code subfolders. +* build.sh - Script to build source on Linux shell. +* build.ps1 - PowerShell script to build source on Windows. +* install.sh - Script to install Application from Linux shell. +* install.ps1 - PowerShell script to install application from Windows. Before calling this script run Connect-ServiceFabricCluster localhost:19000 or however you prefer to connect. +* uninstall.sh - Script to uninstall application from Linux shell. +* uninstall.ps1 - PowerShell script to unintall application from Windows. +* dotnet-include.sh - Script to conditionally handle RHEL dotnet cli through scl(software collections) + +# Testing + +Once everything is up and running on your dev cluster visit http://localhost:31002/EquipmentInterfaces and you should see the following returned. + +```json +["value1","value2"] +``` + +If you get any errors please check the service fabric logs and let me know if you need help. + +## More information + +The [Service Fabric documentation][service-fabric-docs] includes a rich set of tutorials and conceptual articles, which serve as a good complement to the samples. + + + +[service-fabric-programming-models]: https://azure.microsoft.com/en-us/documentation/articles/service-fabric-choose-framework/ +[service-fabric-docs]: http://aka.ms/servicefabricdocs +[service-fabric-Linux-getting-started]: https://azure.microsoft.com/en-us/documentation/articles/service-fabric-get-started-linux/ diff --git a/samples/OcelotServiceFabric/build.bat b/samples/OcelotServiceFabric/build.bat new file mode 100644 index 00000000..9905715a --- /dev/null +++ b/samples/OcelotServiceFabric/build.bat @@ -0,0 +1,12 @@ +cd ./src/OcelotApplicationService/ +dotnet restore -s https://api.nuget.org/v3/index.json +dotnet build +dotnet publish -o ../../OcelotApplication/OcelotApplicationServicePkg/Code +cd ../../ + +cd ./src/OcelotApplicationApiGateway/ +dotnet restore -s https://api.nuget.org/v3/index.json +dotnet build +dotnet publish -o ../../OcelotApplication/OcelotApplicationApiGatewayPkg/Code +cd ../../ + diff --git a/samples/OcelotServiceFabric/build.sh b/samples/OcelotServiceFabric/build.sh new file mode 100644 index 00000000..a18f2a4a --- /dev/null +++ b/samples/OcelotServiceFabric/build.sh @@ -0,0 +1,15 @@ +#!/bin/bash +DIR=`dirname $0` +source $DIR/dotnet-include.sh + +cd $DIR/src/OcelotApplicationService/ +dotnet restore -s https://api.nuget.org/v3/index.json +dotnet build +dotnet publish -o ../../OcelotApplication/OcelotApplicationServicePkg/Code +cd - + +cd $DIR/src/OcelotApplicationApiGateway/ +dotnet restore -s https://api.nuget.org/v3/index.json +dotnet build +dotnet publish -o ../../OcelotApplication/OcelotApplicationApiGatewayPkg/Code +cd - diff --git a/samples/OcelotServiceFabric/dotnet-include.sh b/samples/OcelotServiceFabric/dotnet-include.sh new file mode 100644 index 00000000..a716f3d8 --- /dev/null +++ b/samples/OcelotServiceFabric/dotnet-include.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +. /etc/os-release +linuxDistrib=$ID +if [ $linuxDistrib = "rhel" ]; then + source scl_source enable rh-dotnet20 + exitCode=$? + if [ $exitCode != 0 ]; then + echo "Failed: source scl_source enable rh-dotnet20 : ExitCode: $exitCode" + exit $exitCode + fi +fi diff --git a/samples/OcelotServiceFabric/install.ps1 b/samples/OcelotServiceFabric/install.ps1 new file mode 100644 index 00000000..662c59e3 --- /dev/null +++ b/samples/OcelotServiceFabric/install.ps1 @@ -0,0 +1,20 @@ +$AppPath = "$PSScriptRoot\OcelotApplication" +$sdkInstallPath = (Get-ItemProperty 'HKLM:\Software\Microsoft\Service Fabric SDK').FabricSDKInstallPath +$sfSdkPsModulePath = $sdkInstallPath + "Tools\PSModule\ServiceFabricSDK" +Import-Module $sfSdkPsModulePath\ServiceFabricSDK.psm1 + +$StatefulServiceManifestlocation = $AppPath + "\OcelotApplicationServicePkg\" +$StatefulServiceManifestlocationLinux = $StatefulServiceManifestlocation + "\ServiceManifest-Linux.xml" +$StatefulServiceManifestlocationWindows = $StatefulServiceManifestlocation + "\ServiceManifest-Windows.xml" +$StatefulServiceManifestlocationFinal= $StatefulServiceManifestlocation + "ServiceManifest.xml" +Copy-Item -Path $StatefulServiceManifestlocationWindows -Destination $StatefulServiceManifestlocationFinal -Force + +$WebServiceManifestlocation = $AppPath + "\OcelotApplicationApiGatewayPkg\" +$WebServiceManifestlocationLinux = $WebServiceManifestlocation + "\ServiceManifest-Linux.xml" +$WebServiceManifestlocationWindows = $WebServiceManifestlocation + "\ServiceManifest-Windows.xml" +$WebServiceManifestlocationFinal= $WebServiceManifestlocation + "ServiceManifest.xml" +Copy-Item -Path $WebServiceManifestlocationWindows -Destination $WebServiceManifestlocationFinal -Force + +Copy-ServiceFabricApplicationPackage -ApplicationPackagePath $AppPath -ApplicationPackagePathInImageStore OcelotServiceApplicationType -ImageStoreConnectionString (Get-ImageStoreConnectionStringFromClusterManifest(Get-ServiceFabricClusterManifest)) -TimeoutSec 1800 +Register-ServiceFabricApplicationType OcelotServiceApplicationType +New-ServiceFabricApplication fabric:/OcelotServiceApplication OcelotServiceApplicationType 1.0.0 \ No newline at end of file diff --git a/samples/OcelotServiceFabric/install.sh b/samples/OcelotServiceFabric/install.sh new file mode 100644 index 00000000..e8245579 --- /dev/null +++ b/samples/OcelotServiceFabric/install.sh @@ -0,0 +1,22 @@ +#!/bin/bash +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" + +appPkg="$DIR/OcelotServiceApplication" + +WebServiceManifestlocation="$appPkg/OcelotApplicationApiGatewayPkg" +WebServiceManifestlocationLinux="$WebServiceManifestlocation/ServiceManifest-Linux.xml" +WebServiceManifestlocationWindows="$WebServiceManifestlocation/ServiceManifest-Windows.xml" +WebServiceManifestlocation="$WebServiceManifestlocation/ServiceManifest.xml" +cp $WebServiceManifestlocationLinux $WebServiceManifestlocation + + +StatefulServiceManifestlocation="$appPkg/OcelotApplicationServicePkg" +StatefulServiceManifestlocationLinux="$StatefulServiceManifestlocation/ServiceManifest-Linux.xml" +StatefulServiceManifestlocationWindows="$StatefulServiceManifestlocation/ServiceManifest-Windows.xml" +StatefulServiceManifestlocation="$StatefulServiceManifestlocation/ServiceManifest.xml" +cp $StatefulServiceManifestlocationLinux $StatefulServiceManifestlocation +cp dotnet-include.sh ./OcelotServiceApplication/OcelotApplicationServicePkg/Code +cp dotnet-include.sh ./OcelotServiceApplication/OcelotApplicationApiGatewayPkg/Code +sfctl application upload --path OcelotServiceApplication --show-progress +sfctl application provision --application-type-build-path OcelotServiceApplication +sfctl application create --app-name fabric:/OcelotServiceApplication --app-type OcelotServiceApplicationType --app-version 1.0.0 diff --git a/samples/OcelotServiceFabric/src/OcelotApplicationApiGateway/OcelotApplicationApiGateway.cs b/samples/OcelotServiceFabric/src/OcelotApplicationApiGateway/OcelotApplicationApiGateway.cs new file mode 100644 index 00000000..28ea7abb --- /dev/null +++ b/samples/OcelotServiceFabric/src/OcelotApplicationApiGateway/OcelotApplicationApiGateway.cs @@ -0,0 +1,31 @@ +// ------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. +// ------------------------------------------------------------ + +namespace OcelotApplicationApiGateway +{ + using System.Fabric; + using Microsoft.ServiceFabric.Services.Communication.Runtime; + using Microsoft.ServiceFabric.Services.Runtime; + using System.Collections.Generic; + + /// Service that handles front-end web requests and acts as a proxy to the back-end data for the UI web page. + /// It is a stateless service that hosts a Web API application on OWIN. + internal sealed class OcelotServiceWebService : StatelessService + { + public OcelotServiceWebService(StatelessServiceContext context) + : base(context) + { } + + protected override IEnumerable CreateServiceInstanceListeners() + { + return new[] + { + new ServiceInstanceListener( + initparams => new WebCommunicationListener(string.Empty, initparams), + "OcelotServiceWebListener") + }; + } + } +} \ No newline at end of file diff --git a/samples/OcelotServiceFabric/src/OcelotApplicationApiGateway/OcelotApplicationApiGateway.csproj b/samples/OcelotServiceFabric/src/OcelotApplicationApiGateway/OcelotApplicationApiGateway.csproj new file mode 100644 index 00000000..1ff69c09 --- /dev/null +++ b/samples/OcelotServiceFabric/src/OcelotApplicationApiGateway/OcelotApplicationApiGateway.csproj @@ -0,0 +1,22 @@ + + + Stateless Web Service for Stateful OcelotApplicationApiGateway App + + netcoreapp2.0 + OcelotApplicationApiGateway + Exe + OcelotApplicationApiGateway + + + + PreserveNewest + + + + + + + + + + \ No newline at end of file diff --git a/samples/OcelotServiceFabric/src/OcelotApplicationApiGateway/Program.cs b/samples/OcelotServiceFabric/src/OcelotApplicationApiGateway/Program.cs new file mode 100644 index 00000000..7da30a50 --- /dev/null +++ b/samples/OcelotServiceFabric/src/OcelotApplicationApiGateway/Program.cs @@ -0,0 +1,51 @@ +// ------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. +// ------------------------------------------------------------ + +namespace OcelotApplicationApiGateway + +{ + using System; + using System.Fabric; + using System.Threading; + using Microsoft.ServiceFabric.Services.Runtime; + using System.Diagnostics.Tracing; + + + /// + /// The service host is the executable that hosts the Service instances. + /// + public class Program + { + public static void Main(string[] args) + { + // Create Service Fabric runtime and register the service type. + try + { + + //Creating a new event listener to redirect the traces to a file + ServiceEventListener listener = new ServiceEventListener("OcelotApplicationApiGateway"); + listener.EnableEvents(ServiceEventSource.Current, EventLevel.LogAlways, EventKeywords.All); + + // The ServiceManifest.XML file defines one or more service type names. + // Registering a service maps a service type name to a .NET type. + // When Service Fabric creates an instance of this service type, + // an instance of the class is created in this host process. + ServiceRuntime + .RegisterServiceAsync("OcelotApplicationApiGatewayType", context => new OcelotServiceWebService (context)) + .GetAwaiter() + .GetResult(); + + + // Prevents this host process from terminating so services keep running. + Thread.Sleep(Timeout.Infinite); + } + catch (Exception ex) + { + ServiceEventSource.Current.ServiceHostInitializationFailed(ex); + throw ex; + } + } + } +} \ No newline at end of file diff --git a/samples/OcelotServiceFabric/src/OcelotApplicationApiGateway/Properties/launchSettings.json b/samples/OcelotServiceFabric/src/OcelotApplicationApiGateway/Properties/launchSettings.json new file mode 100644 index 00000000..e28c3315 --- /dev/null +++ b/samples/OcelotServiceFabric/src/OcelotApplicationApiGateway/Properties/launchSettings.json @@ -0,0 +1,27 @@ +{ + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:36034/", + "sslPort": 0 + } + }, + "profiles": { + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "OcelotApplicationApiGateway": { + "commandName": "Project", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "applicationUrl": "http://localhost:36035/" + } + } +} \ No newline at end of file diff --git a/samples/OcelotServiceFabric/src/OcelotApplicationApiGateway/ServiceEventListener.cs b/samples/OcelotServiceFabric/src/OcelotApplicationApiGateway/ServiceEventListener.cs new file mode 100644 index 00000000..555f9fde --- /dev/null +++ b/samples/OcelotServiceFabric/src/OcelotApplicationApiGateway/ServiceEventListener.cs @@ -0,0 +1,94 @@ +// ------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. +// ------------------------------------------------------------ + +namespace OcelotApplicationApiGateway +{ + using System; + using System.IO; + using System.Linq; + using System.Diagnostics.Tracing; + using System.Fabric; + using System.Fabric.Common; + using System.Fabric.Common.Tracing; + using Microsoft.ServiceFabric.Services.Runtime; + using System.Globalization; + using System.Text; + + /// + /// ServiceEventListener is a class which listens to the eventsources registered and redirects the traces to a file + /// Note that this class serves as a template to EventListener class and redirects the logs to /tmp/{appnameyyyyMMddHHmmssffff}. + /// You can extend the functionality by writing your code to implement rolling logs for the logs written through this class. + /// You can also write your custom listener class and handle the registered evestsources accordingly. + /// + internal class ServiceEventListener : EventListener + { + private string fileName; + private string filepath = Path.GetTempPath(); + + public ServiceEventListener(string appName) + { + this.fileName = appName + DateTime.Now.ToString("yyyyMMddHHmmssffff"); + } + + /// + /// We override this method to get a callback on every event we subscribed to with EnableEvents + /// + /// The event arguments that describe the event. + protected override void OnEventWritten(EventWrittenEventArgs eventData) + { + using (StreamWriter writer = new StreamWriter( new FileStream(filepath + fileName, FileMode.Append))) + { + // report all event information + writer.Write(" {0} ", Write(eventData.Task.ToString(), + eventData.EventName, + eventData.EventId.ToString(), + eventData.Level)); + + if (eventData.Message != null) + { + writer.WriteLine(string.Format(CultureInfo.InvariantCulture, eventData.Message, eventData.Payload.ToArray())); + } + } + } + + private static String Write(string taskName, string eventName, string id, EventLevel level) + { + StringBuilder output = new StringBuilder(); + + DateTime now = DateTime.UtcNow; + output.Append(now.ToString("yyyy/MM/dd-HH:mm:ss.fff", CultureInfo.InvariantCulture)); + output.Append(','); + output.Append(ConvertLevelToString(level)); + output.Append(','); + output.Append(taskName); + + if (!string.IsNullOrEmpty(eventName)) + { + output.Append('.'); + output.Append(eventName); + } + + if (!string.IsNullOrEmpty(id)) + { + output.Append('@'); + output.Append(id); + } + + output.Append(','); + return output.ToString(); + } + + private static string ConvertLevelToString(EventLevel level) + { + switch (level) + { + case EventLevel.Informational: + return "Info"; + default: + return level.ToString(); + } + } + } +} \ No newline at end of file diff --git a/samples/OcelotServiceFabric/src/OcelotApplicationApiGateway/ServiceEventSource.cs b/samples/OcelotServiceFabric/src/OcelotApplicationApiGateway/ServiceEventSource.cs new file mode 100644 index 00000000..c0579955 --- /dev/null +++ b/samples/OcelotServiceFabric/src/OcelotApplicationApiGateway/ServiceEventSource.cs @@ -0,0 +1,86 @@ +// ------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. +// ------------------------------------------------------------ + +namespace OcelotApplicationApiGateway +{ + using System; + using System.Diagnostics.Tracing; + using System.Fabric; + using Microsoft.ServiceFabric.Services.Runtime; + + /// + /// Implements methods for logging service related events. + /// + public class ServiceEventSource : EventSource + { + public static ServiceEventSource Current = new ServiceEventSource(); + + // Define an instance method for each event you want to record and apply an [Event] attribute to it. + // The method name is the name of the event. + // Pass any parameters you want to record with the event (only primitive integer types, DateTime, Guid & string are allowed). + // Each event method implementation should check whether the event source is enabled, and if it is, call WriteEvent() method to raise the event. + // The number and types of arguments passed to every event method must exactly match what is passed to WriteEvent(). + // Put [NonEvent] attribute on all methods that do not define an event. + // For more information see https://msdn.microsoft.com/en-us/library/system.diagnostics.tracing.eventsource.aspx + + [NonEvent] + public void Message(string message, params object[] args) + { + if (this.IsEnabled()) + { + var finalMessage = string.Format(message, args); + this.Message(finalMessage); + } + } + + private const int MessageEventId = 1; + + [Event(MessageEventId, Level = EventLevel.Informational, Message = "{0}")] + public void Message(string message) + { + if (this.IsEnabled()) + { + this.WriteEvent(MessageEventId, message); + } + } + + private const int ServiceTypeRegisteredEventId = 3; + + [Event(ServiceTypeRegisteredEventId, Level = EventLevel.Informational, Message = "Service host process {0} registered service type {1}")] + public void ServiceTypeRegistered(int hostProcessId, string serviceType) + { + this.WriteEvent(ServiceTypeRegisteredEventId, hostProcessId, serviceType); + } + + [NonEvent] + public void ServiceHostInitializationFailed(Exception e) + { + this.ServiceHostInitializationFailed(e.ToString()); + } + + private const int ServiceHostInitializationFailedEventId = 4; + + [Event(ServiceHostInitializationFailedEventId, Level = EventLevel.Error, Message = "Service host initialization failed: {0}")] + private void ServiceHostInitializationFailed(string exception) + { + this.WriteEvent(ServiceHostInitializationFailedEventId, exception); + } + + [NonEvent] + public void ServiceWebHostBuilderFailed(Exception e) + { + this.ServiceWebHostBuilderFailed(e.ToString()); + } + + private const int ServiceWebHostBuilderFailedEventId = 5; + + [Event(ServiceWebHostBuilderFailedEventId, Level = EventLevel.Error, Message = "Service Owin Web Host Builder Failed: {0}")] + private void ServiceWebHostBuilderFailed(string exception) + { + this.WriteEvent(ServiceWebHostBuilderFailedEventId, exception); + } + + } +} diff --git a/samples/OcelotServiceFabric/src/OcelotApplicationApiGateway/WebCommunicationListener.cs b/samples/OcelotServiceFabric/src/OcelotApplicationApiGateway/WebCommunicationListener.cs new file mode 100644 index 00000000..6685e11f --- /dev/null +++ b/samples/OcelotServiceFabric/src/OcelotApplicationApiGateway/WebCommunicationListener.cs @@ -0,0 +1,125 @@ +// ------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. +// ------------------------------------------------------------ + +namespace OcelotApplicationApiGateway +{ + using System; + using System.Fabric; + using System.Fabric.Description; + using System.Globalization; + using System.Threading; + using System.Threading.Tasks; + using Microsoft.AspNetCore.Hosting; + using Microsoft.ServiceFabric.Services.Communication.Runtime; + using Microsoft.Extensions.Logging; + using Microsoft.Extensions.Configuration; + using Microsoft.AspNetCore.Builder; + using Microsoft.Extensions.DependencyInjection; + using Ocelot.DependencyInjection; + using Ocelot.Middleware; + + public class WebCommunicationListener : ICommunicationListener + { + private readonly string appRoot; + private readonly ServiceContext serviceInitializationParameters; + private string listeningAddress; + private string publishAddress; + + // OWIN server handle. + private IWebHost webHost; + + public WebCommunicationListener(string appRoot, ServiceContext serviceInitializationParameters) + { + this.appRoot = appRoot; + this.serviceInitializationParameters = serviceInitializationParameters; + } + + public Task OpenAsync(CancellationToken cancellationToken) + { + ServiceEventSource.Current.Message("Initialize"); + + EndpointResourceDescription serviceEndpoint = this.serviceInitializationParameters.CodePackageActivationContext.GetEndpoint("WebEndpoint"); + int port = serviceEndpoint.Port; + + this.listeningAddress = string.Format( + CultureInfo.InvariantCulture, + "http://+:{0}/{1}", + port, + string.IsNullOrWhiteSpace(this.appRoot) + ? string.Empty + : this.appRoot.TrimEnd('/') + '/'); + + this.publishAddress = this.listeningAddress.Replace("+", FabricRuntime.GetNodeContext().IPAddressOrFQDN); + + ServiceEventSource.Current.Message("Starting web server on {0}", this.listeningAddress); + + try + { + this.webHost = new WebHostBuilder() + .UseKestrel() + //.UseStartup() + .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("configuration.json") + .AddEnvironmentVariables(); + }) + .ConfigureLogging((hostingContext, logging) => + { + logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging")); + logging.AddConsole(); + }) + .ConfigureServices(s => { + s.AddOcelot(); + }) + .Configure(a => { + a.UseOcelot().Wait(); + }) + .Build(); + + this.webHost.Start(); + } + catch (Exception ex) + { + ServiceEventSource.Current.ServiceWebHostBuilderFailed(ex); + } + + return Task.FromResult(this.publishAddress); + } + + public Task CloseAsync(CancellationToken cancellationToken) + { + this.StopAll(); + return Task.FromResult(true); + } + + public void Abort() + { + this.StopAll(); + } + + /// + /// Stops, cancels, and disposes everything. + /// + private void StopAll() + { + try + { + if (this.webHost != null) + { + ServiceEventSource.Current.Message("Stopping web server."); + this.webHost.Dispose(); + } + } + catch (ObjectDisposedException) + { + } + } + } +} diff --git a/samples/OcelotServiceFabric/src/OcelotApplicationApiGateway/appsettings.json b/samples/OcelotServiceFabric/src/OcelotApplicationApiGateway/appsettings.json new file mode 100644 index 00000000..51d92491 --- /dev/null +++ b/samples/OcelotServiceFabric/src/OcelotApplicationApiGateway/appsettings.json @@ -0,0 +1,10 @@ +{ + "Logging": { + "IncludeScopes": false, + "LogLevel": { + "Default": "Trace", + "System": "Information", + "Microsoft": "Information" + } + } +} diff --git a/samples/OcelotServiceFabric/src/OcelotApplicationApiGateway/configuration.json b/samples/OcelotServiceFabric/src/OcelotApplicationApiGateway/configuration.json new file mode 100644 index 00000000..dce3d55e --- /dev/null +++ b/samples/OcelotServiceFabric/src/OcelotApplicationApiGateway/configuration.json @@ -0,0 +1,22 @@ +{ + "ReRoutes": [ + { + "DownstreamPathTemplate": "/api/values", + "UpstreamPathTemplate": "/EquipmentInterfaces", + "UpstreamHttpMethod": [ + "Get" + ], + "DownstreamScheme": "http", + "ServiceName": "OcelotServiceApplication/OcelotApplicationService", + "UseServiceDiscovery" : true + } + ], + "GlobalConfiguration": { + "RequestIdKey": "OcRequestId", + "ServiceDiscoveryProvider": { + "Host": "localhost", + "Port": 19081, + "Type": "ServiceFabric" + } + } +} diff --git a/samples/OcelotServiceFabric/src/OcelotApplicationService/ApiGateway.cs b/samples/OcelotServiceFabric/src/OcelotApplicationService/ApiGateway.cs new file mode 100644 index 00000000..8c090885 --- /dev/null +++ b/samples/OcelotServiceFabric/src/OcelotApplicationService/ApiGateway.cs @@ -0,0 +1,59 @@ +using System; +using System.Collections.Generic; +using System.Fabric; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.ServiceFabric.Services.Communication.AspNetCore; +using Microsoft.ServiceFabric.Services.Communication.Runtime; +using Microsoft.ServiceFabric.Services.Runtime; +using Microsoft.Extensions.Logging; + +namespace OcelotApplicationService +{ + /// + /// The FabricRuntime creates an instance of this class for each service type instance. + /// + internal sealed class ApiGateway : StatelessService + { + public ApiGateway(StatelessServiceContext context) + : base(context) + { } + + /// + /// Optional override to create listeners (like tcp, http) for this service instance. + /// + /// The collection of listeners. + protected override IEnumerable CreateServiceInstanceListeners() + { + return new ServiceInstanceListener[] + { + new ServiceInstanceListener(serviceContext => + new KestrelCommunicationListener(serviceContext, "ServiceEndpoint", (url, listener) => + { + Console.WriteLine($"Starting Kestrel on {url}"); + ServiceEventSource.Current.ServiceMessage(serviceContext, $"Starting Kestrel on {url}"); + + return new WebHostBuilder() + .UseKestrel() + .ConfigureServices( + services => services + .AddSingleton(serviceContext)) + .UseContentRoot(Directory.GetCurrentDirectory()) + .UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.UseUniqueServiceUrl) + .UseStartup() + .UseUrls(url) + .ConfigureLogging((hostingContext, logging) => + { + logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging")); + logging.AddConsole(); + }) + .Build(); + })) + }; + } + } +} diff --git a/samples/OcelotServiceFabric/src/OcelotApplicationService/Controllers/ValuesController.cs b/samples/OcelotServiceFabric/src/OcelotApplicationService/Controllers/ValuesController.cs new file mode 100644 index 00000000..13e56999 --- /dev/null +++ b/samples/OcelotServiceFabric/src/OcelotApplicationService/Controllers/ValuesController.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; + +namespace OcelotApplicationService.Controllers +{ + [Route("api/[controller]")] + public class ValuesController : Controller + { + // GET api/values + [HttpGet] + public IEnumerable Get() + { + return new string[] { "value1", "value2" }; + } + + // GET api/values/5 + [HttpGet("{id}")] + public string Get(int id) + { + return "value"; + } + + // POST api/values + [HttpPost] + public void Post([FromBody]string value) + { + } + + // PUT api/values/5 + [HttpPut("{id}")] + public void Put(int id, [FromBody]string value) + { + } + + // DELETE api/values/5 + [HttpDelete("{id}")] + public void Delete(int id) + { + } + } +} diff --git a/samples/OcelotServiceFabric/src/OcelotApplicationService/OcelotApplicationService.csproj b/samples/OcelotServiceFabric/src/OcelotApplicationService/OcelotApplicationService.csproj new file mode 100644 index 00000000..34991440 --- /dev/null +++ b/samples/OcelotServiceFabric/src/OcelotApplicationService/OcelotApplicationService.csproj @@ -0,0 +1,21 @@ + + + Stateless Service Application + + Exe + netcoreapp2.0 + OcelotApplicationService + OcelotApplicationService + $(PackageTargetFallback) + + + + + + + + + + + + \ No newline at end of file diff --git a/samples/OcelotServiceFabric/src/OcelotApplicationService/Program.cs b/samples/OcelotServiceFabric/src/OcelotApplicationService/Program.cs new file mode 100644 index 00000000..b9d7d72e --- /dev/null +++ b/samples/OcelotServiceFabric/src/OcelotApplicationService/Program.cs @@ -0,0 +1,38 @@ +using Microsoft.ServiceFabric.Services.Runtime; +using System; +using System.Diagnostics; +using System.Threading; +using System.Threading.Tasks; + +namespace OcelotApplicationService +{ + internal static class Program + { + /// + /// This is the entry point of the service host process. + /// + private static void Main() + { + try + { + // The ServiceManifest.XML file defines one or more service type names. + // Registering a service maps a service type name to a .NET type. + // When Service Fabric creates an instance of this service type, + // an instance of the class is created in this host process. + + ServiceRuntime.RegisterServiceAsync("OcelotApplicationServiceType", + context => new ApiGateway(context)).GetAwaiter().GetResult(); + + ServiceEventSource.Current.ServiceTypeRegistered(Process.GetCurrentProcess().Id, typeof(ApiGateway).Name); + + // Prevents this host process from terminating so services keeps running. + Thread.Sleep(Timeout.Infinite); + } + catch (Exception e) + { + ServiceEventSource.Current.ServiceHostInitializationFailed(e.ToString()); + throw; + } + } + } +} diff --git a/samples/OcelotServiceFabric/src/OcelotApplicationService/ServiceEventSource.cs b/samples/OcelotServiceFabric/src/OcelotApplicationService/ServiceEventSource.cs new file mode 100644 index 00000000..13e2df12 --- /dev/null +++ b/samples/OcelotServiceFabric/src/OcelotApplicationService/ServiceEventSource.cs @@ -0,0 +1,189 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.Tracing; +using System.Fabric; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace OcelotApplicationService +{ + [EventSource(Name = "MyCompany-ServiceOcelotApplication-OcelotService")] + internal sealed class ServiceEventSource : EventSource + { + public static readonly ServiceEventSource Current = new ServiceEventSource(); + + static ServiceEventSource() + { + // A workaround for the problem where ETW activities do not get tracked until Tasks infrastructure is initialized. + // This problem will be fixed in .NET Framework 4.6.2. + Task.Run(() => { }); + } + + // Instance constructor is private to enforce singleton semantics + private ServiceEventSource() : base() { } + + #region Keywords + // Event keywords can be used to categorize events. + // Each keyword is a bit flag. A single event can be associated with multiple keywords (via EventAttribute.Keywords property). + // Keywords must be defined as a public class named 'Keywords' inside EventSource that uses them. + public static class Keywords + { + public const EventKeywords Requests = (EventKeywords)0x1L; + public const EventKeywords ServiceInitialization = (EventKeywords)0x2L; + } + #endregion + + #region Events + // Define an instance method for each event you want to record and apply an [Event] attribute to it. + // The method name is the name of the event. + // Pass any parameters you want to record with the event (only primitive integer types, DateTime, Guid & string are allowed). + // Each event method implementation should check whether the event source is enabled, and if it is, call WriteEvent() method to raise the event. + // The number and types of arguments passed to every event method must exactly match what is passed to WriteEvent(). + // Put [NonEvent] attribute on all methods that do not define an event. + // For more information see https://msdn.microsoft.com/en-us/library/system.diagnostics.tracing.eventsource.aspx + + [NonEvent] + public void Message(string message, params object[] args) + { + if (this.IsEnabled()) + { + string finalMessage = string.Format(message, args); + Message(finalMessage); + } + } + + private const int MessageEventId = 1; + [Event(MessageEventId, Level = EventLevel.Informational, Message = "{0}")] + public void Message(string message) + { + if (this.IsEnabled()) + { + WriteEvent(MessageEventId, message); + } + } + + [NonEvent] + public void ServiceMessage(ServiceContext serviceContext, string message, params object[] args) + { + if (this.IsEnabled()) + { + + string finalMessage = string.Format(message, args); + ServiceMessage( + serviceContext.ServiceName.ToString(), + serviceContext.ServiceTypeName, + GetReplicaOrInstanceId(serviceContext), + serviceContext.PartitionId, + serviceContext.CodePackageActivationContext.ApplicationName, + serviceContext.CodePackageActivationContext.ApplicationTypeName, + serviceContext.NodeContext.NodeName, + finalMessage); + } + } + + // For very high-frequency events it might be advantageous to raise events using WriteEventCore API. + // This results in more efficient parameter handling, but requires explicit allocation of EventData structure and unsafe code. + // To enable this code path, define UNSAFE conditional compilation symbol and turn on unsafe code support in project properties. + private const int ServiceMessageEventId = 2; + [Event(ServiceMessageEventId, Level = EventLevel.Informational, Message = "{7}")] + private +#if UNSAFE + unsafe +#endif + void ServiceMessage( + string serviceName, + string serviceTypeName, + long replicaOrInstanceId, + Guid partitionId, + string applicationName, + string applicationTypeName, + string nodeName, + string message) + { +#if !UNSAFE + WriteEvent(ServiceMessageEventId, serviceName, serviceTypeName, replicaOrInstanceId, partitionId, applicationName, applicationTypeName, nodeName, message); +#else + const int numArgs = 8; + fixed (char* pServiceName = serviceName, pServiceTypeName = serviceTypeName, pApplicationName = applicationName, pApplicationTypeName = applicationTypeName, pNodeName = nodeName, pMessage = message) + { + EventData* eventData = stackalloc EventData[numArgs]; + eventData[0] = new EventData { DataPointer = (IntPtr) pServiceName, Size = SizeInBytes(serviceName) }; + eventData[1] = new EventData { DataPointer = (IntPtr) pServiceTypeName, Size = SizeInBytes(serviceTypeName) }; + eventData[2] = new EventData { DataPointer = (IntPtr) (&replicaOrInstanceId), Size = sizeof(long) }; + eventData[3] = new EventData { DataPointer = (IntPtr) (&partitionId), Size = sizeof(Guid) }; + eventData[4] = new EventData { DataPointer = (IntPtr) pApplicationName, Size = SizeInBytes(applicationName) }; + eventData[5] = new EventData { DataPointer = (IntPtr) pApplicationTypeName, Size = SizeInBytes(applicationTypeName) }; + eventData[6] = new EventData { DataPointer = (IntPtr) pNodeName, Size = SizeInBytes(nodeName) }; + eventData[7] = new EventData { DataPointer = (IntPtr) pMessage, Size = SizeInBytes(message) }; + + WriteEventCore(ServiceMessageEventId, numArgs, eventData); + } +#endif + } + + private const int ServiceTypeRegisteredEventId = 3; + [Event(ServiceTypeRegisteredEventId, Level = EventLevel.Informational, Message = "Service host process {0} registered service type {1}", Keywords = Keywords.ServiceInitialization)] + public void ServiceTypeRegistered(int hostProcessId, string serviceType) + { + WriteEvent(ServiceTypeRegisteredEventId, hostProcessId, serviceType); + } + + private const int ServiceHostInitializationFailedEventId = 4; + [Event(ServiceHostInitializationFailedEventId, Level = EventLevel.Error, Message = "Service host initialization failed", Keywords = Keywords.ServiceInitialization)] + public void ServiceHostInitializationFailed(string exception) + { + WriteEvent(ServiceHostInitializationFailedEventId, exception); + } + + // A pair of events sharing the same name prefix with a "Start"/"Stop" suffix implicitly marks boundaries of an event tracing activity. + // These activities can be automatically picked up by debugging and profiling tools, which can compute their execution time, child activities, + // and other statistics. + private const int ServiceRequestStartEventId = 5; + [Event(ServiceRequestStartEventId, Level = EventLevel.Informational, Message = "Service request '{0}' started", Keywords = Keywords.Requests)] + public void ServiceRequestStart(string requestTypeName) + { + WriteEvent(ServiceRequestStartEventId, requestTypeName); + } + + private const int ServiceRequestStopEventId = 6; + [Event(ServiceRequestStopEventId, Level = EventLevel.Informational, Message = "Service request '{0}' finished", Keywords = Keywords.Requests)] + public void ServiceRequestStop(string requestTypeName, string exception = "") + { + WriteEvent(ServiceRequestStopEventId, requestTypeName, exception); + } + #endregion + + #region Private methods + private static long GetReplicaOrInstanceId(ServiceContext context) + { + StatelessServiceContext stateless = context as StatelessServiceContext; + if (stateless != null) + { + return stateless.InstanceId; + } + + StatefulServiceContext stateful = context as StatefulServiceContext; + if (stateful != null) + { + return stateful.ReplicaId; + } + + throw new NotSupportedException("Context type not supported."); + } +#if UNSAFE + private int SizeInBytes(string s) + { + if (s == null) + { + return 0; + } + else + { + return (s.Length + 1) * sizeof(char); + } + } +#endif + #endregion + } +} diff --git a/samples/OcelotServiceFabric/src/OcelotApplicationService/Startup.cs b/samples/OcelotServiceFabric/src/OcelotApplicationService/Startup.cs new file mode 100644 index 00000000..022fcb0e --- /dev/null +++ b/samples/OcelotServiceFabric/src/OcelotApplicationService/Startup.cs @@ -0,0 +1,40 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; + +namespace OcelotApplicationService +{ + public class Startup + { + public Startup(IConfiguration configuration) + { + Configuration = configuration; + } + + public IConfiguration Configuration { get; } + + // This method gets called by the runtime. Use this method to add services to the container. + public void ConfigureServices(IServiceCollection services) + { + services.AddMvc(); + } + + // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. + public void Configure(IApplicationBuilder app, IHostingEnvironment env) + { + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + } + + app.UseMvc(); + } + } +} diff --git a/samples/OcelotServiceFabric/src/global.json b/samples/OcelotServiceFabric/src/global.json new file mode 100644 index 00000000..8288598a --- /dev/null +++ b/samples/OcelotServiceFabric/src/global.json @@ -0,0 +1,6 @@ +{ + "projects": [ "../"], + "sdk": { + "version": "2.1.4" + } +} \ No newline at end of file diff --git a/samples/OcelotServiceFabric/uninstall.ps1 b/samples/OcelotServiceFabric/uninstall.ps1 new file mode 100644 index 00000000..032ee0e8 --- /dev/null +++ b/samples/OcelotServiceFabric/uninstall.ps1 @@ -0,0 +1,2 @@ +Remove-ServiceFabricApplication fabric:/OcelotServiceApplication +Unregister-ServiceFabricApplicationType OcelotServiceApplicationType 1.0.0 \ No newline at end of file diff --git a/samples/OcelotServiceFabric/uninstall.sh b/samples/OcelotServiceFabric/uninstall.sh new file mode 100644 index 00000000..45fc561c --- /dev/null +++ b/samples/OcelotServiceFabric/uninstall.sh @@ -0,0 +1,5 @@ +#!/bin/bash -x + +sfctl application delete --application-id OcelotServiceApplication +sfctl application unprovision --application-type-name OcelotServiceApplicationType --application-type-version 1.0.0 +sfctl store delete --content-path OcelotServiceApplication \ No newline at end of file diff --git a/src/Ocelot/Configuration/Builder/DownstreamReRouteBuilder.cs b/src/Ocelot/Configuration/Builder/DownstreamReRouteBuilder.cs index bc860424..0e7509b9 100644 --- a/src/Ocelot/Configuration/Builder/DownstreamReRouteBuilder.cs +++ b/src/Ocelot/Configuration/Builder/DownstreamReRouteBuilder.cs @@ -36,7 +36,6 @@ namespace Ocelot.Configuration.Builder private readonly List _downstreamAddresses; private string _upstreamHost; private string _key; - public DownstreamReRouteBuilder() { _downstreamAddresses = new List(); diff --git a/src/Ocelot/Configuration/Builder/ServiceProviderConfigurationBuilder.cs b/src/Ocelot/Configuration/Builder/ServiceProviderConfigurationBuilder.cs index 0999a47c..b1f4e832 100644 --- a/src/Ocelot/Configuration/Builder/ServiceProviderConfigurationBuilder.cs +++ b/src/Ocelot/Configuration/Builder/ServiceProviderConfigurationBuilder.cs @@ -4,6 +4,7 @@ namespace Ocelot.Configuration.Builder { private string _serviceDiscoveryProviderHost; private int _serviceDiscoveryProviderPort; + private string _type; public ServiceProviderConfigurationBuilder WithServiceDiscoveryProviderHost(string serviceDiscoveryProviderHost) { @@ -17,9 +18,15 @@ namespace Ocelot.Configuration.Builder return this; } + public ServiceProviderConfigurationBuilder WithServiceDiscoveryProviderType(string type) + { + _type = type; + return this; + } + public ServiceProviderConfiguration Build() { - return new ServiceProviderConfiguration(_serviceDiscoveryProviderHost,_serviceDiscoveryProviderPort); + return new ServiceProviderConfiguration(_type, _serviceDiscoveryProviderHost, _serviceDiscoveryProviderPort); } } -} \ No newline at end of file +} diff --git a/src/Ocelot/Configuration/Creator/ServiceProviderConfigurationCreator.cs b/src/Ocelot/Configuration/Creator/ServiceProviderConfigurationCreator.cs index cfc3e7c7..c104385a 100644 --- a/src/Ocelot/Configuration/Creator/ServiceProviderConfigurationCreator.cs +++ b/src/Ocelot/Configuration/Creator/ServiceProviderConfigurationCreator.cs @@ -7,12 +7,14 @@ namespace Ocelot.Configuration.Creator { public ServiceProviderConfiguration Create(FileGlobalConfiguration globalConfiguration) { + //todo log or return error here dont just default to something that wont work.. var serviceProviderPort = globalConfiguration?.ServiceDiscoveryProvider?.Port ?? 0; return new ServiceProviderConfigurationBuilder() - .WithServiceDiscoveryProviderHost(globalConfiguration?.ServiceDiscoveryProvider?.Host) - .WithServiceDiscoveryProviderPort(serviceProviderPort) - .Build(); + .WithServiceDiscoveryProviderHost(globalConfiguration?.ServiceDiscoveryProvider?.Host) + .WithServiceDiscoveryProviderPort(serviceProviderPort) + .WithServiceDiscoveryProviderType(globalConfiguration?.ServiceDiscoveryProvider?.Type) + .Build(); } } -} \ No newline at end of file +} diff --git a/src/Ocelot/Configuration/File/FileServiceDiscoveryProvider.cs b/src/Ocelot/Configuration/File/FileServiceDiscoveryProvider.cs index f9c370b1..203cc675 100644 --- a/src/Ocelot/Configuration/File/FileServiceDiscoveryProvider.cs +++ b/src/Ocelot/Configuration/File/FileServiceDiscoveryProvider.cs @@ -4,5 +4,6 @@ namespace Ocelot.Configuration.File { public string Host {get;set;} public int Port { get; set; } + public string Type { get; set; } } -} \ No newline at end of file +} diff --git a/src/Ocelot/Configuration/Repository/ConsulFileConfigurationRepository.cs b/src/Ocelot/Configuration/Repository/ConsulFileConfigurationRepository.cs index 91b4bd9d..13c128b9 100644 --- a/src/Ocelot/Configuration/Repository/ConsulFileConfigurationRepository.cs +++ b/src/Ocelot/Configuration/Repository/ConsulFileConfigurationRepository.cs @@ -18,8 +18,8 @@ namespace Ocelot.Configuration.Repository public ConsulFileConfigurationRepository(Cache.IOcelotCache cache, ServiceProviderConfiguration serviceProviderConfig) { - var consulHost = string.IsNullOrEmpty(serviceProviderConfig?.ServiceProviderHost) ? "localhost" : serviceProviderConfig?.ServiceProviderHost; - var consulPort = serviceProviderConfig?.ServiceProviderPort ?? 8500; + var consulHost = string.IsNullOrEmpty(serviceProviderConfig?.Host) ? "localhost" : serviceProviderConfig?.Host; + var consulPort = serviceProviderConfig?.Port ?? 8500; var configuration = new ConsulRegistryConfiguration(consulHost, consulPort, _ocelotConfiguration); _cache = cache; _consul = new ConsulClient(c => @@ -76,4 +76,4 @@ namespace Ocelot.Configuration.Repository return new ErrorResponse(new UnableToSetConfigInConsulError($"Unable to set FileConfiguration in consul, response status code from consul was {result.StatusCode}")); } } -} \ No newline at end of file +} diff --git a/src/Ocelot/Configuration/ServiceProviderConfiguraion.cs b/src/Ocelot/Configuration/ServiceProviderConfiguraion.cs index 272d2205..9df16ea2 100644 --- a/src/Ocelot/Configuration/ServiceProviderConfiguraion.cs +++ b/src/Ocelot/Configuration/ServiceProviderConfiguraion.cs @@ -2,13 +2,15 @@ { public class ServiceProviderConfiguration { - public ServiceProviderConfiguration(string serviceProviderHost, int serviceProviderPort) + public ServiceProviderConfiguration(string type, string host, int port) { - ServiceProviderHost = serviceProviderHost; - ServiceProviderPort = serviceProviderPort; + Host = host; + Port = port; + Type = type; } - public string ServiceProviderHost { get; private set; } - public int ServiceProviderPort { get; private set; } + public string Host { get; private set; } + public int Port { get; private set; } + public string Type { get; private set; } } -} \ No newline at end of file +} diff --git a/src/Ocelot/Configuration/Validator/FileConfigurationFluentValidator.cs b/src/Ocelot/Configuration/Validator/FileConfigurationFluentValidator.cs index 58da7c4f..d0c6de0e 100644 --- a/src/Ocelot/Configuration/Validator/FileConfigurationFluentValidator.cs +++ b/src/Ocelot/Configuration/Validator/FileConfigurationFluentValidator.cs @@ -30,7 +30,7 @@ namespace Ocelot.Configuration.Validator RuleForEach(configuration => configuration.Aggregates) .Must((config, aggregateReRoute) => AllReRoutesForAggregateExist(aggregateReRoute, config.ReRoutes)) - .WithMessage((config, aggregateReRoute) => $"ReRoutes for {nameof(aggregateReRoute)} {aggregateReRoute.UpstreamPathTemplate} either do not exist or do not have correct Key property"); + .WithMessage((config, aggregateReRoute) => $"ReRoutes for {nameof(aggregateReRoute)} {aggregateReRoute.UpstreamPathTemplate} either do not exist or do not have correct ServiceName property"); RuleForEach(configuration => configuration.Aggregates) .Must((config, aggregateReRoute) => DoesNotContainReRoutesWithSpecificRequestIdKeys(aggregateReRoute, config.ReRoutes)) diff --git a/src/Ocelot/DependencyInjection/OcelotBuilder.cs b/src/Ocelot/DependencyInjection/OcelotBuilder.cs index f4192713..ccd2a9be 100644 --- a/src/Ocelot/DependencyInjection/OcelotBuilder.cs +++ b/src/Ocelot/DependencyInjection/OcelotBuilder.cs @@ -99,7 +99,6 @@ namespace Ocelot.DependencyInjection _services.TryAddSingleton(); _services.TryAddSingleton(); _services.TryAddSingleton(); - _services.TryAddSingleton(); _services.TryAddSingleton(); _services.TryAddSingleton(); _services.TryAddSingleton(); diff --git a/src/Ocelot/DownstreamUrlCreator/IUrlBuilder.cs b/src/Ocelot/DownstreamUrlCreator/IUrlBuilder.cs index 19fa55a1..9975cec2 100644 --- a/src/Ocelot/DownstreamUrlCreator/IUrlBuilder.cs +++ b/src/Ocelot/DownstreamUrlCreator/IUrlBuilder.cs @@ -1,4 +1,5 @@ -using Ocelot.Responses; +/* +using Ocelot.Responses; using Ocelot.Values; namespace Ocelot.DownstreamUrlCreator @@ -8,3 +9,4 @@ namespace Ocelot.DownstreamUrlCreator Response Build(string downstreamPath, string downstreamScheme, ServiceHostAndPort downstreamHostAndPort); } } +*/ diff --git a/src/Ocelot/DownstreamUrlCreator/Middleware/DownstreamUrlCreatorMiddleware.cs b/src/Ocelot/DownstreamUrlCreator/Middleware/DownstreamUrlCreatorMiddleware.cs index 5b5e8346..dc02a20e 100644 --- a/src/Ocelot/DownstreamUrlCreator/Middleware/DownstreamUrlCreatorMiddleware.cs +++ b/src/Ocelot/DownstreamUrlCreator/Middleware/DownstreamUrlCreatorMiddleware.cs @@ -5,6 +5,7 @@ using Ocelot.Infrastructure.RequestData; using Ocelot.Logging; using Ocelot.Middleware; using System; +using System.Linq; using Ocelot.DownstreamRouteFinder.Middleware; namespace Ocelot.DownstreamUrlCreator.Middleware @@ -14,16 +15,13 @@ namespace Ocelot.DownstreamUrlCreator.Middleware private readonly OcelotRequestDelegate _next; private readonly IDownstreamPathPlaceholderReplacer _replacer; private readonly IOcelotLogger _logger; - private readonly IUrlBuilder _urlBuilder; public DownstreamUrlCreatorMiddleware(OcelotRequestDelegate next, IOcelotLoggerFactory loggerFactory, - IDownstreamPathPlaceholderReplacer replacer, - IUrlBuilder urlBuilder) + IDownstreamPathPlaceholderReplacer replacer) { _next = next; _replacer = replacer; - _urlBuilder = urlBuilder; _logger = loggerFactory.CreateLogger(); } @@ -40,11 +38,32 @@ namespace Ocelot.DownstreamUrlCreator.Middleware return; } - var uriBuilder = new UriBuilder(context.DownstreamRequest.RequestUri) + UriBuilder uriBuilder; + + //todo - feel this is a bit crap the way we build the url dont see why we need this builder thing..maybe i blew my own brains out + // when i originally wrote it.. + if (context.ServiceProviderConfiguration.Type == "ServiceFabric" && context.DownstreamReRoute.UseServiceDiscovery) { - Path = dsPath.Data.Value, - Scheme = context.DownstreamReRoute.DownstreamScheme - }; + _logger.LogInformation("DownstreamUrlCreatorMiddleware - going to try set service fabric path"); + + var scheme = context.DownstreamReRoute.DownstreamScheme; + var host = context.DownstreamRequest.RequestUri.Host; + var port = context.DownstreamRequest.RequestUri.Port; + var serviceFabricPath = $"/{context.DownstreamReRoute.ServiceName + dsPath.Data.Value}"; + + _logger.LogInformation("DownstreamUrlCreatorMiddleware - service fabric path is {proxyUrl}", serviceFabricPath); + + var uri = new Uri($"{scheme}://{host}:{port}{serviceFabricPath}?cmd=instance"); + uriBuilder = new UriBuilder(uri); + } + else + { + uriBuilder = new UriBuilder(context.DownstreamRequest.RequestUri) + { + Path = dsPath.Data.Value, + Scheme = context.DownstreamReRoute.DownstreamScheme + }; + } context.DownstreamRequest.RequestUri = uriBuilder.Uri; diff --git a/src/Ocelot/DownstreamUrlCreator/UrlBuilder.cs b/src/Ocelot/DownstreamUrlCreator/UrlBuilder.cs index 80f2507d..1c5f284c 100644 --- a/src/Ocelot/DownstreamUrlCreator/UrlBuilder.cs +++ b/src/Ocelot/DownstreamUrlCreator/UrlBuilder.cs @@ -1,4 +1,5 @@ -using System; +/* +using System; using System.Collections.Generic; using Ocelot.Errors; using Ocelot.Responses; @@ -25,12 +26,11 @@ namespace Ocelot.DownstreamUrlCreator return new ErrorResponse(new List { new DownstreamHostNullOrEmptyError() }); } - var builder = new UriBuilder { Host = downstreamHostAndPort.DownstreamHost, Path = downstreamPath, - Scheme = downstreamScheme + Scheme = downstreamScheme, }; if (downstreamHostAndPort.DownstreamPort > 0) @@ -44,3 +44,4 @@ namespace Ocelot.DownstreamUrlCreator } } } +*/ diff --git a/src/Ocelot/LoadBalancer/LoadBalancers/NoLoadBalancer.cs b/src/Ocelot/LoadBalancer/LoadBalancers/NoLoadBalancer.cs index 172909d7..203d1b9d 100644 --- a/src/Ocelot/LoadBalancer/LoadBalancers/NoLoadBalancer.cs +++ b/src/Ocelot/LoadBalancer/LoadBalancers/NoLoadBalancer.cs @@ -17,6 +17,7 @@ namespace Ocelot.LoadBalancer.LoadBalancers public async Task> Lease() { + //todo no point spinning a task up here, also first or default could be null.. var service = await Task.FromResult(_services.FirstOrDefault()); return new OkResponse(service.HostAndPort); } diff --git a/src/Ocelot/ServiceDiscovery/ServiceDiscoveryProviderFactory.cs b/src/Ocelot/ServiceDiscovery/ServiceDiscoveryProviderFactory.cs index 0e75cb1a..de93a19d 100644 --- a/src/Ocelot/ServiceDiscovery/ServiceDiscoveryProviderFactory.cs +++ b/src/Ocelot/ServiceDiscovery/ServiceDiscoveryProviderFactory.cs @@ -18,7 +18,7 @@ namespace Ocelot.ServiceDiscovery { if (reRoute.UseServiceDiscovery) { - return GetServiceDiscoveryProvider(reRoute.ServiceName, serviceConfig.ServiceProviderHost, serviceConfig.ServiceProviderPort); + return GetServiceDiscoveryProvider(serviceConfig, reRoute.ServiceName); } var services = new List(); @@ -33,9 +33,15 @@ namespace Ocelot.ServiceDiscovery return new ConfigurationServiceProvider(services); } - private IServiceDiscoveryProvider GetServiceDiscoveryProvider(string keyOfServiceInConsul, string providerHostName, int providerPort) + private IServiceDiscoveryProvider GetServiceDiscoveryProvider(ServiceProviderConfiguration serviceConfig, string serviceName) { - var consulRegistryConfiguration = new ConsulRegistryConfiguration(providerHostName, providerPort, keyOfServiceInConsul); + if (serviceConfig.Type == "ServiceFabric") + { + var config = new ServiceFabricConfiguration(serviceConfig.Host, serviceConfig.Port, serviceName); + return new ServiceFabricServiceDiscoveryProvider(config); + } + + var consulRegistryConfiguration = new ConsulRegistryConfiguration(serviceConfig.Host, serviceConfig.Port, serviceName); return new ConsulServiceDiscoveryProvider(consulRegistryConfiguration, _factory); } } diff --git a/src/Ocelot/ServiceDiscovery/ServiceFabricConfiguration.cs b/src/Ocelot/ServiceDiscovery/ServiceFabricConfiguration.cs new file mode 100644 index 00000000..7522a1e0 --- /dev/null +++ b/src/Ocelot/ServiceDiscovery/ServiceFabricConfiguration.cs @@ -0,0 +1,16 @@ +namespace Ocelot.ServiceDiscovery +{ + public class ServiceFabricConfiguration + { + public ServiceFabricConfiguration(string hostName, int port, string serviceName) + { + HostName = hostName; + Port = port; + ServiceName = serviceName; + } + + public string ServiceName { get; private set; } + public string HostName { get; private set; } + public int Port { get; private set; } + } +} diff --git a/src/Ocelot/ServiceDiscovery/ServiceFabricServiceDiscoveryProvider.cs b/src/Ocelot/ServiceDiscovery/ServiceFabricServiceDiscoveryProvider.cs new file mode 100644 index 00000000..28f9bb65 --- /dev/null +++ b/src/Ocelot/ServiceDiscovery/ServiceFabricServiceDiscoveryProvider.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Ocelot.Values; + +namespace Ocelot.ServiceDiscovery +{ + public class ServiceFabricServiceDiscoveryProvider : IServiceDiscoveryProvider + { + private readonly ServiceFabricConfiguration _configuration; + + public ServiceFabricServiceDiscoveryProvider(ServiceFabricConfiguration configuration) + { + _configuration = configuration; + } + + public async Task> Get() + { + return new List + { + new Service(_configuration.ServiceName, + new ServiceHostAndPort(_configuration.HostName, _configuration.Port), + "doesnt matter with service fabric", + "doesnt matter with service fabric", + new List()) + }; + } + } +} diff --git a/test/Ocelot.AcceptanceTests/ServiceFabricTests.cs b/test/Ocelot.AcceptanceTests/ServiceFabricTests.cs new file mode 100644 index 00000000..bfe14103 --- /dev/null +++ b/test/Ocelot.AcceptanceTests/ServiceFabricTests.cs @@ -0,0 +1,112 @@ +using System.Linq; +using Microsoft.Extensions.Primitives; + +namespace Ocelot.AcceptanceTests +{ + using System; + using System.Collections.Generic; + using System.IO; + using System.Net; + using Microsoft.AspNetCore.Builder; + using Microsoft.AspNetCore.Hosting; + using Microsoft.AspNetCore.Http; + using Ocelot.Configuration.File; + using Shouldly; + using TestStack.BDDfy; + using Xunit; + + public class ServiceFabricTests : IDisposable + { + private IWebHost _builder; + private readonly Steps _steps; + private string _downstreamPath; + + public ServiceFabricTests() + { + _steps = new Steps(); + } + + [Fact] + public void should_support_service_fabric_naming_and_dns_service() + { + var configuration = new FileConfiguration + { + ReRoutes = new List + { + new FileReRoute + { + DownstreamPathTemplate = "/api/values", + DownstreamScheme = "http", + UpstreamPathTemplate = "/EquipmentInterfaces", + UpstreamHttpMethod = new List { "Get" }, + UseServiceDiscovery = true, + ServiceName = "OcelotServiceApplication/OcelotApplicationService" + } + }, + GlobalConfiguration = new FileGlobalConfiguration + { + ServiceDiscoveryProvider = new FileServiceDiscoveryProvider() + { + Host = "localhost", + Port = 19081, + Type = "ServiceFabric" + } + } + }; + + this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:19081", "/OcelotServiceApplication/OcelotApplicationService/api/values", 200, "Hello from Laura")) + .And(x => _steps.GivenThereIsAConfiguration(configuration)) + .And(x => _steps.GivenOcelotIsRunning()) + .When(x => _steps.WhenIGetUrlOnTheApiGateway("/EquipmentInterfaces")) + .Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK)) + .And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura")) + .BDDfy(); + } + + private void GivenThereIsAServiceRunningOn(string baseUrl, string basePath, int statusCode, string responseBody) + { + _builder = new WebHostBuilder() + .UseUrls(baseUrl) + .UseKestrel() + .UseContentRoot(Directory.GetCurrentDirectory()) + .UseIISIntegration() + .Configure(app => + { + app.UsePathBase(basePath); + app.Run(async context => + { + _downstreamPath = !string.IsNullOrEmpty(context.Request.PathBase.Value) ? context.Request.PathBase.Value : context.Request.Path.Value; + + if(_downstreamPath != basePath) + { + context.Response.StatusCode = statusCode; + await context.Response.WriteAsync("downstream path didnt match base path"); + } + else + { + if (context.Request.Query.TryGetValue("cmd", out var values)) + { + values.First().ShouldBe("instance"); + context.Response.StatusCode = statusCode; + await context.Response.WriteAsync(responseBody); + } + else + { + context.Response.StatusCode = statusCode; + await context.Response.WriteAsync("downstream path didnt match base path"); + } + } + }); + }) + .Build(); + + _builder.Start(); + } + + public void Dispose() + { + _builder?.Dispose(); + _steps.Dispose(); + } + } +} diff --git a/test/Ocelot.UnitTests/Configuration/ConfigurationFluentValidationTests.cs b/test/Ocelot.UnitTests/Configuration/ConfigurationFluentValidationTests.cs index e7e56178..ba7bfd01 100644 --- a/test/Ocelot.UnitTests/Configuration/ConfigurationFluentValidationTests.cs +++ b/test/Ocelot.UnitTests/Configuration/ConfigurationFluentValidationTests.cs @@ -328,7 +328,7 @@ namespace Ocelot.UnitTests.Configuration this.Given(x => x.GivenAConfiguration(configuration)) .When(x => x.WhenIValidateTheConfiguration()) .Then(x => x.ThenTheResultIsNotValid()) - .And(x => x.ThenTheErrorMessageAtPositionIs(0, "ReRoutes for aggregateReRoute / either do not exist or do not have correct Key property")) + .And(x => x.ThenTheErrorMessageAtPositionIs(0, "ReRoutes for aggregateReRoute / either do not exist or do not have correct ServiceName property")) .BDDfy(); } diff --git a/test/Ocelot.UnitTests/Configuration/ServiceProviderCreatorTests.cs b/test/Ocelot.UnitTests/Configuration/ServiceProviderCreatorTests.cs index c0a35696..8b0cc078 100644 --- a/test/Ocelot.UnitTests/Configuration/ServiceProviderCreatorTests.cs +++ b/test/Ocelot.UnitTests/Configuration/ServiceProviderCreatorTests.cs @@ -30,13 +30,15 @@ namespace Ocelot.UnitTests.Configuration ServiceDiscoveryProvider = new FileServiceDiscoveryProvider { Host = "127.0.0.1", - Port = 1234 + Port = 1234, + Type = "ServiceFabric" } }; var expected = new ServiceProviderConfigurationBuilder() .WithServiceDiscoveryProviderHost("127.0.0.1") .WithServiceDiscoveryProviderPort(1234) + .WithServiceDiscoveryProviderType("ServiceFabric") .Build(); this.Given(x => x.GivenTheFollowingReRoute(reRoute)) @@ -63,8 +65,8 @@ namespace Ocelot.UnitTests.Configuration private void ThenTheConfigIs(ServiceProviderConfiguration expected) { - _result.ServiceProviderHost.ShouldBe(expected.ServiceProviderHost); - _result.ServiceProviderPort.ShouldBe(expected.ServiceProviderPort); + _result.Host.ShouldBe(expected.Host); + _result.Port.ShouldBe(expected.Port); } } -} \ No newline at end of file +} diff --git a/test/Ocelot.UnitTests/DownstreamUrlCreator/DownstreamUrlCreatorMiddlewareTests.cs b/test/Ocelot.UnitTests/DownstreamUrlCreator/DownstreamUrlCreatorMiddlewareTests.cs index ec4829a7..d0926fc9 100644 --- a/test/Ocelot.UnitTests/DownstreamUrlCreator/DownstreamUrlCreatorMiddlewareTests.cs +++ b/test/Ocelot.UnitTests/DownstreamUrlCreator/DownstreamUrlCreatorMiddlewareTests.cs @@ -1,4 +1,5 @@ -using Ocelot.Middleware; +using Ocelot.Configuration; +using Ocelot.Middleware; namespace Ocelot.UnitTests.DownstreamUrlCreator { @@ -27,7 +28,6 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator public class DownstreamUrlCreatorMiddlewareTests { private readonly Mock _downstreamUrlTemplateVariableReplacer; - private readonly Mock _urlBuilder; private OkResponse _downstreamPath; private Mock _loggerFactory; private Mock _logger; @@ -42,7 +42,6 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator _logger = new Mock(); _loggerFactory.Setup(x => x.CreateLogger()).Returns(_logger.Object); _downstreamUrlTemplateVariableReplacer = new Mock(); - _urlBuilder = new Mock(); _downstreamContext.DownstreamRequest = new HttpRequestMessage(HttpMethod.Get, "https://my.url/abc/?q=123"); _next = async context => { //do nothing @@ -58,6 +57,9 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator .WithDownstreamScheme("https") .Build(); + var config = new ServiceProviderConfigurationBuilder() + .Build(); + this.Given(x => x.GivenTheDownStreamRouteIs( new DownstreamRoute( new List(), @@ -66,15 +68,81 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator .WithUpstreamHttpMethod(new List { "Get" }) .Build()))) .And(x => x.GivenTheDownstreamRequestUriIs("http://my.url/abc?q=123")) + .And(x => GivenTheServiceProviderConfigIs(config)) .And(x => x.GivenTheUrlReplacerWillReturn("/api/products/1")) .When(x => x.WhenICallTheMiddleware()) .Then(x => x.ThenTheDownstreamRequestUriIs("https://my.url:80/api/products/1?q=123")) .BDDfy(); } + [Fact] + public void should_not_create_service_fabric_url() + { + var downstreamReRoute = new DownstreamReRouteBuilder() + .WithDownstreamPathTemplate("any old string") + .WithUpstreamHttpMethod(new List { "Get" }) + .WithDownstreamScheme("https") + .Build(); + + var config = new ServiceProviderConfigurationBuilder() + .WithServiceDiscoveryProviderType("ServiceFabric") + .WithServiceDiscoveryProviderHost("localhost") + .WithServiceDiscoveryProviderPort(19081) + .Build(); + + this.Given(x => x.GivenTheDownStreamRouteIs( + new DownstreamRoute( + new List(), + new ReRouteBuilder() + .WithDownstreamReRoute(downstreamReRoute) + .WithUpstreamHttpMethod(new List { "Get" }) + .Build()))) + .And(x => x.GivenTheDownstreamRequestUriIs("http://my.url/abc?q=123")) + .And(x => GivenTheServiceProviderConfigIs(config)) + .And(x => x.GivenTheUrlReplacerWillReturn("/api/products/1")) + .When(x => x.WhenICallTheMiddleware()) + .Then(x => x.ThenTheDownstreamRequestUriIs("https://my.url:80/api/products/1?q=123")) + .BDDfy(); + } + + [Fact] + public void should_create_service_fabric_url() + { + var downstreamReRoute = new DownstreamReRouteBuilder() + .WithDownstreamScheme("http") + .WithServiceName("Ocelot/OcelotApp") + .WithUseServiceDiscovery(true) + .Build(); + + var downstreamRoute = new DownstreamRoute( + new List(), + new ReRouteBuilder() + .WithDownstreamReRoute(downstreamReRoute) + .Build()); + + var config = new ServiceProviderConfigurationBuilder() + .WithServiceDiscoveryProviderType("ServiceFabric") + .WithServiceDiscoveryProviderHost("localhost") + .WithServiceDiscoveryProviderPort(19081) + .Build(); + + this.Given(x => x.GivenTheDownStreamRouteIs(downstreamRoute)) + .And(x => GivenTheServiceProviderConfigIs(config)) + .And(x => x.GivenTheDownstreamRequestUriIs("http://localhost:19081")) + .And(x => x.GivenTheUrlReplacerWillReturn("/api/products/1")) + .When(x => x.WhenICallTheMiddleware()) + .Then(x => x.ThenTheDownstreamRequestUriIs("http://localhost:19081/Ocelot/OcelotApp/api/products/1?cmd=instance")) + .BDDfy(); + } + + private void GivenTheServiceProviderConfigIs(ServiceProviderConfiguration config) + { + _downstreamContext.ServiceProviderConfiguration = config; + } + private void WhenICallTheMiddleware() { - _middleware = new DownstreamUrlCreatorMiddleware(_next, _loggerFactory.Object, _downstreamUrlTemplateVariableReplacer.Object, _urlBuilder.Object); + _middleware = new DownstreamUrlCreatorMiddleware(_next, _loggerFactory.Object, _downstreamUrlTemplateVariableReplacer.Object); _middleware.Invoke(_downstreamContext).GetAwaiter().GetResult(); } diff --git a/test/Ocelot.UnitTests/DownstreamUrlCreator/UrlBuilderTests.cs b/test/Ocelot.UnitTests/DownstreamUrlCreator/UrlBuilderTests.cs deleted file mode 100644 index 20dfa1a1..00000000 --- a/test/Ocelot.UnitTests/DownstreamUrlCreator/UrlBuilderTests.cs +++ /dev/null @@ -1,122 +0,0 @@ -using System; -using Ocelot.DownstreamUrlCreator; -using Ocelot.Responses; -using Ocelot.Values; -using Shouldly; -using TestStack.BDDfy; -using Xunit; - -namespace Ocelot.UnitTests.DownstreamUrlCreator -{ - public class UrlBuilderTests - { - private readonly IUrlBuilder _urlBuilder; - private string _dsPath; - private string _dsScheme; - private string _dsHost; - private int _dsPort; - - private Response _result; - - public UrlBuilderTests() - { - _urlBuilder = new UrlBuilder(); - } - - [Fact] - public void should_return_error_when_downstream_path_is_null() - { - this.Given(x => x.GivenADownstreamPath(null)) - .When(x => x.WhenIBuildTheUrl()) - .Then(x => x.ThenThereIsAnErrorOfType()) - .BDDfy(); - } - - [Fact] - public void should_return_error_when_downstream_scheme_is_null() - { - this.Given(x => x.GivenADownstreamScheme(null)) - .And(x => x.GivenADownstreamPath("test")) - .When(x => x.WhenIBuildTheUrl()) - .Then(x => x.ThenThereIsAnErrorOfType()) - .BDDfy(); - } - - [Fact] - public void should_return_error_when_downstream_host_is_null() - { - this.Given(x => x.GivenADownstreamScheme(null)) - .And(x => x.GivenADownstreamPath("test")) - .And(x => x.GivenADownstreamScheme("test")) - .When(x => x.WhenIBuildTheUrl()) - .Then(x => x.ThenThereIsAnErrorOfType()) - .BDDfy(); - } - - [Fact] - public void should_not_use_port_if_zero() - { - this.Given(x => x.GivenADownstreamPath("/api/products/1")) - .And(x => x.GivenADownstreamScheme("http")) - .And(x => x.GivenADownstreamHost("127.0.0.1")) - .And(x => x.GivenADownstreamPort(0)) - .When(x => x.WhenIBuildTheUrl()) - .Then(x => x.ThenTheUrlIsReturned("http://127.0.0.1/api/products/1")) - .And(x => x.ThenTheUrlIsWellFormed()) - .BDDfy(); - } - - [Fact] - public void should_build_well_formed_uri() - { - this.Given(x => x.GivenADownstreamPath("/api/products/1")) - .And(x => x.GivenADownstreamScheme("http")) - .And(x => x.GivenADownstreamHost("127.0.0.1")) - .And(x => x.GivenADownstreamPort(5000)) - .When(x => x.WhenIBuildTheUrl()) - .Then(x => x.ThenTheUrlIsReturned("http://127.0.0.1:5000/api/products/1")) - .And(x => x.ThenTheUrlIsWellFormed()) - .BDDfy(); - } - - private void ThenThereIsAnErrorOfType() - { - _result.Errors[0].ShouldBeOfType(); - } - - private void GivenADownstreamPath(string dsPath) - { - _dsPath = dsPath; - } - - private void GivenADownstreamScheme(string dsScheme) - { - _dsScheme = dsScheme; - } - - private void GivenADownstreamHost(string dsHost) - { - _dsHost = dsHost; - } - - private void GivenADownstreamPort(int dsPort) - { - _dsPort = dsPort; - } - - private void WhenIBuildTheUrl() - { - _result = _urlBuilder.Build(_dsPath, _dsScheme, new ServiceHostAndPort(_dsHost, _dsPort)); - } - - private void ThenTheUrlIsReturned(string expected) - { - _result.Data.Value.ShouldBe(expected); - } - - private void ThenTheUrlIsWellFormed() - { - Uri.IsWellFormedUriString(_result.Data.Value, UriKind.Absolute).ShouldBeTrue(); - } - } -} diff --git a/test/Ocelot.UnitTests/ServiceDiscovery/ServiceFabricServiceDiscoveryProviderTests.cs b/test/Ocelot.UnitTests/ServiceDiscovery/ServiceFabricServiceDiscoveryProviderTests.cs new file mode 100644 index 00000000..39deb681 --- /dev/null +++ b/test/Ocelot.UnitTests/ServiceDiscovery/ServiceFabricServiceDiscoveryProviderTests.cs @@ -0,0 +1,58 @@ +namespace Ocelot.UnitTests.ServiceDiscovery +{ + using System; + using System.Collections.Generic; + using System.IO; + using System.Text; + using Consul; + using Microsoft.AspNetCore.Builder; + using Microsoft.AspNetCore.Hosting; + using Microsoft.AspNetCore.Http; + using Moq; + using Ocelot.Logging; + using Ocelot.ServiceDiscovery; + using Ocelot.Values; + using Xunit; + using TestStack.BDDfy; + using Shouldly; + + public class ServiceFabricServiceDiscoveryProviderTests + { + private ServiceFabricServiceDiscoveryProvider _provider; + private ServiceFabricConfiguration _config; + private string _host; + private string _serviceName; + private int _port; + private List _services; + + [Fact] + public void should_return_service_fabric_naming_service() + { + this.Given(x => GivenTheFollowing()) + .When(x => WhenIGet()) + .Then(x => ThenTheServiceFabricNamingServiceIsRetured()) + .BDDfy(); + } + + private void GivenTheFollowing() + { + _host = "localhost"; + _serviceName = "OcelotServiceApplication/OcelotApplicationService"; + _port = 19081; + } + + private void WhenIGet() + { + _config = new ServiceFabricConfiguration(_host, _port, _serviceName); + _provider = new ServiceFabricServiceDiscoveryProvider(_config); + _services = _provider.Get().GetAwaiter().GetResult(); + } + + private void ThenTheServiceFabricNamingServiceIsRetured() + { + _services.Count.ShouldBe(1); + _services[0].HostAndPort.DownstreamHost.ShouldBe(_host); + _services[0].HostAndPort.DownstreamPort.ShouldBe(_port); + } + } +} diff --git a/test/Ocelot.UnitTests/ServiceDiscovery/ServiceProviderFactoryTests.cs b/test/Ocelot.UnitTests/ServiceDiscovery/ServiceProviderFactoryTests.cs index f8c60bb7..021b9efb 100644 --- a/test/Ocelot.UnitTests/ServiceDiscovery/ServiceProviderFactoryTests.cs +++ b/test/Ocelot.UnitTests/ServiceDiscovery/ServiceProviderFactoryTests.cs @@ -77,6 +77,24 @@ namespace Ocelot.UnitTests.ServiceDiscovery .BDDfy(); } + [Fact] + public void should_return_service_fabric_provider() + { + var reRoute = new DownstreamReRouteBuilder() + .WithServiceName("product") + .WithUseServiceDiscovery(true) + .Build(); + + var serviceConfig = new ServiceProviderConfigurationBuilder() + .WithServiceDiscoveryProviderType("ServiceFabric") + .Build(); + + this.Given(x => x.GivenTheReRoute(serviceConfig, reRoute)) + .When(x => x.WhenIGetTheServiceProvider()) + .Then(x => x.ThenTheServiceProviderIs()) + .BDDfy(); + } + private void ThenTheFollowingServicesAreReturned(List downstreamAddresses) { var result = (ConfigurationServiceProvider)_result; From 4a28666a41468e21e97936ef06c9300249281660 Mon Sep 17 00:00:00 2001 From: TomPallister Date: Sat, 3 Mar 2018 17:05:40 +0000 Subject: [PATCH 23/26] #238 support passing statefull service headers to service fabric naming service --- docs/features/servicefabric.rst | 8 +++ samples/OcelotServiceFabric/README.md | 2 +- .../DownstreamUrlCreatorMiddleware.cs | 51 +++++++++++----- .../ServiceFabricTests.cs | 46 ++++++++++++-- .../DownstreamUrlCreatorMiddlewareTests.cs | 60 +++++++++++++++++++ 5 files changed, 147 insertions(+), 20 deletions(-) diff --git a/docs/features/servicefabric.rst b/docs/features/servicefabric.rst index e6f69983..d3faa40f 100644 --- a/docs/features/servicefabric.rst +++ b/docs/features/servicefabric.rst @@ -33,3 +33,11 @@ The example below is taken from the samples folder so please check it if this do } } } + +If you are using stateless / guest exe services ocelot will be able to proxy through the naming service without anything else. However +if you are using statefull / actor services you must send the PartitionKind and PartitionKey query string values with the client +request e.g. + +GET http://ocelot.com/EquipmentInterfaces?PartitionKind=xxx&PartitionKey=xxx + +There is no way for Ocelot to work these out for you. diff --git a/samples/OcelotServiceFabric/README.md b/samples/OcelotServiceFabric/README.md index 099348c6..a601e9f4 100644 --- a/samples/OcelotServiceFabric/README.md +++ b/samples/OcelotServiceFabric/README.md @@ -9,7 +9,7 @@ author: raunakpandya edited by Tom Pallister for Ocelot This shows a service fabric cluster with Ocelot exposed over HTTP accessing services in the cluster via the naming service. If you want to try and use Ocelot with Service Fabric I reccomend using this as a starting point. -Ocelot does not support partitioned services (stateful & actors) at the moment. +If you want to use statefull / actors you must send the PartitionKind and PartitionKey to Ocelot as query string parameters. I have not tested this sample on Service Fabric hosted on Linux just a Windows dev cluster. This sample assumes a good understanding of Service Fabric. diff --git a/src/Ocelot/DownstreamUrlCreator/Middleware/DownstreamUrlCreatorMiddleware.cs b/src/Ocelot/DownstreamUrlCreator/Middleware/DownstreamUrlCreatorMiddleware.cs index dc02a20e..308daea5 100644 --- a/src/Ocelot/DownstreamUrlCreator/Middleware/DownstreamUrlCreatorMiddleware.cs +++ b/src/Ocelot/DownstreamUrlCreator/Middleware/DownstreamUrlCreatorMiddleware.cs @@ -7,6 +7,8 @@ using Ocelot.Middleware; using System; using System.Linq; using Ocelot.DownstreamRouteFinder.Middleware; +using Ocelot.Responses; +using Ocelot.Values; namespace Ocelot.DownstreamUrlCreator.Middleware { @@ -40,21 +42,9 @@ namespace Ocelot.DownstreamUrlCreator.Middleware UriBuilder uriBuilder; - //todo - feel this is a bit crap the way we build the url dont see why we need this builder thing..maybe i blew my own brains out - // when i originally wrote it.. - if (context.ServiceProviderConfiguration.Type == "ServiceFabric" && context.DownstreamReRoute.UseServiceDiscovery) + if (ServiceFabricRequest(context)) { - _logger.LogInformation("DownstreamUrlCreatorMiddleware - going to try set service fabric path"); - - var scheme = context.DownstreamReRoute.DownstreamScheme; - var host = context.DownstreamRequest.RequestUri.Host; - var port = context.DownstreamRequest.RequestUri.Port; - var serviceFabricPath = $"/{context.DownstreamReRoute.ServiceName + dsPath.Data.Value}"; - - _logger.LogInformation("DownstreamUrlCreatorMiddleware - service fabric path is {proxyUrl}", serviceFabricPath); - - var uri = new Uri($"{scheme}://{host}:{port}{serviceFabricPath}?cmd=instance"); - uriBuilder = new UriBuilder(uri); + uriBuilder = CreateServiceFabricUri(context, dsPath); } else { @@ -71,5 +61,38 @@ namespace Ocelot.DownstreamUrlCreator.Middleware await _next.Invoke(context); } + + private UriBuilder CreateServiceFabricUri(DownstreamContext context, Response dsPath) + { + var query = context.DownstreamRequest.RequestUri.Query; + var scheme = context.DownstreamReRoute.DownstreamScheme; + var host = context.DownstreamRequest.RequestUri.Host; + var port = context.DownstreamRequest.RequestUri.Port; + var serviceFabricPath = $"/{context.DownstreamReRoute.ServiceName + dsPath.Data.Value}"; + + Uri uri; + + if (RequestForStatefullService(query)) + { + uri = new Uri($"{scheme}://{host}:{port}{serviceFabricPath}{query}"); + } + else + { + var split = string.IsNullOrEmpty(query) ? "?" : "&"; + uri = new Uri($"{scheme}://{host}:{port}{serviceFabricPath}{query}{split}cmd=instance"); + } + + return new UriBuilder(uri); + } + + private static bool ServiceFabricRequest(DownstreamContext context) + { + return context.ServiceProviderConfiguration.Type == "ServiceFabric" && context.DownstreamReRoute.UseServiceDiscovery; + } + + private static bool RequestForStatefullService(string query) + { + return query.Contains("PartitionKind") && query.Contains("PartitionKey"); + } } } diff --git a/test/Ocelot.AcceptanceTests/ServiceFabricTests.cs b/test/Ocelot.AcceptanceTests/ServiceFabricTests.cs index bfe14103..3f79a801 100644 --- a/test/Ocelot.AcceptanceTests/ServiceFabricTests.cs +++ b/test/Ocelot.AcceptanceTests/ServiceFabricTests.cs @@ -27,7 +27,7 @@ namespace Ocelot.AcceptanceTests } [Fact] - public void should_support_service_fabric_naming_and_dns_service() + public void should_support_service_fabric_naming_and_dns_service_stateless_and_guest() { var configuration = new FileConfiguration { @@ -54,7 +54,7 @@ namespace Ocelot.AcceptanceTests } }; - this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:19081", "/OcelotServiceApplication/OcelotApplicationService/api/values", 200, "Hello from Laura")) + this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:19081", "/OcelotServiceApplication/OcelotApplicationService/api/values", 200, "Hello from Laura", "cmd=instance")) .And(x => _steps.GivenThereIsAConfiguration(configuration)) .And(x => _steps.GivenOcelotIsRunning()) .When(x => _steps.WhenIGetUrlOnTheApiGateway("/EquipmentInterfaces")) @@ -63,7 +63,44 @@ namespace Ocelot.AcceptanceTests .BDDfy(); } - private void GivenThereIsAServiceRunningOn(string baseUrl, string basePath, int statusCode, string responseBody) + [Fact] + public void should_support_service_fabric_naming_and_dns_service_statefull_and_actors() + { + var configuration = new FileConfiguration + { + ReRoutes = new List + { + new FileReRoute + { + DownstreamPathTemplate = "/api/values", + DownstreamScheme = "http", + UpstreamPathTemplate = "/EquipmentInterfaces", + UpstreamHttpMethod = new List { "Get" }, + UseServiceDiscovery = true, + ServiceName = "OcelotServiceApplication/OcelotApplicationService" + } + }, + GlobalConfiguration = new FileGlobalConfiguration + { + ServiceDiscoveryProvider = new FileServiceDiscoveryProvider() + { + Host = "localhost", + Port = 19081, + Type = "ServiceFabric" + } + } + }; + + this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:19081", "/OcelotServiceApplication/OcelotApplicationService/api/values", 200, "Hello from Laura", "PartitionKind=test&PartitionKey=1")) + .And(x => _steps.GivenThereIsAConfiguration(configuration)) + .And(x => _steps.GivenOcelotIsRunning()) + .When(x => _steps.WhenIGetUrlOnTheApiGateway("/EquipmentInterfaces?PartitionKind=test&PartitionKey=1")) + .Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK)) + .And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura")) + .BDDfy(); + } + + private void GivenThereIsAServiceRunningOn(string baseUrl, string basePath, int statusCode, string responseBody, string expectedQueryString) { _builder = new WebHostBuilder() .UseUrls(baseUrl) @@ -84,9 +121,8 @@ namespace Ocelot.AcceptanceTests } else { - if (context.Request.Query.TryGetValue("cmd", out var values)) + if (context.Request.QueryString.Value.Contains(expectedQueryString)) { - values.First().ShouldBe("instance"); context.Response.StatusCode = statusCode; await context.Response.WriteAsync(responseBody); } diff --git a/test/Ocelot.UnitTests/DownstreamUrlCreator/DownstreamUrlCreatorMiddlewareTests.cs b/test/Ocelot.UnitTests/DownstreamUrlCreator/DownstreamUrlCreatorMiddlewareTests.cs index d0926fc9..0d678a7b 100644 --- a/test/Ocelot.UnitTests/DownstreamUrlCreator/DownstreamUrlCreatorMiddlewareTests.cs +++ b/test/Ocelot.UnitTests/DownstreamUrlCreator/DownstreamUrlCreatorMiddlewareTests.cs @@ -135,6 +135,66 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator .BDDfy(); } + [Fact] + public void should_create_service_fabric_url_with_query_string_for_stateless_service() + { + var downstreamReRoute = new DownstreamReRouteBuilder() + .WithDownstreamScheme("http") + .WithServiceName("Ocelot/OcelotApp") + .WithUseServiceDiscovery(true) + .Build(); + + var downstreamRoute = new DownstreamRoute( + new List(), + new ReRouteBuilder() + .WithDownstreamReRoute(downstreamReRoute) + .Build()); + + var config = new ServiceProviderConfigurationBuilder() + .WithServiceDiscoveryProviderType("ServiceFabric") + .WithServiceDiscoveryProviderHost("localhost") + .WithServiceDiscoveryProviderPort(19081) + .Build(); + + this.Given(x => x.GivenTheDownStreamRouteIs(downstreamRoute)) + .And(x => GivenTheServiceProviderConfigIs(config)) + .And(x => x.GivenTheDownstreamRequestUriIs("http://localhost:19081?Tom=test&laura=1")) + .And(x => x.GivenTheUrlReplacerWillReturn("/api/products/1")) + .When(x => x.WhenICallTheMiddleware()) + .Then(x => x.ThenTheDownstreamRequestUriIs("http://localhost:19081/Ocelot/OcelotApp/api/products/1?Tom=test&laura=1&cmd=instance")) + .BDDfy(); + } + + [Fact] + public void should_create_service_fabric_url_with_query_string_for_stateful_service() + { + var downstreamReRoute = new DownstreamReRouteBuilder() + .WithDownstreamScheme("http") + .WithServiceName("Ocelot/OcelotApp") + .WithUseServiceDiscovery(true) + .Build(); + + var downstreamRoute = new DownstreamRoute( + new List(), + new ReRouteBuilder() + .WithDownstreamReRoute(downstreamReRoute) + .Build()); + + var config = new ServiceProviderConfigurationBuilder() + .WithServiceDiscoveryProviderType("ServiceFabric") + .WithServiceDiscoveryProviderHost("localhost") + .WithServiceDiscoveryProviderPort(19081) + .Build(); + + this.Given(x => x.GivenTheDownStreamRouteIs(downstreamRoute)) + .And(x => GivenTheServiceProviderConfigIs(config)) + .And(x => x.GivenTheDownstreamRequestUriIs("http://localhost:19081?PartitionKind=test&PartitionKey=1")) + .And(x => x.GivenTheUrlReplacerWillReturn("/api/products/1")) + .When(x => x.WhenICallTheMiddleware()) + .Then(x => x.ThenTheDownstreamRequestUriIs("http://localhost:19081/Ocelot/OcelotApp/api/products/1?PartitionKind=test&PartitionKey=1")) + .BDDfy(); + } + private void GivenTheServiceProviderConfigIs(ServiceProviderConfiguration config) { _downstreamContext.ServiceProviderConfiguration = config; From 2f37acc792c399fa124f06a5757c75a7964681b4 Mon Sep 17 00:00:00 2001 From: TomPallister Date: Sat, 3 Mar 2018 17:08:39 +0000 Subject: [PATCH 24/26] #238 updated readme --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index fc9b67b8..a34dd2fa 100644 --- a/README.md +++ b/README.md @@ -39,6 +39,7 @@ A quick list of Ocelot's capabilities for more information see the [documentatio * Routing * Request Aggregation * Service Discovery with Consul +* Servic Fabric * Authentication * Authorisation * Rate Limiting From b7e409214b7351b56c535041bcbfddbdd8a7160b Mon Sep 17 00:00:00 2001 From: TomPallister Date: Sun, 4 Mar 2018 10:02:53 +0000 Subject: [PATCH 25/26] #238 - updated readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a34dd2fa..6bbc77e0 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ A quick list of Ocelot's capabilities for more information see the [documentatio * Routing * Request Aggregation * Service Discovery with Consul -* Servic Fabric +* Service Fabric * Authentication * Authorisation * Rate Limiting From 7e1f8a4604aaa6a9432b49533e1929346ccda1c9 Mon Sep 17 00:00:00 2001 From: TomPallister Date: Sun, 4 Mar 2018 10:24:04 +0000 Subject: [PATCH 26/26] Added service fabric to big picture in docs --- docs/images/OcelotServiceFabric.jpg | Bin 0 -> 53509 bytes docs/introduction/bigpicture.rst | 4 ++++ 2 files changed, 4 insertions(+) create mode 100644 docs/images/OcelotServiceFabric.jpg diff --git a/docs/images/OcelotServiceFabric.jpg b/docs/images/OcelotServiceFabric.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e4aaab7ad8bb169696340e82b606beb7d6a1981d GIT binary patch literal 53509 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 literal 0 HcmV?d00001 diff --git a/docs/introduction/bigpicture.rst b/docs/introduction/bigpicture.rst index 95e62fdc..989c0f5c 100644 --- a/docs/introduction/bigpicture.rst +++ b/docs/introduction/bigpicture.rst @@ -36,3 +36,7 @@ Multiple Instances With Consul ^^^^^^^^^^^ .. image:: ../images/OcelotMultipleInstancesConsul.jpg + +With Service Fabric +^^^^^^^^^^^^^^^^^^^ +.. image:: ../images/OcelotServiceFabric.jpg