Merge pull request #41 from ThreeMammals/develop

support_service_fabric
This commit is contained in:
geffzhang 2018-03-05 08:36:58 +08:00 committed by GitHub
commit 681f0551cd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
209 changed files with 3107 additions and 912 deletions

46
CODE_OF_CONDUCT.md Normal file
View File

@ -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/

9
CONTRIBUTING.md Normal file
View File

@ -0,0 +1,9 @@
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 :)

17
ISSUE_TEMPLATE.md Normal file
View File

@ -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:

View File

@ -12,6 +12,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
build-and-run-tests.ps1 = build-and-run-tests.ps1 build-and-run-tests.ps1 = build-and-run-tests.ps1
build.cake = build.cake build.cake = build.cake
build.ps1 = build.ps1 build.ps1 = build.ps1
codeanalysis.ruleset = codeanalysis.ruleset
GitVersion.yml = GitVersion.yml GitVersion.yml = GitVersion.yml
global.json = global.json global.json = global.json
LICENSE.md = LICENSE.md LICENSE.md = LICENSE.md

7
PULL_REQUEST_TEMPLATE.md Normal file
View File

@ -0,0 +1,7 @@
Fixes / New Feature #
## Proposed Changes
-
-
-

View File

@ -1,15 +1,17 @@
# Ocelot [<img src="http://threemammals.com/images/ocelot_logo.png">](http://threemammals.com/ocelot)
[![Build status](https://ci.appveyor.com/api/projects/status/r6sv51qx36sis1je?svg=true)](https://ci.appveyor.com/project/TomPallister/ocelot-fcfpb) [![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) [![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) [![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 Ocelot is a .NET Api Gateway. This project is aimed at people using .NET running
a micro services / service orientated architecture 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 In particular I want easy integration with
IdentityServer reference and bearer tokens. IdentityServer reference and bearer tokens.
@ -26,10 +28,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 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 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 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 The response from the downstream service is retrieved as the requests goes back up the Ocelot pipeline.
and retrieved as the requests goes back up the Ocelot pipeline. There is a piece of middleware There is a piece of middleware that maps the HttpResponseMessage onto the HttpResponse object and that
that maps the HttpResponseMessage onto the HttpResponse object and that is returned to the client. is returned to the client. That is basically it with a bunch of other features!
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
* Service Fabric
* 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 ## How to install
@ -48,20 +68,22 @@ Please click [here](http://ocelot.readthedocs.io/en/latest/) for the Ocleot docu
## Coming up ## 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 ## Contributing
Pull requests, issues and commentary welcome! No special process just create a request and get in We love to receive contributions from the community so please keep them coming :)
touch either via gitter or create an issue.
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 ## 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) [![](https://codescene.io/projects/697/status.svg) Get more details at **codescene.io**.](https://codescene.io/projects/697/jobs/latest-successful/results)

152
codeanalysis.ruleset Normal file
View File

@ -0,0 +1,152 @@
<?xml version="1.0" encoding="utf-8"?>
<RuleSet Name="Rules for StyleCop.Analyzers" Description="Code analysis rules for StyleCop.Analyzers.csproj." ToolsVersion="14.0">
<Rules AnalyzerId="AsyncUsageAnalyzers" RuleNamespace="AsyncUsageAnalyzers">
<Rule Id="AvoidAsyncSuffix" Action="None" />
<Rule Id="AvoidAsyncVoid" Action="None" />
<Rule Id="UseAsyncSuffix" Action="None" />
<Rule Id="UseConfigureAwait" Action="None" />
</Rules>
<Rules AnalyzerId="Microsoft.Analyzers.ManagedCodeAnalysis" RuleNamespace="Microsoft.Rules.Managed">
<Rule Id="CA1001" Action="None" />
<Rule Id="CA1009" Action="None" />
<Rule Id="CA1016" Action="None" />
<Rule Id="CA1033" Action="None" />
<Rule Id="CA1049" Action="None" />
<Rule Id="CA1060" Action="None" />
<Rule Id="CA1061" Action="None" />
<Rule Id="CA1063" Action="None" />
<Rule Id="CA1065" Action="None" />
<Rule Id="CA1301" Action="None" />
<Rule Id="CA1400" Action="None" />
<Rule Id="CA1401" Action="None" />
<Rule Id="CA1403" Action="None" />
<Rule Id="CA1404" Action="None" />
<Rule Id="CA1405" Action="None" />
<Rule Id="CA1410" Action="None" />
<Rule Id="CA1415" Action="None" />
<Rule Id="CA1821" Action="None" />
<Rule Id="CA1900" Action="None" />
<Rule Id="CA1901" Action="None" />
<Rule Id="CA2002" Action="None" />
<Rule Id="CA2100" Action="None" />
<Rule Id="CA2101" Action="None" />
<Rule Id="CA2108" Action="None" />
<Rule Id="CA2111" Action="None" />
<Rule Id="CA2112" Action="None" />
<Rule Id="CA2114" Action="None" />
<Rule Id="CA2116" Action="None" />
<Rule Id="CA2117" Action="None" />
<Rule Id="CA2122" Action="None" />
<Rule Id="CA2123" Action="None" />
<Rule Id="CA2124" Action="None" />
<Rule Id="CA2126" Action="None" />
<Rule Id="CA2131" Action="None" />
<Rule Id="CA2132" Action="None" />
<Rule Id="CA2133" Action="None" />
<Rule Id="CA2134" Action="None" />
<Rule Id="CA2137" Action="None" />
<Rule Id="CA2138" Action="None" />
<Rule Id="CA2140" Action="None" />
<Rule Id="CA2141" Action="None" />
<Rule Id="CA2146" Action="None" />
<Rule Id="CA2147" Action="None" />
<Rule Id="CA2149" Action="None" />
<Rule Id="CA2200" Action="None" />
<Rule Id="CA2202" Action="None" />
<Rule Id="CA2207" Action="None" />
<Rule Id="CA2212" Action="None" />
<Rule Id="CA2213" Action="None" />
<Rule Id="CA2214" Action="None" />
<Rule Id="CA2216" Action="None" />
<Rule Id="CA2220" Action="None" />
<Rule Id="CA2229" Action="None" />
<Rule Id="CA2231" Action="None" />
<Rule Id="CA2232" Action="None" />
<Rule Id="CA2235" Action="None" />
<Rule Id="CA2236" Action="None" />
<Rule Id="CA2237" Action="None" />
<Rule Id="CA2238" Action="None" />
<Rule Id="CA2240" Action="None" />
<Rule Id="CA2241" Action="None" />
<Rule Id="CA2242" Action="None" />
</Rules>
<Rules AnalyzerId="Microsoft.CodeAnalysis.CSharp.Features" RuleNamespace="Microsoft.CodeAnalysis.CSharp.Features">
<Rule Id="IDE0003" Action="None" />
</Rules>
<Rules AnalyzerId="StyleCop.Analyzers" RuleNamespace="StyleCop.Analyzers">
<Rule Id="SA0000" Action="Hidden" />
<Rule Id="SA1000" Action="None" />
<Rule Id="SA1001" Action="None" />
<Rule Id="SA1002" Action="None" />
<Rule Id="SA1003" Action="None" />
<Rule Id="SA1005" Action="None" />
<Rule Id="SA1008" Action="None" />
<Rule Id="SA1009" Action="None" />
<Rule Id="SA1011" Action="None" />
<Rule Id="SA1012" Action="None" />
<Rule Id="SA1013" Action="None" />
<Rule Id="SA1015" Action="None" />
<Rule Id="SA1016" Action="None" />
<Rule Id="SA1021" Action="None" />
<Rule Id="SA1022" Action="None" />
<Rule Id="SA1024" Action="None" />
<Rule Id="SA1026" Action="None" />
<Rule Id="SA1028" Action="None" />
<Rule Id="SA1100" Action="None" />
<Rule Id="SA1101" Action="None" />
<Rule Id="SA1106" Action="None" />
<Rule Id="SA1111" Action="None" />
<Rule Id="SA1112" Action="None" />
<Rule Id="SA1116" Action="None" />
<Rule Id="SA1117" Action="None" />
<Rule Id="SA1118" Action="None" />
<Rule Id="SA1119" Action="None" />
<Rule Id="SA1121" Action="None" />
<Rule Id="SA1122" Action="None" />
<Rule Id="SA1128" Action="None" />
<Rule Id="SA1133" Action="None" />
<Rule Id="SA1200" Action="None" />
<Rule Id="SA1201" Action="None" />
<Rule Id="SA1202" Action="None" />
<Rule Id="SA1203" Action="None" />
<Rule Id="SA1204" Action="None" />
<Rule Id="SA1208" Action="None" />
<Rule Id="SA1209" Action="None" />
<Rule Id="SA1210" Action="None" />
<Rule Id="SA1214" Action="None" />
<Rule Id="SA1216" Action="None" />
<Rule Id="SA1300" Action="None" />
<Rule Id="SA1302" Action="None" />
<Rule Id="SA1303" Action="None" />
<Rule Id="SA1304" Action="None" />
<Rule Id="SA1305" Action="None" />
<Rule Id="SA1309" Action="None" />
<Rule Id="SA1310" Action="None" />
<Rule Id="SA1311" Action="None" />
<Rule Id="SA1400" Action="None" />
<Rule Id="SA1401" Action="None" />
<Rule Id="SA1402" Action="None" />
<Rule Id="SA1403" Action="None" />
<Rule Id="SA1404" Action="None" />
<Rule Id="SA1405" Action="None" />
<Rule Id="SA1406" Action="None" />
<Rule Id="SA1407" Action="None" />
<Rule Id="SA1408" Action="None" />
<Rule Id="SA1410" Action="None" />
<Rule Id="SA1411" Action="None" />
<Rule Id="SA1412" Action="None" />
<Rule Id="SA1500" Action="None" />
<Rule Id="SA1502" Action="None" />
<Rule Id="SA1516" Action="None" />
<Rule Id="SA1600" Action="None" />
<Rule Id="SA1603" Action="None" />
<Rule Id="SA1609" Action="None" />
<Rule Id="SA1623" Action="None" />
<Rule Id="SA1633" Action="None" />
<Rule Id="SA1636" Action="None" />
<Rule Id="SA1642" Action="None" />
<Rule Id="SA1643" Action="None" />
<Rule Id="SA1652" Action="None" />
</Rules>
</RuleSet>

View File

@ -6,8 +6,10 @@ 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 GlobalConfiguration section which means the same service discovery provider will be used for all ReRoutes
you specify a ServiceName for at ReRoute level. 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 Consul
GlobalConfiguration. The Provider is required and if you do not specify a host and port the Consul default ^^^^^^
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. will be used.
.. code-block:: json .. code-block:: json

View File

@ -0,0 +1,43 @@
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"
}
}
}
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.

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

