diff --git a/README.md b/README.md index 84617f637..3aa57d7e3 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ # Ocelot -Ocelot is a .NET API Gateway. This project is aimed at people using .NET running a micro services / service oriented architecture +Ocelot is a .NET API Gateway. This project is aimed at people using .NET running a microservices / service-oriented architecture that need a unified point of entry into their system. However it will work with anything that speaks HTTP and run on any platform that ASP.NET Core supports. In particular I want easy integration with IdentityServer reference and bearer tokens. @@ -15,7 +15,11 @@ We have been unable to find this in my current workplace without having to write Ocelot is a bunch of middlewares in a specific order. -Ocelot manipulates the HttpRequest object into a state specified by its configuration until it reaches a request builder middleware where it creates a HttpRequestMessage object which is used to make a request to a downstream service. The middleware that makes the request is the last thing in the Ocelot pipeline. It does not call the next middleware. The response from the downstream service is retrieved as the requests goes back up the Ocelot pipeline. There is a piece of middleware that maps the HttpResponseMessage onto the HttpResponse object and that is returned to the client. That is basically it with a bunch of other features! +Ocelot manipulates the `HttpRequest` object into a state specified by its configuration until it reaches a request builder middleware, where it creates a `HttpRequestMessage` object which is used to make a request to a downstream service. +The middleware that makes the request is the last thing in the Ocelot pipeline. It does not call the next middleware. +The response from the downstream service is retrieved as the requests goes back up the Ocelot pipeline. +There is a piece of middleware that maps the `HttpResponseMessage` onto the `HttpResponse` object and that is returned to the client. +That is basically it with a bunch of other features! ## Features @@ -39,19 +43,21 @@ A quick list of Ocelot's capabilities for more information see the [documentatio * Configuration / Administration REST API * Platform / Cloud Agnostic -## How to install +## Install Ocelot is designed to work with ASP.NET and it targets `net7.0`. -Install Ocelot and it's dependencies using NuGet. +Install Ocelot and its dependencies using NuGet Package Manager: +```powershell +Install-Package Ocelot +``` -`Install-Package Ocelot` +Or via the .NET CLI: +```shell +dotnet add package Ocelot +``` -Or via the .NET Core CLI: - -`dotnet add package ocelot` - -All versions can be found [here](https://www.nuget.org/packages/Ocelot/) +All versions can be found [here](https://www.nuget.org/packages/Ocelot/). ## Documentation @@ -67,6 +73,6 @@ We love to receive contributions from the community so please keep them coming : Pull requests, issues and commentary welcome! -Please complete the relevant 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 :) +Please complete the relevant template for issues and PRs. Sometimes it's worth getting in touch with us to discuss changes before doing any work in case 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 contribute for the first time I suggest looking at a help wanted & small effort issue :) diff --git a/docs/building/building.rst b/docs/building/building.rst index 4544eccd9..460380092 100644 --- a/docs/building/building.rst +++ b/docs/building/building.rst @@ -3,8 +3,9 @@ Building * You can also just run `dotnet tool restore && dotnet cake` locally!. Output will got to the `./artifacts` directory. -* The best way to replicate the CI process is to build Ocelot locally is using the Dockerfile.build file which can be found in the docker folder in Ocelot root. Use the following command `docker build --platform linux/amd64 -f ./docker/Dockerfile.build .` for example. You will need to change the platform flag depending on your platform. +* The best way to replicate the CI process is to build Ocelot locally is using the Dockerfile.build file which can be found in the docker folder in Ocelot root. + Use the following command ``docker build --platform linux/amd64 -f ./docker/Dockerfile.build .`` for example. You will need to change the platform flag depending on your platform. -* There is a Makefile to make it easier to call the various targers in `build.cake`. The scripts are called with .sh but can be easily changed to ps1 if you are using Windows. +* There is a Makefile to make it easier to call the various targets in `build.cake`. The scripts are called with **.sh** but can be easily changed to **.ps1** if you are using Windows. -* Alternatively you can build the project in VS2022 with the latest .NET 7.0 SDK. \ No newline at end of file +* Alternatively you can build the project in VS2022 with the latest .NET 7.0 SDK. diff --git a/docs/features/authentication.rst b/docs/features/authentication.rst index e41c0033a..af4f6dea8 100644 --- a/docs/features/authentication.rst +++ b/docs/features/authentication.rst @@ -172,6 +172,6 @@ NOTE: In order to get Ocelot to view the scope claim from Okta properly, you hav Allowed Scopes ^^^^^^^^^^^^^ -If you add scopes to AllowedScopes Ocelot will get all the user claims (from the token) of the type scope and make sure that the user has all of the scopes in the list. +If you add scopes to AllowedScopes Ocelot will get all the user claims (from the token) of the type scope and make sure that the user has at least one of the scopes in the list. This is a way to restrict access to a Route on a per scope basis. diff --git a/docs/features/authorization.rst b/docs/features/authorization.rst index c890c14c0..1510e131e 100644 --- a/docs/features/authorization.rst +++ b/docs/features/authorization.rst @@ -1,7 +1,7 @@ Authorization ============= -Ocelot supports claims based authorization which is run post authentication. This means if you have a route you want to authorize you can add the following to you Route configuration. +Ocelot supports claims based authorization which is run post authentication. This means if you have a route you want to authorize you can add the following to your Route configuration. .. code-block:: json @@ -9,7 +9,4 @@ Ocelot supports claims based authorization which is run post authentication. Thi "UserType": "registered" } -In this example when the authorization middleware is called Ocelot will check to seeif the user has the claim type UserType and if the value of that claim is registered. If it isn't then the user will not be authorized and the response will be 403 forbidden. - - - +In this example when the authorization middleware is called Ocelot will check to see if the user has the claim type UserType and if the value of that claim is registered. If it isn't then the user will not be authorized and the response will be 403 forbidden. diff --git a/docs/features/caching.rst b/docs/features/caching.rst index f6c2a7fd2..0a1cac37b 100644 --- a/docs/features/caching.rst +++ b/docs/features/caching.rst @@ -1,7 +1,7 @@ Caching ======= -Ocelot supports some very rudimentary caching at the moment provider by the `CacheManager `_ project. This is an amazing project that is solving a lot of caching problems. I would reccomend using this package to cache with Ocelot. +Ocelot supports some very rudimentary caching at the moment provider by the `CacheManager `_ project. This is an amazing project that is solving a lot of caching problems. I would recommend using this package to cache with Ocelot. The following example shows how to add CacheManager to Ocelot so that you can do output caching. @@ -15,6 +15,8 @@ The second thing you need to do something like the following to your ConfigureSe .. code-block:: csharp + using Ocelot.Cache.CacheManager; + s.AddOcelot() .AddCacheManager(x => { diff --git a/docs/features/claimstransformation.rst b/docs/features/claimstransformation.rst index c82657a4c..07e949e80 100644 --- a/docs/features/claimstransformation.rst +++ b/docs/features/claimstransformation.rst @@ -3,20 +3,21 @@ Claims Transformation Ocelot allows the user to access claims and transform them into headers, query string parameters, other claims and change downstream paths. This is only available once a user has been authenticated. -After the user is authenticated we run the claims to claims transformation middleware. This allows the user to transform claims before the authorization middleware is called. After the user is authorized first we call the claims to headers middleware, thenthe claims to query string parameters middleware, and Finally the claims to downstream pathmiddleware. +After the user is authenticated, we run the claims to claims transformation middleware. This allows the user to transform claims before the authorisation middleware is called. +After the user is authorized, we call the claims to headers middleware, then the claims to query string parameters middleware, and finally the claims to downstream path middleware. -The syntax for performing the transforms is the same for each process. In the Route configuration a json dictionary is added with a specific name either AddClaimsToRequest, AddHeadersToRequest, AddQueriesToRequest, or ChangeDownstreamPathTemplate. +The syntax for performing the transforms is the same for each process. In the Route configuration, a json dictionary is added with a specific name either AddClaimsToRequest, AddHeadersToRequest, AddQueriesToRequest, or ChangeDownstreamPathTemplate. Note: I'm not a hotshot programmer so have no idea if this syntax is good... Within this dictionary the entries specify how Ocelot should transform things! The key to the dictionary is going to become the key of either a claim, header or query parameter. In the case of ChangeDownstreamPathTemplate, the key must be also specified in the DownstreamPathTemplate, in order to do the transformation. -The value of the entry is parsed to logic that will perform the transform. First ofall a dictionary accessor is specified e.g. Claims[CustomerId]. This means we want to access the claims and get the CustomerId claim type. Next is a greater than (>)symbol which is just used to split the string. The next entry is either value or value with an indexer. If value is specified Ocelot will just take the value and add it to the transform. If the value has an indexer Ocelot will look for a delimiter which is provided after another greater than symbol. Ocelot will then split the value on the delimiter and add whatever was at the index requested to the transform. +The value of the entry is parsed to logic that will perform the transform. First of all a dictionary accessor is specified e.g. Claims[CustomerId]. This means we want to access the claims and get the CustomerId claim type. Next is a greater than (>) symbol which is just used to split the string. The next entry is either value or value with an indexer. If value is specified, Ocelot will just take the value and add it to the transform. If the value has an indexer, Ocelot will look for a delimiter which is provided after another greater than (>) symbol. Ocelot will then split the value on the delimiter and add whatever was at the index requested to the transform. Claims to Claims Transformation ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Below is an example configuration that will transforms claims to claims +Below is an example configuration that will transform claims to claims .. code-block:: json @@ -30,7 +31,7 @@ This shows a transforms where Ocelot looks at the users sub claim and transforms Claims to Headers Tranformation ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Below is an example configuration that will transforms claims to headers +Below is an example configuration that will transform claims to headers .. code-block:: json @@ -43,7 +44,7 @@ This shows a transform where Ocelot looks at the users sub claim and transforms Claims to Query String Parameters Transformation ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Below is an example configuration that will transforms claims to query string parameters +Below is an example configuration that will transform claims to query string parameters .. code-block:: json @@ -56,7 +57,7 @@ This shows a transform where Ocelot looks at the users LocationId claim and add Claims to Downstream Path Transformation ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Below is an example configuration that will transform claims to downstream path custom placeholders +Below is an example configuration that will transform claims to downstream path custom placeholders: .. code-block:: json @@ -69,4 +70,4 @@ Below is an example configuration that will transform claims to downstream path This shows a transform where Ocelot looks at the users userId claim and substitutes the value to the "{userId}" placeholder specified in the DownstreamPathTemplate. Take into account that the key specified in the ChangeDownstreamPathTemplate must be the same than the placeholder specified in the DownstreamPathTemplate. -Note: if a key specified in the ChangeDownstreamPathTemplate does not exist as a placeholder in DownstreamPathTemplate it will fail at runtime returning an error in the response. \ No newline at end of file +Note: if a key specified in the ChangeDownstreamPathTemplate does not exist as a placeholder in DownstreamPathTemplate it will fail at runtime returning an error in the response. diff --git a/docs/features/configuration.rst b/docs/features/configuration.rst index 05fa81afd..83a49d9f6 100644 --- a/docs/features/configuration.rst +++ b/docs/features/configuration.rst @@ -31,6 +31,10 @@ Here is an example Route configuration, You don't need to set all of these thing "TtlSeconds": 0, "Region": "" }, + "SecurityOptions": { + "IPAllowedList": [], + "IPBlockedList": [] + }, "RouteIsCaseSensitive": false, "ServiceName": "", "DownstreamScheme": "http", @@ -139,7 +143,7 @@ Store configuration in Consul ----------------------------- The first thing you need to do is install the NuGet package that provides Consul support in Ocelot. - + .. code-block:: powershell Install-Package Ocelot.Provider.Consul diff --git a/docs/features/errorcodes.rst b/docs/features/errorcodes.rst index d07eb3a49..a9fffd2a6 100644 --- a/docs/features/errorcodes.rst +++ b/docs/features/errorcodes.rst @@ -1,13 +1,19 @@ -Http Error Status Codes +HTTP Error Status Codes ======================= -Ocelot will return HTTP status error codes based on internal logic in certain siturations: -- 401 if the authentication middleware runs and the user is not authenticated. -- 403 if the authorization middleware runs and the user is unauthenticated, claim value not authroised, scope not authorized, user doesnt have required claim or cannot find claim. -- 503 if the downstream request times out. -- 499 if the request is cancelled by the client. -- 404 if unable to find a downstream route. -- 502 if unable to connect to downstream service. -- 500 if unable to complete the HTTP request downstream and the exception is not OperationCanceledException or HttpRequestException. -- 404 if Ocelot is unable to map an internal error code to a HTTP status code. +Ocelot will return HTTP status error codes based on internal logic in certain situations: +Client error responses +---------------------- + +- **401** - if the authentication middleware runs and the user is not authenticated. +- **403** - if the authorization middleware runs and the user is unauthenticated, claim value not authorized, scope not authorized, user doesn't have required claim, or cannot find claim. +- **404** - if unable to find a downstream route, or Ocelot is unable to map an internal error code to a HTTP status code. +- **499** - if the request is cancelled by the client. + +Server error responses +---------------------- + +- **500** - if unable to complete the HTTP request to downstream service, and the exception is not ``OperationCanceledException`` or ``HttpRequestException``. +- **502** - if unable to connect to downstream service. +- **503** - if the downstream request times out. diff --git a/docs/features/headerstransformation.rst b/docs/features/headerstransformation.rst index a7f9d50a0..0250a0fd8 100644 --- a/docs/features/headerstransformation.rst +++ b/docs/features/headerstransformation.rst @@ -6,7 +6,7 @@ Ocelot allows the user to transform headers pre and post downstream request. At Add to Request ^^^^^^^^^^^^^^ -This feature was requestes in `GitHub #313 `_. +This feature was requested in `GitHub #313 `_. If you want to add a header to your upstream request please add the following to a Route in your ocelot.json: @@ -141,10 +141,10 @@ Ideally this feature would be able to support the fact that a header can have mu .. code-block:: json "DownstreamHeaderTransform": { - "Location": "[{one,one},{two,two}" + "Location": "[{one,one},{two,two}]" }, "HttpHandlerOptions": { "AllowAutoRedirect": false, }, -If anyone wants to have a go at this please help yourself!! +If anyone wants to have a go at this please help yourself! diff --git a/docs/features/loadbalancer.rst b/docs/features/loadbalancer.rst index a4ec4ad91..af4067bbd 100644 --- a/docs/features/loadbalancer.rst +++ b/docs/features/loadbalancer.rst @@ -104,7 +104,7 @@ Please note that if you give more than one DownstreamHostAndPort or you are usin Custom Load Balancers ^^^^^^^^^^^^^^^^^^^^ -`DavidLievrouw `_ implemented a way to provide Ocelot with custom load balancer in `PR 1155 `_. In order to create and use a custom load balancer you can do the following. Below we setup a basic load balancing config and not the Type is CustomLoadBalancer this is the name of a class we will setup to do load balancing. @@ -135,11 +135,10 @@ Then you need to create a class that implements the ILoadBalancer interface. Bel .. code-block:: csharp - private class CustomLoadBalancer : ILoadBalancer + public class CustomLoadBalancer : ILoadBalancer { private readonly Func>> _services; private readonly object _lock = new object(); - private int _last; public CustomLoadBalancer(Func>> services) @@ -147,25 +146,20 @@ Then you need to create a class that implements the ILoadBalancer interface. Bel _services = services; } - public async Task> Lease(DownstreamContext downstreamContext, HttpContext httpContext) + public async Task> Lease(HttpContext httpContext) { var services = await _services(); lock (_lock) { if (_last >= services.Count) - { _last = 0; - } - var next = services[_last]; - _last++; + var next = services[_last++]; return new OkResponse(next.HostAndPort); } } - public void Release(ServiceHostAndPort hostAndPort) - { - } + public void Release(ServiceHostAndPort hostAndPort) { } } Finally you need to register this class with Ocelot. I have used the most complex example below to show all of the data / types that can be passed into the factory that creates load balancers. @@ -207,4 +201,4 @@ There are numerous extension methods to add a custom load balancer and the inter When you enable custom load balancers Ocelot looks up your load balancer by its class name when it decides if it should do load balancing. If it finds a match it will use your load balaner to load balance. If Ocelot cannot match the load balancer type in your configuration with the name of registered load balancer class then you will receive a HTTP 500 internal server error. If your load balancer factory throw an exception when Ocelot calls it you will receive a HTTP 500 internal server error. -Remember if you specify no load balancer in your config Ocelot will not try and load balance. \ No newline at end of file +Remember if you specify no load balancer in your config Ocelot will not try and load balance. diff --git a/docs/features/logging.rst b/docs/features/logging.rst index c79c7743d..f92a04377 100644 --- a/docs/features/logging.rst +++ b/docs/features/logging.rst @@ -1,17 +1,22 @@ Logging ======= -Ocelot uses the standard logging interfaces ILoggerFactory / ILogger at the moment. This is encapsulated in IOcelotLogger / IOcelotLoggerFactory with an implementation -for the standard asp.net core logging stuff at the moment. This is because Ocelot add's some extra info to the logs such as request id if it is configured. +Ocelot uses the standard logging interfaces ``ILoggerFactory`` and ``ILogger`` at the moment. +This is encapsulated in ``IOcelotLogger`` and ``IOcelotLoggerFactory`` with an implementation for the standard ASP.NET Core logging stuff at the moment. +This is because Ocelot adds some extra info to the logs such as **request ID** if it is configured. There is a global error handler that should catch any exceptions thrown and log them as errors. -Finally if logging is set to trace level Ocelot will log starting, finishing and any middlewares that throw an exception which can be quite useful. +Finally, if logging is set to trace level, Ocelot will log starting, finishing and any middlewares that throw an exception which can be quite useful. -The reason for not just using bog standard framework logging is that I could not work out how to override the request id that get's logged when setting IncludeScopes -to true for logging settings. Nicely onto the next feature. +The reason for not just using `bog standard `_ framework logging is that +I could not work out how to override the request id that get's logged when setting **IncludeScopes** to ``true`` for logging settings. +Nicely onto the next feature. Warning -^^^^^^^ +------- -If you are logging to Console you will get terrible performance. I have had so many issues about performance issues with Ocelot and it is always logging level Debug, logging to Console :) Make sure you are logging to something proper in production :) +If you are logging to `Console `_ you will get terrible performance. +I have had so many issues about performance issues with Ocelot and it is always logging level Debug, logging to `Console `_. + +* **Warning!** Make sure you are logging to something proper in production environment! diff --git a/docs/features/methodtransformation.rst b/docs/features/methodtransformation.rst index b1fc8cd32..0748e6fd2 100644 --- a/docs/features/methodtransformation.rst +++ b/docs/features/methodtransformation.rst @@ -18,11 +18,11 @@ This achieved by setting the following Route configuration: "DownstreamHostAndPorts": [ { "Host": "localhost", - "Port": 53271 + "Port": 54321 } ], } -The key property here is DownstreamHttpMethod which is set as POST and the Route will only match on GET as set by UpstreamHttpMethod. +The key property here is **DownstreamHttpMethod** which is set as POST and the Route will only match on GET as set by **UpstreamHttpMethod**. -This feature can be useful when interacting with downstream apis that only support POST and you want to present some kind of RESTful interface. \ No newline at end of file +This feature can be useful when interacting with downstream APIs that only support POST and you want to present some kind of RESTful interface. diff --git a/docs/features/middlewareinjection.rst b/docs/features/middlewareinjection.rst index 7fccc599b..811cc4ce2 100644 --- a/docs/features/middlewareinjection.rst +++ b/docs/features/middlewareinjection.rst @@ -37,5 +37,32 @@ The user can set functions against the following. * PreQueryStringBuilderMiddleware - This allows the user to manipulate the query string on the http request before it is passed to Ocelots request creator. -Obviously you can just add middleware as normal before the call to app.UseOcelot() It cannot be added -after as Ocelot does not call the next middleware. +Obviously you can just add mentioned Ocelot's middleware overridings as normal before the call to ``app.UseOcelot()``. +It cannot be added after as Ocelot does not call the next Ocelot's middleware overridings based on specified middleware configuration. +So, the next called middlewares won't affect Ocelot configuration. + +ASP.NET Core Middlewares and Ocelot Pipeline Builder +---------------------------------------------------- + +Ocelot pipeline is a part of entire `ASP.NET Core Middlewares `_ conveyor aka app pipeline. +The `BuildOcelotPipeline `_ method encapsulates Ocelot pipeline. +The last middleware in the **BuildOcelotPipeline** method is **HttpRequesterMiddleware** that calls the next middleware. + +The internal `HttpRequesterMiddleware `_ is part of the pipeline but it is private and cannot be overridden, since this middleware does not belong to the list of user's one that can be overridden! +So, this is `the last middleware `_ of the entire Ocelot and ASP.NET pipeline, and it handles non-user operation. +The last user middleware that can be overridden is `PreQueryStringBuilderMiddleware `_ being read from the `pipeline configuration object `_, see previous section. + +Considering that **PreQueryStringBuilderMiddleware** and **HttpRequesterMiddleware** are the last user and system middlewares, there are no other middlewares in the pipeline at all. +But you can still extend the ASP.NET pipeline, as shown in the following code: + +.. code-block:: csharp + + app.UseOcelot().Wait(); + app.UseMiddleware(); + +But we do not recommend adding this custom middleware before or after calling of ``UseOcelot()`` as it affects the stability of the entire pipeline and has not been tested. +Such kind of custom pipeline building is out of the Ocelot pipeline model and the quality of the solution is at your own risk. + +Finally, don't get confused about the distinction between system (private) and user (public) middlewares. +Private middlewares are hidden and cannot be overridden, but the entire ASP.NET pipeline can still be extended. +The public middlewares are fully customizable and can be overridden. diff --git a/docs/features/requestaggregation.rst b/docs/features/requestaggregation.rst index 98ffd410e..76bc7a963 100644 --- a/docs/features/requestaggregation.rst +++ b/docs/features/requestaggregation.rst @@ -5,7 +5,7 @@ Ocelot allows you to specify Aggregate Routes that compose multiple normal Route a client that is making multiple requests to a server where it could just be one. This feature allows you to start implementing back end for a front end type architecture with Ocelot. -This feature was requested as part of `Issue 79 `_ and further improvements were made as part of `Issue 298 `_. +This feature was requested as part of `Issue 79 `_ and further improvements were made as part of `Issue 298 `_. In order to set this up you must do something like the following in your **ocelot.json**. Here we have specified two normal Routes and each one has a Key property. We then specify an Aggregate that composes the two Routes using their keys in the RouteKeys list and says then we have the UpstreamPathTemplate which works like a normal Route. diff --git a/docs/features/routing.rst b/docs/features/routing.rst index 30e42a82b..8f232c780 100644 --- a/docs/features/routing.rst +++ b/docs/features/routing.rst @@ -1,10 +1,11 @@ Routing ======= -Ocelot's primary functionality is to take incoming http requests and forward them on to a downstream service. Ocelot currently only supports this in the form of another http request (in the future -this could be any transport mechanism). +Ocelot's primary functionality is to take incoming HTTP requests and forward them on to a downstream service. +Ocelot currently only supports this in the form of another HTTP request (in the future this could be any transport mechanism). -Ocelot's describes the routing of one request to another as a Route. In order to get anything working in Ocelot you need to set up a Route in the configuration. +Ocelot describes the routing of one request to another as a Route. +In order to get anything working in Ocelot you need to set up a Route in the configuration. .. code-block:: json diff --git a/docs/features/servicediscovery.rst b/docs/features/servicediscovery.rst index 94b993cdf..9b2b158bd 100644 --- a/docs/features/servicediscovery.rst +++ b/docs/features/servicediscovery.rst @@ -23,7 +23,7 @@ Then add the following to your ConfigureServices method. 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. -Please note the Scheme option defauls to HTTP. It was added in this `PR `_. It defaults to HTTP to not introduce a breaking change. +Please note the Scheme option defaults to HTTP. It was added in this `PR `_. It defaults to HTTP to not introduce a breaking change. .. code-block:: json diff --git a/docs/features/websockets.rst b/docs/features/websockets.rst index ad185f297..2c0e6961f 100644 --- a/docs/features/websockets.rst +++ b/docs/features/websockets.rst @@ -66,7 +66,7 @@ Then in your ocelot.json add the following to proxy a Route using SignalR. Note "DownstreamHostAndPorts": [ { "Host": "localhost", - "Port": 50000 + "Port": 5001 } ], "UpstreamPathTemplate": "/gateway/{catchAll}", diff --git a/docs/introduction/bigpicture.rst b/docs/introduction/bigpicture.rst index ee56f0efa..fbb5b12c9 100644 --- a/docs/introduction/bigpicture.rst +++ b/docs/introduction/bigpicture.rst @@ -1,7 +1,7 @@ Big Picture =========== -Ocelot is aimed at people using .NET running a micro services / service orientated architecture that need a unified point of entry into their system. +Ocelot is aimed at people using .NET running a microservices / service-oriented architecture that need a unified point of entry into their system. In particular I want easy integration with IdentityServer reference and bearer tokens. diff --git a/docs/introduction/gettingstarted.rst b/docs/introduction/gettingstarted.rst index c2b388750..86d580a36 100644 --- a/docs/introduction/gettingstarted.rst +++ b/docs/introduction/gettingstarted.rst @@ -10,12 +10,14 @@ Install NuGet package ^^^^^^^^^^^^^^^^^^^^^ Install Ocelot and it's dependencies using `nuget `_. -You will need to create `a net7.0 project `_ and bring the package into it. +You will need to create a `net7.0 project `_ and bring the package into it. Then follow the Startup below and :doc:`../features/configuration` sections to get up and running. - ``Install-Package Ocelot`` +.. code-block:: powershell -All versions can be found `here `_. + Install-Package Ocelot + +All versions can be found in the `NuGet Gallery | Ocelot `_. Configuration ^^^^^^^^^^^^^ diff --git a/src/Ocelot/RateLimit/Middleware/ClientRateLimitMiddleware.cs b/src/Ocelot/RateLimit/Middleware/ClientRateLimitMiddleware.cs index f69a45893..63d6b2f95 100644 --- a/src/Ocelot/RateLimit/Middleware/ClientRateLimitMiddleware.cs +++ b/src/Ocelot/RateLimit/Middleware/ClientRateLimitMiddleware.cs @@ -140,7 +140,7 @@ public virtual DownstreamResponse ReturnQuotaExceededResponse(HttpContext httpCo private static string GetResponseMessage(RateLimitOptions option) { var message = string.IsNullOrEmpty(option.QuotaExceededMessage) - ? $"API calls quota exceeded! Maximum admitted {option.RateLimitRule.Limit} per {option.RateLimitRule.Period}." + ? $"API calls quota exceeded! maximum admitted {option.RateLimitRule.Limit} per {option.RateLimitRule.Period}." : option.QuotaExceededMessage; return message; }