{"id":13445469,"url":"https://github.com/ProxyKit/ProxyKit","last_synced_at":"2025-03-20T21:30:36.763Z","repository":{"id":49035955,"uuid":"149996573","full_name":"ProxyKit/ProxyKit","owner":"ProxyKit","description":"A toolkit to create code-first HTTP reverse proxies on ASP.NET Core","archived":true,"fork":false,"pushed_at":"2020-10-23T13:57:56.000Z","size":699,"stargazers_count":1114,"open_issues_count":0,"forks_count":134,"subscribers_count":44,"default_branch":"master","last_synced_at":"2024-10-08T13:08:12.136Z","etag":null,"topics":["aspnetcore","dotnet","middleware","obsolete-soon","proxy","reverse-proxy","serverless"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ProxyKit.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-09-23T15:18:32.000Z","updated_at":"2024-10-06T16:49:08.000Z","dependencies_parsed_at":"2022-07-26T06:02:04.395Z","dependency_job_id":null,"html_url":"https://github.com/ProxyKit/ProxyKit","commit_stats":null,"previous_names":["damianh/proxykit"],"tags_count":24,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ProxyKit%2FProxyKit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ProxyKit%2FProxyKit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ProxyKit%2FProxyKit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ProxyKit%2FProxyKit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ProxyKit","download_url":"https://codeload.github.com/ProxyKit/ProxyKit/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":221331143,"owners_count":16799322,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aspnetcore","dotnet","middleware","obsolete-soon","proxy","reverse-proxy","serverless"],"created_at":"2024-07-31T05:00:34.193Z","updated_at":"2025-03-20T21:30:36.757Z","avatar_url":"https://github.com/ProxyKit.png","language":"C#","funding_links":[],"categories":["Frameworks, Libraries and Tools","C#","C# #","dotnet","C\\#","serverless"],"sub_categories":["Distributed Computing"],"readme":"# ProxyKit\n\n![Image](logo.png)\n\n[![Build Status](https://img.shields.io/endpoint.svg?url=https%3A%2F%2Factions-badge.atrox.dev%2Fproxykit%2FProxyKit%2Fbadge%3Fref%3Dmaster\u0026style=flat\u0026label=build)](https://actions-badge.atrox.dev/proxykit/ProxyKit/goto?ref=master)\n[![NuGet][nuget badge]][nuget package]\n[![Feedz][feedz badge]][feedz package]\n\n⚠️ **ProxyKit is obsolescent.** See [announcement](https://github.com/ProxyKit/ProxyKit/issues/230). Migrate to [YARP](https://github.com/microsoft/reverse-proxy).\n\nA toolkit to create code-first **HTTP Reverse Proxies** hosted in ASP.NET Core as middleware. This\nallows focused code-first proxies that can be embedded in existing ASP.NET Core\napplications or deployed as a standalone server. Deployable anywhere ASP.NET\nCore is deployable such as Windows, Linux, Containers and Serverless (with\ncaveats).\n\nHaving built proxies many times before, I felt it is time to make a package. Forked\nfrom [ASP.NET labs][aspnet labs], it has been heavily modified with a different\nAPI, to facilitate a wider variety of proxying scenarios (i.e. routing based on\na JWT claim) and interception of the proxy requests / responses for\ncustomization of headers and (optionally) request / response bodies. It also\nuses [`HttpClientFactory`] internally that will mitigate against DNS caching\nissues making it suitable for microservice / container environments.\n\n\u003c!-- TOC depthFrom:2 --\u003e\n\n- [1. Quick Start](#1-quick-start)\n    - [1.1. Install](#11-install)\n    - [1.2. Forward HTTP Requests](#12-forward-http-requests)\n    - [1.3. Forward WebSocket Requests](#13-forward-websocket-requests)\n- [2. Core Features](#2-core-features)\n    - [2.1. Customising the upstream HTTP request](#21-customising-the-upstream-http-request)\n    - [2.2. Customising the upstream response](#22-customising-the-upstream-response)\n    - [2.3. X-Forwarded Headers](#23-x-forwarded-headers)\n        - [2.3.1. Client Sent X-Forwarded-Headers](#231-client-sent-x-forwarded-headers)\n        - [2.3.2. Adding `X-Forwarded-*` Headers](#232-adding-x-forwarded--headers)\n        - [2.3.3. Copying `X-Forwarded` headers](#233-copying-x-forwarded-headers)\n    - [2.4. Configuring ProxyKit's HttpClient](#24-configuring-proxykits-httpclient)\n    - [2.5. Error handling](#25-error-handling)\n    - [2.6. Testing](#26-testing)\n    - [2.7. Load Balancing](#27-load-balancing)\n        - [2.7.1. Weighted Round Robin](#271-weighted-round-robin)\n    - [2.8. Typed Handlers](#28-typed-handlers)\n- [3. Recipes](#3-recipes)\n- [4. Making upstream servers reverse proxy friendly](#4-making-upstream-servers-reverse-proxy-friendly)\n- [5. Performance considerations](#5-performance-considerations)\n- [6. Note about serverless](#6-note-about-serverless)\n- [7. Comparison with Ocelot](#7-comparison-with-ocelot)\n- [8. How to build](#8-how-to-build)\n- [9. Contributing / Feedback / Questions](#9-contributing--feedback--questions)\n- [10. Articles, blogs and other external links](#10-articles-blogs-and-other-external-links)\n\n\u003c!-- /TOC --\u003e\n\n## 1. Quick Start\n\n### 1.1. Install\n\nProxyKit is a `NetStandard2.0` package. Install into your ASP.NET Core project:\n\n```bash\ndotnet add package ProxyKit\n```\n\n### 1.2. Forward HTTP Requests\n\nIn your `Startup`, add the proxy service:\n\n```csharp\npublic void ConfigureServices(IServiceCollection services)\n{\n    ...\n    services.AddProxy();\n    ...\n}\n```\n\nForward HTTP requests to `upstream-server:5001`:\n\n```csharp\npublic void Configure(IApplicationBuilder app)\n{\n    app.RunProxy(context =\u003e context\n        .ForwardTo(\"http://upstream-server:5001/\")\n        .AddXForwardedHeaders()\n        .Send());\n}\n```\n\nWhat is happening here?\n\n 1. `context.ForwardTo(upstreamHost)` is an extension method on\n    `HttpContext` that creates and initializes an `HttpRequestMessage` with\n    the original request headers copied over, yielding a `ForwardContext`.\n 2. `AddXForwardedHeaders` adds `X-Forwarded-For`, `X-Forwarded-Host`,\n    `X-Forwarded-Proto` and `X-Forwarded-PathBase` headers to the upstream\n    request.\n 3. `Send` Sends the forward request to the upstream server and returns an\n    `HttpResponseMessage`.\n 4. The proxy middleware then takes the response and applies it to\n    `HttpContext.Response`.\n\nNote: `RunProxy` is [terminal] - anything added to the pipeline _after_\n`RunProxy` will never be executed.\n\n### 1.3. Forward WebSocket Requests\n\nForward WebSocket requests to `upstream-server:5002`:\n\n```csharp\npublic void Configure(IApplicationBuilder app)\n{\n    app.UseWebSockets();\n    app.UseWebSocketProxy(\n        context =\u003e new Uri(\"ws://upstream-host:80/\"),\n        options =\u003e options.AddXForwardedHeaders());\n}\n```\n\nWhat is happening here?\n\n 1. `app.UseWebSockets()` must first be added otherwise websocket requests will\n    never be handled by ProxyKit.\n 2. The first parameter must return the URI of the upstream host with a scheme\n    of `ws://`.\n 3. The second parameter `options` allows you to do some customisation of the\n    initial upstream requests such as adding some headers.\n\n## 2. Core Features\n\n### 2.1. Customising the upstream HTTP request\n\nOne can modify the upstream request headers prior to sending them to suit\ncustomisation needs. ProxyKit doesn't add, remove, nor modify any headers by\ndefault; one must opt in any behaviours explicitly.\n\nIn this example we will add a `X-Correlation-ID` header if the incoming request does not bear one:\n\n```csharp\npublic const string XCorrelationId = \"X-Correlation-ID\";\n\npublic void Configure(IApplicationBuilder app)\n{\n    app.RunProxy(context =\u003e\n    {\n        var forwardContext = context.ForwardTo(\"http://upstream-server:5001/\");\n        if (!forwardContext.UpstreamRequest.Headers.Contains(XCorrelationId))\n        {\n            forwardContext.UpstreamRequest.Headers.Add(XCorrelationId, Guid.NewGuid().ToString());\n        }\n        return forwardContext.Send();\n    });\n}\n```\n\nThis can be encapsulated as an extension method:\n\n```csharp\npublic static class CorrelationIdExtensions\n{\n    public const string XCorrelationId = \"X-Correlation-ID\";\n    \n    public static ForwardContext ApplyCorrelationId(this ForwardContext forwardContext)\n    {\n        if (!forwardContext.UpstreamRequest.Headers.Contains(XCorrelationId))\n        {\n            forwardContext.UpstreamRequest.Headers.Add(XCorrelationId, Guid.NewGuid().ToString());\n        }\n        return forwardContext;\n    }\n}\n```\n\n... making the proxy code a little nicer to read:\n\n```csharp\npublic void Configure(IApplicationBuilder app)\n{\n    app.RunProxy(context =\u003e context\n        .ForwardTo(\"http://upstream-server:5001/\")\n        .ApplyCorrelationId()\n        .Send());\n}\n```\n\n### 2.2. Customising the upstream response\n\nThe response from an upstream server can be modified before it is sent to the\nclient. In this example we are removing a header:\n\n```csharp\npublic void Configure(IApplicationBuilder app)\n{\n    app.RunProxy(async context =\u003e\n    {\n        var response = await context\n            .ForwardTo(\"http://localhost:5001/\")\n            .Send();\n\n        response.Headers.Remove(\"MachineID\");\n\n        return response;\n    });\n}\n```\n\n### 2.3. X-Forwarded Headers\n\n#### 2.3.1. Client Sent X-Forwarded-Headers \n\n:warning: To mitigate against spoofing attacks and misconfiguration ProxyKit\ndoes not copy `X-Forward-*` headers from the incoming request to the upstream\nrequest by default. Copying them requires opting in; see _2.3.3 Copying\nX-Forwarded headers_ below.\n\n#### 2.3.2. Adding `X-Forwarded-*` Headers\n\nMany applications will need to know what their \"outside\" host / URL is in order\nto generate correct values. This is achieved using `X-Forwarded-*` and\n`Forwarded` headers. ProxyKit supports applying `X-Forward-*` headers out of the\nbox (applying `Forwarded` headers support is on backlog). At the time of writing,\n`Forwarded` is [not supported](https://github.com/aspnet/AspNetCore/issues/5978)\nin ASP.NET Core.\n\nTo add `X-Forwarded-*` headers to the request to the upstream server:\n\n```csharp\npublic void Configure(IApplicationBuilder app)\n{\n    app.RunProxy(context =\u003e context\n        .ForwardTo(\"http://upstream-server:5001/\")\n        .AddXForwardedHeaders()\n        .Send());\n}\n```\n\nThis will add `X-Forwarded-For`, `X-Forwarded-Host` and `X-Forwarded-Proto`\nheaders to the upstream request using values from `HttpContext`. If the proxy\nmiddleware is hosted on a path and a `PathBase` exists on the request, then an\n`X-Forwarded-PathBase` is also added.\n\n#### 2.3.3. Copying `X-Forwarded` headers\n\nChaining proxies is a common pattern in more complex setups. In this case, if\nthe proxy is an \"internal\" proxy, you will want to copy the \"X-Forwarded-*\"\nheaders from previous proxy. To do so, use `CopyXForwardedHeaders()`:\n\n```csharp\npublic void Configure(IApplicationBuilder app)\n{\n    app.RunProxy(context =\u003e context\n        .ForwardTo(\"http://upstream-server:5001/\")\n        .CopyXForwardedHeaders()\n        .Send());\n}\n```\n\nYou may optionally also add the \"internal\" proxy details to the `X-Forwarded-*`\nheader values by combining `CopyXForwardedHeaders()` and\n`AddXForwardedHeaders()` (*note the order is important*):\n\n```csharp\npublic void Configure(IApplicationBuilder app)\n{\n    app.RunProxy(context =\u003e context\n        .ForwardTo(\"http://upstream-server:5001/\")\n        .CopyXForwardedHeaders()\n        .AddXForwardedHeaders()\n        .Send());\n}\n```\n\n### 2.4. Configuring ProxyKit's HttpClient\n\nWhen adding the Proxy to your application's service collection, there is an\nopportunity to configure the internal HttpClient. As\n[`HttpClientFactory`](https://docs.microsoft.com/en-us/dotnet/standard/microservices-architecture/implement-resilient-applications/use-httpclientfactory-to-implement-resilient-http-requests)\nis used, its builder is exposed for you to configure:\n\n```csharp\nservices.AddProxy(httpClientBuilder =\u003e /* configure http client builder */);\n```\n\nBelow are two examples of what you might want to do:\n\n1. Configure the HTTP Client's timeout to 5 seconds:\n\n    ```csharp\n    services.AddProxy(httpClientBuilder =\u003e\n        httpClientBuilder.ConfigureHttpClient =\n            client =\u003e client.Timeout = TimeSpan.FromSeconds(5));\n    ```\n\n2. Configure the primary `HttpMessageHandler`. This is typically used in testing\n   to inject a test handler (see _Testing_ below). \n\n    ```csharp\n    services.AddProxy(httpClientBuilder =\u003e\n        httpClientBuilder.ConfigurePrimaryHttpMessageHandler = \n            () =\u003e _testMessageHandler);\n    ```\n\n### 2.5. Error handling\n\nWhen `HttpClient` throws, the following logic applies:\n\n1. When upstream server is not reachable, then `503 ServiceUnavailable` is returned.\n2. When upstream server is slow and client timeouts, then `504 GatewayTimeout` is\n   returned.\n\nNot all exception scenarios and variations are caught, which may result in a\n`InternalServerError` being returned to your clients. Please create an issue if\na scenario is missing.\n\n### 2.6. Testing\n\nAs ProxyKit is a standard ASP.NET Core middleware, it can be tested using the\nstandard in-memory `TestServer` mechanism.\n\nOften you will want to test ProxyKit with your application and perhaps test the\nbehaviour of your application when load balanced with two or more instances as\nindicated below.\n\n```\n                               +----------+\n                               |\"Outside\" |\n                               |HttpClient|\n                               +-----+----+\n                                     |\n                                     |\n                                     |\n                         +-----------+---------+\n    +--------------------\u003eRoutingMessageHandler|\n    |                    +-----------+---------+\n    |                                |\n    |                                |\n    |           +--------------------+-------------------------+\n    |           |                    |                         |\n+---+-----------v----+      +--------v---------+     +---------v--------+\n|Proxy TestServer    |      |Host1 TestServer  |     |Host2 TestServer  |\n|with Routing Handler|      |HttpMessageHandler|     |HttpMessageHandler|\n+--------------------+      +------------------+     +------------------+\n```\n\n`RoutingMessageHandler` is an `HttpMessageHandler` that will route requests\nto specific hosts based on the origin it is configured with. For ProxyKit\nto forward requests (in memory) to the upstream hosts, it needs to be configured\nto use the `RoutingMessageHandler` as its primary `HttpMessageHandler`.\n\nFull example can been viewed in [Recipe 6](https://github.com/ProxyKit/Recipes/blob/master/Recipes/06_Testing.cs).\n\n### 2.7. Load Balancing\n\nLoad balancing is a mechanism to decide which upstream server to forward the\nrequest to. Out of the box, ProxyKit currently supports one type of\nload balancing - Weighted Round Robin. Other types are planned.\n\n#### 2.7.1. Weighted Round Robin\n\nRound Robin simply distributes requests as they arrive to the next host in a\ndistribution list. With optional weighting, more requests are sent to the host with\nthe greater weight.\n\n```csharp\npublic void Configure(IApplicationBuilder app)\n{\n    var roundRobin = new RoundRobin\n    {\n        new UpstreamHost(\"http://localhost:5001/\", weight: 1),\n        new UpstreamHost(\"http://localhost:5002/\", weight: 2)\n    };\n\n    app.RunProxy(\n        async context =\u003e\n        {\n            var host = roundRobin.Next();\n\n            return await context\n                .ForwardTo(host)\n                .Send();\n        });\n}\n```\n\n### 2.8. Typed Handlers\n\n_New in version 2.1.0_\n\nInstead of specifying a delegate, it is possible to use a typed handler. The\nreason you may want to do this is when you want to better leverage dependency\ninjection.\n\nTyped handlers must implement `IProxyHandler` that has a single method with same\nsignature as `HandleProxyRequest`. In this example our typed handler has a\ndependency on an imaginary service to lookup hosts:\n\n```csharp\npublic class MyTypedHandler : IProxyHandler\n{\n    private IUpstreamHostLookup _upstreamHostLookup;\n\n    public MyTypeHandler(IUpstreamHostLookup upstreamHostLookup)\n    {\n        _upstreamHostLookup = upstreamHostLookup;\n    }\n\n    public Task\u003cHttpResponseMessage\u003e HandleProxyRequest(HttpContext context)\n    {\n        var upstreamHost = _upstreamHostLookup.Find(context);\n        return context\n            .ForwardTo(upstreamHost)\n            .AddXForwardedHeaders()\n            .Send();\n    }\n}\n```\n\nWe then need to register our typed handler service:\n\n```csharp\npublic void ConfigureServices(IServiceCollection services)\n{\n    ...\n    services.AddSingleton\u003cMyTypedHandler\u003e();\n    ...\n}\n```\n\nWhen adding the proxy to the pipeline, use the generic form:\n\n```csharp\npublic void ConfigureServices(IServiceCollection services)\n{\n    ...\n    appInner.RunProxy\u003cMyTypedHandler\u003e());\n    ...\n}\n```\n\n## 3. Recipes\n\nRecipes have moved to [own repo](https://github.com/proxykit/Recipes).\n\n## 4. Making upstream servers reverse proxy friendly\n\nApplications that are deployed behind a reverse proxy typically need to be\nsomewhat aware of that so they can generate correct URLs and paths when\nresponding to a browser. That is, they look at `X-Forward-*` / `Forwarded`\nheaders and use their values.\n\nIn ASP.NET Core, this means using the `ForwardedHeaders` middleware in your\napplication. Please refer to the [documentation][forwarded headers middleware]\nfor correct usage (and note the security advisory!).\n\n**Note:** the Forwarded Headers middleware does not support\n`X-Forwarded-PathBase`. This means if you proxy `http://example.com/foo/` to\n`http://upstream-host/` the `/foo/` part is lost and absolute URLs cannot be\ngenerated unless you configure your application's `PathBase` directly.\n\nRelated issues and discussions:\n\n- https://github.com/aspnet/AspNetCore/issues/5978\n- https://github.com/aspnet/AspNetCore/issues/5898\n\nTo support PathBase dynamically in your application with `X-Forwarded-PathBase`,\nexamine the header early in your pipeline and set the `PathBase` accordingly:\n\n```csharp\nvar options = new ForwardedHeadersOptions\n{\n   ...\n};\napp.UseForwardedHeaders(options);\napp.Use((context, next) =\u003e \n{\n    if (context.Request.Headers.TryGetValue(\"X-Forwarded-PathBase\", out var pathBases))\n    {\n        context.Request.PathBase = pathBases.First();\n    }\n    return next();\n});\n```\n\nAlternatively you can use ProxyKit's `UseXForwardedHeaders` extension that\nperforms the same as the above (including calling `UseForwardedHeaders`):\n\n```csharp\nvar options = new ForwardedHeadersOptions\n{\n   ...\n};\napp.UseXForwardedHeaders(options);\n```\n\n## 5. Performance considerations\n\nAccording to TechEmpower's Web Framework Benchmarks, ASP.NET Core [is up there\nwith the fastest for plain\ntext](https://www.techempower.com/benchmarks/#section=data-r17\u0026hw=ph\u0026test=plaintext).\nAs ProxyKit simply captures headers and async copies request and response body\nstreams, it will be fast enough for most scenarios.\n\nIf absolute raw throughput is a concern for you, then\nconsider nginx or alternatives. For me being able to create flexible proxies\nusing C# is a reasonable tradeoff for the (small) performance cost. Note that\nwhat your specific proxy (and its specific configuration) does will impact performance\nso you should measure for yourself in your context.\n\nOn Windows, ProxyKit is ~3x faster than nginx. However, nginx has clearly\ndocumented that [it has known\nperformance issues on Windows](https://nginx.org/en/docs/windows.html). Since\none wouldn't be running production nginx on Windows, this comparison is\nacademic.\n\nMemory wise, ProxyKit maintained a steady ~20MB of RAM after processing millions\nof requests for simple forwarding. Again, it depends on what your proxy does so\nyou should analyse and measure yourself.\n\n## 6. Note about serverless\n\nWhilst it is possible to run full ASP.NET Core web application in [AWS\nLambda] and [Azure Functions] it should be noted that Serverless systems are\nmessage based and not stream based. Incoming and outgoing HTTP request messages\nwill be buffered and potentially encoded as Base64 if binary (so larger). This\nmeans ProxyKit should only be used for API (json) proxying in production on\nServerless. (Though proxying other payloads is fine for dev / exploration /\nquick'n'dirty purposes.)\n\n## 7. Comparison with Ocelot\n\n[Ocelot] is an API Gateway that also runs on ASP.NET Core. A key difference\nbetween API Gateways and general Reverse Proxies is that the former tend to be\n**message** based whereas a reverse proxy is **stream** based. That is, an API\nGateway will typically buffer every request and response message to be able\nto perform transformations. This is fine for an API Gateway but not suitable for\na general reverse proxy performance wise nor for responses that are\nchunked-encoded. See [Not Supported Ocelot docs][ocelot not supported].\n\nCombining ProxyKit with Ocelot would give some nice options for a variety of\nscenarios.\n\n## 8. How to build\n\nRequirements: .NET Core SDK 2.2.100 or later.\n\nOn Windows: \n\n```bash\n.\\build.cmd\n```\n\nOn Linux: \n```bash\n./build.sh\n```\n\n## 9. Contributing / Feedback / Questions\n\nAny ideas for features, bugs or questions, please create an issue. Pull requests \ngratefully accepted but please create an issue for discussion first.\n\nI can be reached on twitter at [@randompunter](https://twitter.com/randompunter)\n\n## 10. Articles, blogs and other external links\n\n- [An alternative way to secure SPAs (with ASP.NET Core, OpenID Connect, OAuth 2.0 and ProxyKit)](https://leastprivilege.com/2019/01/18/an-alternative-way-to-secure-spas-with-asp-net-core-openid-connect-oauth-2-0-and-proxykit/)\n\n---\n\n\u003csub\u003elogo is [distribute](https://thenounproject.com/term/target/345443) by [ChangHoon Baek](https://thenounproject.com/changhoon.baek.50/) from [the Noun Project](https://thenounproject.com/).\u003c/sub\u003e\n\n[nuget badge]: https://img.shields.io/nuget/v/ProxyKit.svg\n[nuget package]: https://www.nuget.org/packages/ProxyKit\n[feedz badge]: https://img.shields.io/badge/endpoint.svg?url=https%3A%2F%2Ff.feedz.io%2Fdh%2Foss-ci%2Fshield%2FProxyKit%2Flatest\n[feedz package]: https://f.feedz.io/dh/oss-ci/packages/ProxyKit/latest/download\n[aspnet labs]: https://github.com/aspnet/AspLabs\n[`httpclientfactory`]:  https://docs.microsoft.com/en-us/dotnet/standard/microservices-architecture/implement-resilient-applications/use-httpclientfactory-to-implement-resilient-http-requests\n[terminal]: https://docs.microsoft.com/en-ie/dotnet/api/microsoft.aspnetcore.builder.runextensions.run?view=aspnetcore-2.1\n[forwarded headers middleware]: https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/proxy-load-balancer?view=aspnetcore-2.2\n[aws lambda]: https://aws.amazon.com/blogs/developer/running-serverless-asp-net-core-web-apis-with-amazon-lambda/\n[azure functions]: https://blog.wille-zone.de/post/serverless-webapi-hosting-aspnetcore-webapi-in-azure-functions/\n[ocelot]: https://github.com/ThreeMammals/Ocelot\n[ocelot not supported]: https://ocelot.readthedocs.io/en/latest/introduction/notsupported.html\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FProxyKit%2FProxyKit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FProxyKit%2FProxyKit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FProxyKit%2FProxyKit/lists"}