View File

@ -22,6 +22,7 @@ Thanks for taking a look at the Ocelot documentation. Please use the left hand n
features/routing features/routing
features/requestaggregation features/requestaggregation
features/servicediscovery features/servicediscovery
features/servicefabric
features/authentication features/authentication
features/authorisation features/authorisation
features/administration features/administration

View File

@ -36,3 +36,7 @@ Multiple Instances
With Consul With Consul
^^^^^^^^^^^ ^^^^^^^^^^^
.. image:: ../images/OcelotMultipleInstancesConsul.jpg .. image:: ../images/OcelotMultipleInstancesConsul.jpg
With Service Fabric
^^^^^^^^^^^^^^^^^^^
.. image:: ../images/OcelotServiceFabric.jpg

269
samples/OcelotServiceFabric/.gitignore vendored Normal file
View File

@ -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

View File

@ -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.

View File

@ -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.

View File

@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<ApplicationManifest ApplicationTypeName="OcelotServiceApplicationType"
ApplicationTypeVersion="1.0.0"
xmlns="http://schemas.microsoft.com/2011/01/fabric"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Parameters>
<Parameter Name="OcelotApplicationService_InstanceCount" DefaultValue="1" />
<Parameter Name="OcelotApplicationApiGateway_InstanceCount" DefaultValue="1" />
</Parameters>
<!-- Import the ServiceManifest from the ServicePackage. The ServiceManifestName and ServiceManifestVersion
should match the Name and Version attributes of the ServiceManifest element defined in the
ServiceManifest.xml file. -->
<ServiceManifestImport>
<ServiceManifestRef ServiceManifestName="OcelotApplicationServicePkg" ServiceManifestVersion="1.0.0" />
<ConfigOverrides />
</ServiceManifestImport>
<ServiceManifestImport>
<ServiceManifestRef ServiceManifestName="OcelotApplicationApiGatewayPkg" ServiceManifestVersion="1.0.0" />
<ConfigOverrides />
</ServiceManifestImport>
<DefaultServices>
<!-- The section below creates instances of service types, when an instance of this
application type is created. You can also create one or more instances of service type using the
ServiceFabric PowerShell module.
The attribute ServiceTypeName below must match the name defined in the imported ServiceManifest.xml file. -->
<Service Name="OcelotApplicationService">
<StatelessService ServiceTypeName="OcelotApplicationServiceType" InstanceCount="[OcelotApplicationService_InstanceCount]">
<SingletonPartition />
</StatelessService>
</Service>
<Service Name="OcelotApplicationApiGateway">
<StatelessService ServiceTypeName="OcelotApplicationApiGatewayType" InstanceCount="[OcelotApplicationApiGateway_InstanceCount]">
<SingletonPartition />
</StatelessService>
</Service>
</DefaultServices>
</ApplicationManifest>

View File

@ -0,0 +1,2 @@
dotnet %~dp0\OcelotApplicationApiGateway.dll
exit /b %errorlevel%

View File

@ -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 $?

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8" ?>
<Settings xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/2011/01/fabric">
<!-- Add your custom configuration sections and parameters here -->
<!--
<Section Name="MyConfigSection">
<Parameter Name="MyParameter" Value="Value1" />
</Section>
-->
</Settings>

View File

@ -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.

View File

@ -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.

View File

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<ServiceManifest Name="OcelotApplicationApiGatewayPkg"
Version="1.0.0"
xmlns="http://schemas.microsoft.com/2011/01/fabric"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<ServiceTypes>
<!-- This is the name of your ServiceType.
This name must match the string used in RegisterServiceType call in Program.cs. -->
<StatelessServiceType ServiceTypeName="OcelotApplicationApiGatewayType" />
</ServiceTypes>
<!-- Code package is your service executable. -->
<CodePackage Name="Code" Version="1.0.0">
<EntryPoint>
<ExeHost>
<Program>entryPoint.sh</Program>
<ConsoleRedirection FileRetentionCount="5" FileMaxSizeInKb="2048"/>
</ExeHost>
</EntryPoint>
</CodePackage>
<!-- Config package is the contents of the Config directoy under PackageRoot that contains an
independently-updateable and versioned set of custom configuration settings for your service. -->
<ConfigPackage Name="Config" Version="1.0.0" />
<Resources>
<Endpoints>
<!-- This endpoint is used by the communication listener to obtain the port on which to
listen. Please note that if your service is partitioned, this port is shared with
replicas of different partitions that are placed in your code. -->
<Endpoint Name="WebEndpoint" Protocol="http" Port="31002" />
</Endpoints>
</Resources>
</ServiceManifest>

View File

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<ServiceManifest Name="OcelotApplicationApiGatewayPkg"
Version="1.0.0"
xmlns="http://schemas.microsoft.com/2011/01/fabric"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<ServiceTypes>
<!-- This is the name of your ServiceType.
This name must match the string used in RegisterServiceType call in Program.cs. -->
<StatelessServiceType ServiceTypeName="OcelotApplicationApiGatewayType" />
</ServiceTypes>
<!-- Code package is your service executable. -->
<CodePackage Name="Code" Version="1.0.0">
<EntryPoint>
<ExeHost>
<Program>entryPoint.cmd</Program>
<ConsoleRedirection FileRetentionCount="5" FileMaxSizeInKb="2048"/>
</ExeHost>
</EntryPoint>
</CodePackage>
<!-- Config package is the contents of the Config directoy under PackageRoot that contains an
independently-updateable and versioned set of custom configuration settings for your service. -->
<ConfigPackage Name="Config" Version="1.0.0" />
<Resources>
<Endpoints>
<!-- This endpoint is used by the communication listener to obtain the port on which to
listen. Please note that if your service is partitioned, this port is shared with
replicas of different partitions that are placed in your code. -->
<Endpoint Name="WebEndpoint" Protocol="http" Port="31002" />
</Endpoints>
</Resources>
</ServiceManifest>

View File

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<ServiceManifest Name="OcelotApplicationApiGatewayPkg"
Version="1.0.0"
xmlns="http://schemas.microsoft.com/2011/01/fabric"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<ServiceTypes>
<!-- This is the name of your ServiceType.
This name must match the string used in RegisterServiceType call in Program.cs. -->
<StatelessServiceType ServiceTypeName="OcelotApplicationApiGatewayType" />
</ServiceTypes>
<!-- Code package is your service executable. -->
<CodePackage Name="Code" Version="1.0.0">
<EntryPoint>
<ExeHost>
<Program>entryPoint.cmd</Program>
<ConsoleRedirection FileRetentionCount="5" FileMaxSizeInKb="2048"/>
</ExeHost>
</EntryPoint>
</CodePackage>
<!-- Config package is the contents of the Config directoy under PackageRoot that contains an
independently-updateable and versioned set of custom configuration settings for your service. -->
<ConfigPackage Name="Config" Version="1.0.0" />
<Resources>
<Endpoints>
<!-- This endpoint is used by the communication listener to obtain the port on which to
listen. Please note that if your service is partitioned, this port is shared with
replicas of different partitions that are placed in your code. -->
<Endpoint Name="WebEndpoint" Protocol="http" Port="31002" />
</Endpoints>
</Resources>
</ServiceManifest>

View File

@ -0,0 +1,2 @@
dotnet %~dp0\OcelotApplicationService.dll
exit /b %errorlevel%

View File

@ -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 $?

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8" ?>
<Settings xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/2011/01/fabric">
<!-- Add your custom configuration sections and parameters here -->
<!--
<Section Name="MyConfigSection">
<Parameter Name="MyParameter" Value="Value1" />
</Section>
-->
</Settings>

View File

@ -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.

View File

@ -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.

View File

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<ServiceManifest Name="OcelotApplicationServicePkg"
Version="1.0.0"
xmlns="http://schemas.microsoft.com/2011/01/fabric"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<ServiceTypes>
<!-- This is the name of your ServiceType.
This name must match the string used in RegisterServiceType call in Program.cs. -->
<StatelessServiceType ServiceTypeName="OcelotApplicationServiceType" />
</ServiceTypes>
<!-- Code package is your service executable. -->
<CodePackage Name="Code" Version="1.0.0">
<EntryPoint>
<ExeHost>
<Program>entryPoint.sh</Program>
<ConsoleRedirection FileRetentionCount="5" FileMaxSizeInKb="2048"/>
</ExeHost>
</EntryPoint>
</CodePackage>
<!-- Config package is the contents of the Config directoy under PackageRoot that contains an
independently-updateable and versioned set of custom configuration settings for your service. -->
<ConfigPackage Name="Config" Version="1.0.0" />
<Resources>
<Endpoints>
<Endpoint Name="ServiceEndpoint" Protocol="http"/>
</Endpoints>
</Resources>
</ServiceManifest>

View File

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<ServiceManifest Name="OcelotApplicationServicePkg"
Version="1.0.0"
xmlns="http://schemas.microsoft.com/2011/01/fabric"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<ServiceTypes>
<!-- This is the name of your ServiceType.
This name must match the string used in RegisterServiceType call in Program.cs. -->
<StatelessServiceType ServiceTypeName="OcelotApplicationServiceType" />
</ServiceTypes>
<!-- Code package is your service executable. -->
<CodePackage Name="Code" Version="1.0.0">
<EntryPoint>
<ExeHost>
<Program>entryPoint.cmd</Program>
<ConsoleRedirection FileRetentionCount="5" FileMaxSizeInKb="2048"/>
</ExeHost>
</EntryPoint>
</CodePackage>
<!-- Config package is the contents of the Config directoy under PackageRoot that contains an
independently-updateable and versioned set of custom configuration settings for your service. -->
<ConfigPackage Name="Config" Version="1.0.0" />
<Resources>
<Endpoints>
<Endpoint Name="ServiceEndpoint" Protocol="http"/>
</Endpoints>
</Resources>
</ServiceManifest>

View File

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<ServiceManifest Name="OcelotApplicationServicePkg"
Version="1.0.0"
xmlns="http://schemas.microsoft.com/2011/01/fabric"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<ServiceTypes>
<!-- This is the name of your ServiceType.
This name must match the string used in RegisterServiceType call in Program.cs. -->
<StatelessServiceType ServiceTypeName="OcelotApplicationServiceType" />
</ServiceTypes>
<!-- Code package is your service executable. -->
<CodePackage Name="Code" Version="1.0.0">
<EntryPoint>
<ExeHost>
<Program>entryPoint.cmd</Program>
<ConsoleRedirection FileRetentionCount="5" FileMaxSizeInKb="2048"/>
</ExeHost>
</EntryPoint>
</CodePackage>
<!-- Config package is the contents of the Config directoy under PackageRoot that contains an
independently-updateable and versioned set of custom configuration settings for your service. -->
<ConfigPackage Name="Config" Version="1.0.0" />
<Resources>
<Endpoints>
<Endpoint Name="ServiceEndpoint" Protocol="http"/>
</Endpoints>
</Resources>
</ServiceManifest>

View File

@ -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.
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.
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.
* &lt;application package folder&gt;/ - 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.
<!-- Links -->
[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/

View File

@ -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 ../../

View File

@ -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 -

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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<ServiceInstanceListener> CreateServiceInstanceListeners()
{
return new[]
{
new ServiceInstanceListener(
initparams => new WebCommunicationListener(string.Empty, initparams),
"OcelotServiceWebListener")
};
}
}
}

View File

@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<Description>Stateless Web Service for Stateful OcelotApplicationApiGateway App</Description>
<Authors> </Authors>
<TargetFramework>netcoreapp2.0</TargetFramework>
<AssemblyName>OcelotApplicationApiGateway</AssemblyName>
<OutputType>Exe</OutputType>
<PackageId>OcelotApplicationApiGateway</PackageId>
</PropertyGroup>
<ItemGroup>
<None Update="configuration.json;appsettings.json;">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.ServiceFabric" Version="6.1.456" />
<PackageReference Include="Microsoft.ServiceFabric.Services" Version="3.0.456" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\..\src\Ocelot\Ocelot.csproj" />
</ItemGroup>
</Project>

View File

@ -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;
/// <summary>
/// The service host is the executable that hosts the Service instances.
/// </summary>
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;
}
}
}
}

View File

@ -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/"
}
}
}

View File

@ -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;
/// <summary>
/// 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.
/// </summary>
internal class ServiceEventListener : EventListener
{
private string fileName;
private string filepath = Path.GetTempPath();
public ServiceEventListener(string appName)
{
this.fileName = appName + DateTime.Now.ToString("yyyyMMddHHmmssffff");
}
/// <summary>
/// We override this method to get a callback on every event we subscribed to with EnableEvents
/// </summary>
/// <param name="eventData">The event arguments that describe the event.</param>
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();
}
}
}
}

View File

@ -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;
/// <summary>
/// Implements methods for logging service related events.
/// </summary>
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);
}
}
}

View File

@ -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<string> 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<Startup>()
.UseUrls(this.listeningAddress)
.ConfigureAppConfiguration((hostingContext, config) =>
{
config
.SetBasePath(hostingContext.HostingEnvironment.ContentRootPath)
.AddJsonFile("appsettings.json", true, true)
.AddJsonFile($"appsettings.{hostingContext.HostingEnvironment.EnvironmentName}.json", true, true)
.AddJsonFile("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();
}
/// <summary>
/// Stops, cancels, and disposes everything.
/// </summary>
private void StopAll()
{
try
{
if (this.webHost != null)
{
ServiceEventSource.Current.Message("Stopping web server.");
this.webHost.Dispose();
}
}
catch (ObjectDisposedException)
{
}
}
}
}

View File

@ -0,0 +1,10 @@
{
"Logging": {
"IncludeScopes": false,
"LogLevel": {
"Default": "Trace",
"System": "Information",
"Microsoft": "Information"
}
}
}

View File

@ -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"
}
}
}

View File

@ -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
{
/// <summary>
/// The FabricRuntime creates an instance of this class for each service type instance.
/// </summary>
internal sealed class ApiGateway : StatelessService
{
public ApiGateway(StatelessServiceContext context)
: base(context)
{ }
/// <summary>
/// Optional override to create listeners (like tcp, http) for this service instance.
/// </summary>
/// <returns>The collection of listeners.</returns>
protected override IEnumerable<ServiceInstanceListener> 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<StatelessServiceContext>(serviceContext))
.UseContentRoot(Directory.GetCurrentDirectory())
.UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.UseUniqueServiceUrl)
.UseStartup<Startup>()
.UseUrls(url)
.ConfigureLogging((hostingContext, logging) =>
{
logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
logging.AddConsole();
})
.Build();
}))
};
}
}
}

View File

@ -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<string> 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)
{
}
}
}

View File

@ -0,0 +1,21 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Description>Stateless Service Application</Description>
<Authors> </Authors>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.0</TargetFramework>
<AssemblyName>OcelotApplicationService</AssemblyName>
<PackageId>OcelotApplicationService</PackageId>
<PackageTargetFallback>$(PackageTargetFallback)</PackageTargetFallback>
</PropertyGroup>
<ItemGroup>&#xD;
&#xD;
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.ServiceFabric" Version="6.1.456"/>
<PackageReference Include="Microsoft.ServiceFabric.Services" Version="3.0.456"/>
<PackageReference Include="Microsoft.AspNetCore" Version="2.0.1"/>
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.0.2"/>
<PackageReference Include="Microsoft.ServiceFabric.AspNetCore.Kestrel" Version="3.0.456"/>
</ItemGroup>
</Project>

View File

@ -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
{
/// <summary>
/// This is the entry point of the service host process.
/// </summary>
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;
}
}
}
}

View File

@ -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
}
}

View File

@ -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();
}
}
}

View File

@ -0,0 +1,6 @@
{
"projects": [ "../"],
"sdk": {
"version": "2.1.4"
}
}

View File

@ -0,0 +1,2 @@
Remove-ServiceFabricApplication fabric:/OcelotServiceApplication
Unregister-ServiceFabricApplicationType OcelotServiceApplicationType 1.0.0

View File

@ -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

View File

@ -63,4 +63,3 @@ namespace Ocelot.Authentication.Middleware
} }
} }
} }

View File

@ -47,6 +47,7 @@ namespace Ocelot.Authorisation
}); });
} }
} }
return new OkResponse<bool>(true); return new OkResponse<bool>(true);
} }
} }

View File

@ -123,7 +123,6 @@ namespace Ocelot.Cache.Middleware
var contentHeaders = response?.Content?.Headers.ToDictionary(v => v.Key, v => v.Value); var contentHeaders = response?.Content?.Headers.ToDictionary(v => v.Key, v => v.Value);
var cached = new CachedResponse(statusCode, headers, body, contentHeaders); var cached = new CachedResponse(statusCode, headers, body, contentHeaders);
return cached; return cached;
} }

View File

@ -4,7 +4,6 @@ using Ocelot.Configuration.File;
namespace Ocelot.Cache namespace Ocelot.Cache
{ {
public class RegionCreator : IRegionCreator public class RegionCreator : IRegionCreator
{ {
public string Create(FileReRoute reRoute) public string Create(FileReRoute reRoute)

View File

@ -8,6 +8,7 @@ namespace Ocelot.Cache
{ {
Value = value; Value = value;
} }
public List<string> Value {get;private set;} public List<string> Value {get;private set;}
} }
} }

View File

@ -39,6 +39,7 @@ namespace Ocelot.Claims.Middleware
return; return;
} }
} }
await _next.Invoke(context); await _next.Invoke(context);
} }
} }

View File

@ -36,7 +36,6 @@ namespace Ocelot.Configuration.Builder
private readonly List<DownstreamHostAndPort> _downstreamAddresses; private readonly List<DownstreamHostAndPort> _downstreamAddresses;
private string _upstreamHost; private string _upstreamHost;
private string _key; private string _key;
public DownstreamReRouteBuilder() public DownstreamReRouteBuilder()
{ {
_downstreamAddresses = new List<DownstreamHostAndPort>(); _downstreamAddresses = new List<DownstreamHostAndPort>();
@ -216,7 +215,6 @@ namespace Ocelot.Configuration.Builder
return this; return this;
} }
public DownstreamReRoute Build() public DownstreamReRoute Build()
{ {
return new DownstreamReRoute( return new DownstreamReRoute(

View File

@ -4,6 +4,7 @@ namespace Ocelot.Configuration.Builder
{ {
private string _serviceDiscoveryProviderHost; private string _serviceDiscoveryProviderHost;
private int _serviceDiscoveryProviderPort; private int _serviceDiscoveryProviderPort;
private string _type;
public ServiceProviderConfigurationBuilder WithServiceDiscoveryProviderHost(string serviceDiscoveryProviderHost) public ServiceProviderConfigurationBuilder WithServiceDiscoveryProviderHost(string serviceDiscoveryProviderHost)
{ {
@ -17,9 +18,15 @@ namespace Ocelot.Configuration.Builder
return this; return this;
} }
public ServiceProviderConfigurationBuilder WithServiceDiscoveryProviderType(string type)
{
_type = type;
return this;
}
public ServiceProviderConfiguration Build() public ServiceProviderConfiguration Build()
{ {
return new ServiceProviderConfiguration(_serviceDiscoveryProviderHost,_serviceDiscoveryProviderPort); return new ServiceProviderConfiguration(_type, _serviceDiscoveryProviderHost, _serviceDiscoveryProviderPort);
} }
} }
} }

View File

@ -35,7 +35,6 @@ namespace Ocelot.Configuration.Creator
private readonly IHeaderFindAndReplaceCreator _headerFAndRCreator; private readonly IHeaderFindAndReplaceCreator _headerFAndRCreator;
private readonly IDownstreamAddressesCreator _downstreamAddressesCreator; private readonly IDownstreamAddressesCreator _downstreamAddressesCreator;
public FileOcelotConfigurationCreator( public FileOcelotConfigurationCreator(
IOptions<FileConfiguration> options, IOptions<FileConfiguration> options,
IConfigurationValidator configurationValidator, IConfigurationValidator configurationValidator,

View File

@ -7,11 +7,13 @@ namespace Ocelot.Configuration.Creator
{ {
public ServiceProviderConfiguration Create(FileGlobalConfiguration globalConfiguration) 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; var serviceProviderPort = globalConfiguration?.ServiceDiscoveryProvider?.Port ?? 0;
return new ServiceProviderConfigurationBuilder() return new ServiceProviderConfigurationBuilder()
.WithServiceDiscoveryProviderHost(globalConfiguration?.ServiceDiscoveryProvider?.Host) .WithServiceDiscoveryProviderHost(globalConfiguration?.ServiceDiscoveryProvider?.Host)
.WithServiceDiscoveryProviderPort(serviceProviderPort) .WithServiceDiscoveryProviderPort(serviceProviderPort)
.WithServiceDiscoveryProviderType(globalConfiguration?.ServiceDiscoveryProvider?.Type)
.Build(); .Build();
} }
} }

View File

@ -67,7 +67,6 @@ namespace Ocelot.Configuration.Creator
return false; return false;
} }
private bool IsPlaceHolder(string upstreamTemplate, int i) private bool IsPlaceHolder(string upstreamTemplate, int i)
{ {
return upstreamTemplate[i] == '{'; return upstreamTemplate[i] == '{';

View File

@ -7,6 +7,7 @@
Host = host; Host = host;
Port = port; Port = port;
} }
public string Host { get; private set; } public string Host { get; private set; }
public int Port { get; private set; } public int Port { get; private set; }
} }

View File

@ -12,6 +12,7 @@ namespace Ocelot.Configuration.File
} }
public List<FileReRoute> ReRoutes { get; set; } public List<FileReRoute> ReRoutes { get; set; }
// Seperate field for aggregates because this let's you re-use ReRoutes in multiple Aggregates // Seperate field for aggregates because this let's you re-use ReRoutes in multiple Aggregates
public List<FileAggregateReRoute> Aggregates { get;set; } public List<FileAggregateReRoute> Aggregates { get;set; }
public FileGlobalConfiguration GlobalConfiguration { get; set; } public FileGlobalConfiguration GlobalConfiguration { get; set; }

View File

@ -1,5 +1,4 @@
 namespace Ocelot.Configuration.File
namespace Ocelot.Configuration.File
{ {
public class FileGlobalConfiguration public class FileGlobalConfiguration
{ {

View File

@ -34,6 +34,4 @@ namespace Ocelot.Configuration.File
/// </summary> /// </summary>
public int HttpStatusCode { get; set; } = 429; public int HttpStatusCode { get; set; } = 429;
} }
} }

View File

@ -6,7 +6,6 @@ using System.Threading.Tasks;
namespace Ocelot.Configuration.File namespace Ocelot.Configuration.File
{ {
public class FileRateLimitRule public class FileRateLimitRule
{ {
public FileRateLimitRule() public FileRateLimitRule()
@ -27,6 +26,7 @@ namespace Ocelot.Configuration.File
public string Period { get; set; } public string Period { get; set; }
public double PeriodTimespan { get; set; } public double PeriodTimespan { get; set; }
/// <summary> /// <summary>
/// Maximum number of requests that a client can make in a defined period /// Maximum number of requests that a client can make in a defined period
/// </summary> /// </summary>
@ -38,6 +38,7 @@ namespace Ocelot.Configuration.File
{ {
return string.Empty; return string.Empty;
} }
var sb = new StringBuilder(); var sb = new StringBuilder();
sb.Append( sb.Append(
$"{nameof(Period)}:{Period},{nameof(PeriodTimespan)}:{PeriodTimespan:F},{nameof(Limit)}:{Limit},{nameof(ClientWhitelist)}:["); $"{nameof(Period)}:{Period},{nameof(PeriodTimespan)}:{PeriodTimespan:F},{nameof(Limit)}:{Limit},{nameof(ClientWhitelist)}:[");

View File

@ -4,5 +4,6 @@ namespace Ocelot.Configuration.File
{ {
public string Host {get;set;} public string Host {get;set;}
public int Port { get; set; } public int Port { get; set; }
public string Type { get; set; }
} }
} }

View File

@ -16,7 +16,6 @@ namespace Ocelot.Configuration
TimeoutStrategy = timeoutStrategy; TimeoutStrategy = timeoutStrategy;
} }
public int ExceptionsAllowedBeforeBreaking { get; private set; } public int ExceptionsAllowedBeforeBreaking { get; private set; }
public int DurationOfBreak { get; private set; } public int DurationOfBreak { get; private set; }
@ -24,6 +23,5 @@ namespace Ocelot.Configuration
public int TimeoutValue { get; private set; } public int TimeoutValue { get; private set; }
public TimeoutStrategy TimeoutStrategy { get; private set; } public TimeoutStrategy TimeoutStrategy { get; private set; }
} }
} }

View File

@ -17,6 +17,7 @@ namespace Ocelot.Configuration
public string Period { get; private set; } public string Period { get; private set; }
public double PeriodTimespan { get; private set; } public double PeriodTimespan { get; private set; }
/// <summary> /// <summary>
/// Maximum number of requests that a client can make in a defined period /// Maximum number of requests that a client can make in a defined period
/// </summary> /// </summary>

View File

@ -9,8 +9,8 @@ namespace Ocelot.Configuration
IsCached = isCached; IsCached = isCached;
IsQos = isQos; IsQos = isQos;
EnableRateLimiting = isEnableRateLimiting; EnableRateLimiting = isEnableRateLimiting;
} }
public bool IsAuthenticated { get; private set; } public bool IsAuthenticated { get; private set; }
public bool IsAuthorised { get; private set; } public bool IsAuthorised { get; private set; }
public bool IsCached { get; private set; } public bool IsCached { get; private set; }

View File

@ -34,7 +34,6 @@ namespace Ocelot.Configuration.Repository
_polling = true; _polling = true;
await Poll(); await Poll();
_polling = false; _polling = false;
}, null, 0, 1000); }, null, 0, 1000);
} }

View File

@ -9,7 +9,6 @@ using Ocelot.ServiceDiscovery;
namespace Ocelot.Configuration.Repository namespace Ocelot.Configuration.Repository
{ {
public class ConsulFileConfigurationRepository : IFileConfigurationRepository public class ConsulFileConfigurationRepository : IFileConfigurationRepository
{ {
private readonly ConsulClient _consul; private readonly ConsulClient _consul;
@ -18,8 +17,8 @@ namespace Ocelot.Configuration.Repository
public ConsulFileConfigurationRepository(Cache.IOcelotCache<FileConfiguration> cache, ServiceProviderConfiguration serviceProviderConfig) public ConsulFileConfigurationRepository(Cache.IOcelotCache<FileConfiguration> cache, ServiceProviderConfiguration serviceProviderConfig)
{ {
var consulHost = string.IsNullOrEmpty(serviceProviderConfig?.ServiceProviderHost) ? "localhost" : serviceProviderConfig?.ServiceProviderHost; var consulHost = string.IsNullOrEmpty(serviceProviderConfig?.Host) ? "localhost" : serviceProviderConfig?.Host;
var consulPort = serviceProviderConfig?.ServiceProviderPort ?? 8500; var consulPort = serviceProviderConfig?.Port ?? 8500;
var configuration = new ConsulRegistryConfiguration(consulHost, consulPort, _ocelotConfiguration); var configuration = new ConsulRegistryConfiguration(consulHost, consulPort, _ocelotConfiguration);
_cache = cache; _cache = cache;
_consul = new ConsulClient(c => _consul = new ConsulClient(c =>

View File

@ -1,14 +0,0 @@
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; }
}
}

View File

@ -0,0 +1,16 @@
namespace Ocelot.Configuration
{
public class ServiceProviderConfiguration
{
public ServiceProviderConfiguration(string type, string host, int port)
{
Host = host;
Port = port;
Type = type;
}
public string Host { get; private set; }
public int Port { get; private set; }
public string Type { get; private set; }
}
}

View File

@ -30,7 +30,7 @@ namespace Ocelot.Configuration.Validator
RuleForEach(configuration => configuration.Aggregates) RuleForEach(configuration => configuration.Aggregates)
.Must((config, aggregateReRoute) => AllReRoutesForAggregateExist(aggregateReRoute, config.ReRoutes)) .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) RuleForEach(configuration => configuration.Aggregates)
.Must((config, aggregateReRoute) => DoesNotContainReRoutesWithSpecificRequestIdKeys(aggregateReRoute, config.ReRoutes)) .Must((config, aggregateReRoute) => DoesNotContainReRoutesWithSpecificRequestIdKeys(aggregateReRoute, config.ReRoutes))

View File

@ -9,7 +9,6 @@ namespace Ocelot.Configuration.Validator
{ {
public FileValidationFailedError(string message) : base(message, OcelotErrorCode.FileValidationFailedError) public FileValidationFailedError(string message) : base(message, OcelotErrorCode.FileValidationFailedError)
{ {
} }
} }
} }

View File

@ -67,6 +67,7 @@ namespace Ocelot.Configuration.Validator
{ {
return true; return true;
} }
var schemes = await _authenticationSchemeProvider.GetAllSchemesAsync(); var schemes = await _authenticationSchemeProvider.GetAllSchemesAsync();
var supportedSchemes = schemes.Select(scheme => scheme.Name).ToList(); var supportedSchemes = schemes.Select(scheme => scheme.Name).ToList();

View File

@ -99,7 +99,6 @@ namespace Ocelot.DependencyInjection
_services.TryAddSingleton<ILoadBalancerFactory, LoadBalancerFactory>(); _services.TryAddSingleton<ILoadBalancerFactory, LoadBalancerFactory>();
_services.TryAddSingleton<ILoadBalancerHouse, LoadBalancerHouse>(); _services.TryAddSingleton<ILoadBalancerHouse, LoadBalancerHouse>();
_services.TryAddSingleton<IOcelotLoggerFactory, AspDotNetLoggerFactory>(); _services.TryAddSingleton<IOcelotLoggerFactory, AspDotNetLoggerFactory>();
_services.TryAddSingleton<IUrlBuilder, UrlBuilder>();
_services.TryAddSingleton<IRemoveOutputHeaders, RemoveOutputHeaders>(); _services.TryAddSingleton<IRemoveOutputHeaders, RemoveOutputHeaders>();
_services.TryAddSingleton<IOcelotConfigurationProvider, OcelotConfigurationProvider>(); _services.TryAddSingleton<IOcelotConfigurationProvider, OcelotConfigurationProvider>();
_services.TryAddSingleton<IClaimToThingConfigurationParser, ClaimToThingConfigurationParser>(); _services.TryAddSingleton<IClaimToThingConfigurationParser, ClaimToThingConfigurationParser>();
@ -154,7 +153,6 @@ namespace Ocelot.DependencyInjection
// We add this here so that we can always inject something into the factory for IoC.. // We add this here so that we can always inject something into the factory for IoC..
_services.AddSingleton<IServiceTracer, FakeServiceTracer>(); _services.AddSingleton<IServiceTracer, FakeServiceTracer>();
} }
public IOcelotAdministrationBuilder AddAdministration(string path, string secret) public IOcelotAdministrationBuilder AddAdministration(string path, string secret)
@ -267,7 +265,6 @@ namespace Ocelot.DependencyInjection
var baseSchemeUrlAndPort = urlFinder.Find(); var baseSchemeUrlAndPort = urlFinder.Find();
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear(); JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
_services.AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme) _services.AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme)
.AddIdentityServerAuthentication(o => .AddIdentityServerAuthentication(o =>
{ {

View File

@ -11,6 +11,7 @@ namespace Ocelot.DownstreamRouteFinder
TemplatePlaceholderNameAndValues = templatePlaceholderNameAndValues; TemplatePlaceholderNameAndValues = templatePlaceholderNameAndValues;
ReRoute = reRoute; ReRoute = reRoute;
} }
public List<PlaceholderNameAndValue> TemplatePlaceholderNameAndValues { get; private set; } public List<PlaceholderNameAndValue> TemplatePlaceholderNameAndValues { get; private set; }
public ReRoute ReRoute { get; private set; } public ReRoute ReRoute { get; private set; }
} }

View File

@ -17,7 +17,6 @@ namespace Ocelot.DownstreamRouteFinder.Middleware
private readonly IOcelotConfigurationProvider _configProvider; private readonly IOcelotConfigurationProvider _configProvider;
private readonly IMultiplexer _multiplexer; private readonly IMultiplexer _multiplexer;
public DownstreamRouteFinderMiddleware(OcelotRequestDelegate next, public DownstreamRouteFinderMiddleware(OcelotRequestDelegate next,
IOcelotLoggerFactory loggerFactory, IOcelotLoggerFactory loggerFactory,
IDownstreamRouteFinder downstreamRouteFinder, IDownstreamRouteFinder downstreamRouteFinder,
@ -61,7 +60,7 @@ namespace Ocelot.DownstreamRouteFinder.Middleware
} }
// todo - put this back in // todo - put this back in
// _logger.LogDebug("downstream template is {downstreamRoute.Data.ReRoute.DownstreamPath}", downstreamRoute.Data.ReRoute.DownstreamReRoute.DownstreamPathTemplate); //// _logger.LogDebug("downstream template is {downstreamRoute.Data.ReRoute.DownstreamPath}", downstreamRoute.Data.ReRoute.DownstreamReRoute.DownstreamPathTemplate);
context.TemplatePlaceholderNameAndValues = downstreamRoute.Data.TemplatePlaceholderNameAndValues; context.TemplatePlaceholderNameAndValues = downstreamRoute.Data.TemplatePlaceholderNameAndValues;

View File

@ -7,6 +7,7 @@ namespace Ocelot.DownstreamRouteFinder.UrlMatcher
Name = name; Name = name;
Value = value; Value = value;
} }
public string Name {get;private set;} public string Name {get;private set;}
public string Value {get;private set;} public string Value {get;private set;}
} }

View File

@ -6,6 +6,7 @@ namespace Ocelot.DownstreamRouteFinder.UrlMatcher
{ {
Match = match; Match = match;
} }
public bool Match {get;private set;} public bool Match {get;private set;}
} }
} }

View File

@ -50,6 +50,7 @@ namespace Ocelot.DownstreamRouteFinder.UrlMatcher
counterForTemplate = endOfPlaceholder; counterForTemplate = endOfPlaceholder;
} }
counterForPath++; counterForPath++;
} }
@ -90,6 +91,7 @@ namespace Ocelot.DownstreamRouteFinder.UrlMatcher
return variableName; return variableName;
} }
private int GetNextCounterPosition(string urlTemplate, int counterForTemplate, char delimiter) private int GetNextCounterPosition(string urlTemplate, int counterForTemplate, char delimiter)
{ {
var closingPlaceHolderPositionOnTemplate = urlTemplate.IndexOf(delimiter, counterForTemplate); var closingPlaceHolderPositionOnTemplate = urlTemplate.IndexOf(delimiter, counterForTemplate);

View File

@ -1,4 +1,5 @@
using Ocelot.Responses; /*
using Ocelot.Responses;
using Ocelot.Values; using Ocelot.Values;
namespace Ocelot.DownstreamUrlCreator namespace Ocelot.DownstreamUrlCreator
@ -8,3 +9,4 @@ namespace Ocelot.DownstreamUrlCreator
Response<DownstreamUrl> Build(string downstreamPath, string downstreamScheme, ServiceHostAndPort downstreamHostAndPort); Response<DownstreamUrl> Build(string downstreamPath, string downstreamScheme, ServiceHostAndPort downstreamHostAndPort);
} }
} }
*/

View File

@ -5,7 +5,10 @@ using Ocelot.Infrastructure.RequestData;
using Ocelot.Logging; using Ocelot.Logging;
using Ocelot.Middleware; using Ocelot.Middleware;
using System; using System;
using System.Linq;
using Ocelot.DownstreamRouteFinder.Middleware; using Ocelot.DownstreamRouteFinder.Middleware;
using Ocelot.Responses;
using Ocelot.Values;
namespace Ocelot.DownstreamUrlCreator.Middleware namespace Ocelot.DownstreamUrlCreator.Middleware
{ {
@ -14,16 +17,13 @@ namespace Ocelot.DownstreamUrlCreator.Middleware
private readonly OcelotRequestDelegate _next; private readonly OcelotRequestDelegate _next;
private readonly IDownstreamPathPlaceholderReplacer _replacer; private readonly IDownstreamPathPlaceholderReplacer _replacer;
private readonly IOcelotLogger _logger; private readonly IOcelotLogger _logger;
private readonly IUrlBuilder _urlBuilder;
public DownstreamUrlCreatorMiddleware(OcelotRequestDelegate next, public DownstreamUrlCreatorMiddleware(OcelotRequestDelegate next,
IOcelotLoggerFactory loggerFactory, IOcelotLoggerFactory loggerFactory,
IDownstreamPathPlaceholderReplacer replacer, IDownstreamPathPlaceholderReplacer replacer)
IUrlBuilder urlBuilder)
{ {
_next = next; _next = next;
_replacer = replacer; _replacer = replacer;
_urlBuilder = urlBuilder;
_logger = loggerFactory.CreateLogger<DownstreamUrlCreatorMiddleware>(); _logger = loggerFactory.CreateLogger<DownstreamUrlCreatorMiddleware>();
} }
@ -40,11 +40,20 @@ namespace Ocelot.DownstreamUrlCreator.Middleware
return; return;
} }
var uriBuilder = new UriBuilder(context.DownstreamRequest.RequestUri) UriBuilder uriBuilder;
if (ServiceFabricRequest(context))
{
uriBuilder = CreateServiceFabricUri(context, dsPath);
}
else
{
uriBuilder = new UriBuilder(context.DownstreamRequest.RequestUri)
{ {
Path = dsPath.Data.Value, Path = dsPath.Data.Value,
Scheme = context.DownstreamReRoute.DownstreamScheme Scheme = context.DownstreamReRoute.DownstreamScheme
}; };
}
context.DownstreamRequest.RequestUri = uriBuilder.Uri; context.DownstreamRequest.RequestUri = uriBuilder.Uri;
@ -52,5 +61,38 @@ namespace Ocelot.DownstreamUrlCreator.Middleware
await _next.Invoke(context); await _next.Invoke(context);
} }
private UriBuilder CreateServiceFabricUri(DownstreamContext context, Response<DownstreamPath> 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");
}
} }
} }

View File

@ -1,4 +1,5 @@
using System; /*
using System;
using System.Collections.Generic; using System.Collections.Generic;
using Ocelot.Errors; using Ocelot.Errors;
using Ocelot.Responses; using Ocelot.Responses;
@ -25,12 +26,11 @@ namespace Ocelot.DownstreamUrlCreator
return new ErrorResponse<DownstreamUrl>(new List<Error> { new DownstreamHostNullOrEmptyError() }); return new ErrorResponse<DownstreamUrl>(new List<Error> { new DownstreamHostNullOrEmptyError() });
} }
var builder = new UriBuilder var builder = new UriBuilder
{ {
Host = downstreamHostAndPort.DownstreamHost, Host = downstreamHostAndPort.DownstreamHost,
Path = downstreamPath, Path = downstreamPath,
Scheme = downstreamScheme Scheme = downstreamScheme,
}; };
if (downstreamHostAndPort.DownstreamPort > 0) if (downstreamHostAndPort.DownstreamPort > 0)
@ -44,3 +44,4 @@ namespace Ocelot.DownstreamUrlCreator
} }
} }
} }
*/

View File

@ -100,6 +100,7 @@ namespace Ocelot.Errors.Middleware
message = message =
$"{message}, inner exception message {e.InnerException.Message}, inner exception stack {e.InnerException.StackTrace}"; $"{message}, inner exception message {e.InnerException.Message}, inner exception stack {e.InnerException.StackTrace}";
} }
return $"{message} RequestId: {context.HttpContext.TraceIdentifier}"; return $"{message} RequestId: {context.HttpContext.TraceIdentifier}";
} }
} }

View File

@ -26,6 +26,7 @@ namespace Ocelot.Headers
return $"{downstreamUrl}/"; return $"{downstreamUrl}/";
}); });
} }
public Response Replace(HttpResponseMessage response, List<HeaderFindAndReplace> fAndRs, HttpRequestMessage httpRequestMessage) public Response Replace(HttpResponseMessage response, List<HeaderFindAndReplace> fAndRs, HttpRequestMessage httpRequestMessage)
{ {
foreach (var f in fAndRs) foreach (var f in fAndRs)

View File

@ -37,7 +37,6 @@
return new OkResponse<string>(value); return new OkResponse<string>(value);
} }
public Response<List<string>> GetValuesByClaimType(IEnumerable<Claim> claims, string claimType) public Response<List<string>> GetValuesByClaimType(IEnumerable<Claim> claims, string claimType)
{ {
List<string> values = new List<string>(); List<string> values = new List<string>();
@ -47,7 +46,6 @@
return new OkResponse<List<string>>(values); return new OkResponse<List<string>>(values);
} }
private Response<string> GetValue(IEnumerable<Claim> claims, string key) private Response<string> GetValue(IEnumerable<Claim> claims, string key)
{ {
var claim = claims.FirstOrDefault(c => c.Type == key); var claim = claims.FirstOrDefault(c => c.Type == key);

View File

@ -9,6 +9,7 @@ namespace Ocelot.LoadBalancer.LoadBalancers
HostAndPort = hostAndPort; HostAndPort = hostAndPort;
Connections = connections; Connections = connections;
} }
public ServiceHostAndPort HostAndPort { get; private set; } public ServiceHostAndPort HostAndPort { get; private set; }
public int Connections { get; private set; } public int Connections { get; private set; }
} }

Some files were not shown because too many files have changed in this diff Show More