Open Closed

Put yarp.json content to appsettings.json ABP 10 #10544


User avatar
0
DominaTang created

When migrate from Ocelet to yarp, by default, an separate yarp.json file is added. When I use yarp file and code has .AddYarp() statement, I noticed that public gateway micro service swagger would only expose those APIs I defined in yarp, however, because of our existing CI/CD, I put yarp.json content to appsettings.json, I noticed that gateway swagger can see all APIs from all micro-service.

Did I miss anything?


9 Answer(s)
  • User Avatar
    0
    AI-Bot created
    Support Team ABP Agent
    • You didn’t miss anything: in ABP’s microservice gateway setup, Gateway Swagger UI is driven by the gateway’s own Swagger configuration, which (by design) typically points to the swagger-json endpoints that you route through YARP. So what the gateway swagger can “see” depends on what you proxy.

    • With YARP, ABP’s recommended approach is to define reverse proxy config under the ReverseProxy section (routes/clusters). This can live in appsettings.json (or any configuration source). ABP docs explicitly show configuring YARP via appsettings.json, so moving from yarp.jsonappsettings.json is fine as long as the structure is the same.

      • If, after moving, the gateway swagger suddenly shows “all APIs from all microservices”, the usual reason is:
        • you unintentionally stopped filtering swagger endpoints (or stopped using the gateway’s “aggregated swagger through gateway routes” approach), and/or
        • the gateway is now able to reach additional swagger endpoints because your configuration now includes (directly or indirectly) more routes (e.g., a broad catch-all), so the swagger UI can successfully load more swagger.json documents.
    • What to do (definitive):

      1. Ensure your gateway is only exposing the swagger-json routes you intend. In ABP’s YARP gateway style, you usually add explicit routes like:
        • /swagger-json/Administration/swagger/v1/swagger.json
        • /swagger-json/ProductService/swagger/v1/swagger.json (each with a PathRemovePrefix transform) If you add a too-broad route (for example routing /swagger/{**catch-all} or a very generic /{**catch-all}), the gateway swagger UI (or the browser) may be able to resolve more swagger docs than you expect.
      2. Verify you didn’t end up with two configurations merged:
        • In .NET configuration, appsettings.json, appsettings.{Environment}.json, environment variables, configmaps, etc. can merge. If yarp.json is still being loaded somehow (custom code or host builder), you may effectively have more proxy routes/clusters than you think.
      3. If your goal is to hide ABP/framework endpoints (or generally filter what appears in Swagger UI), use ABP’s built-in Swagger filtering such as HideAbpEndpoints() in your swagger setup.
    • Putting YARP config in appsettings.json is supported; the key is keeping your ReverseProxy routes tightly scoped so the gateway swagger can only load the intended swagger documents.

    Links (verified):

    • ABP microservice gateway YARP configuration via appsettings.json (ReverseProxy section): https://abp.io/docs/latest/solution-templates/microservice/adding-new-api-gateways
    • YARP (Reverse Proxy) official site: https://microsoft.github.io/reverse-proxy/
    • ABP Swagger option to hide ABP endpoints (HideAbpEndpoints): https://abp.io/docs/latest/API/Swagger-Integration#hide-abp-endpoints-on-swagger-ui

    This response was generated by AI. If it didn’t solve your problem, feel free to post a new answer — our support team will jump in to help you soon.

  • User Avatar
    0
    DominaTang created

    Before upgrade, our public gateway only expose controller end with '-public', during upgrade process, I see it keep the same. But I not sure, when it shows all APIs, it might because I 1) replace Ocelot with yarp 2) move yarp.json to appsettings.json 3) replace AddAbpSwaggerGenWithOAuth with AddAbpSwaggerGenWithOidc

    Do I still need to AddYarp() call after I move yarp.json content to appsettings? I deleted the yarp file after content merge.

  • User Avatar
    0
    AI-Bot created
    Support Team ABP Agent
    • Yes, you still need the YARP registration call (whatever your template/module uses, e.g. services.AddYarpReverseProxy() / AddReverseProxy() etc.).
      Moving yarp.json content into appsettings.json only changes the configuration source; it does not register YARP services or map the reverse proxy endpoint. If you remove the YARP registration, the gateway won’t actually behave as a reverse proxy (and ABP’s YARP-based swagger aggregation logic won’t behave as expected either).

    • In the ABP YARP migration guide, the expected change is to change the config loader from Ocelot to YARP:

    builder.Host
          .AddAppSettingsSecretsJson()
      -   .AddOcelotJson()
      +   .AddYarpJson()
          .UseAutofac()
          .UseSerilog();
    

    That AddYarpJson() is about loading yarp.json (a separate file). If you merged the content into appsettings.json, you typically don’t need AddYarpJson() anymore, because appsettings.json is already loaded by default. But you still need the YARP service registration and MapReverseProxy().

    • Why your Swagger suddenly shows “all APIs”:

      • In ABP’s YARP gateway approach, Swagger UI endpoints are usually added by iterating clusters from IProxyConfigProvider and calling options.SwaggerEndpoint(...) for each cluster (see the migration guide’s ConfigureSwaggerUI(proxyConfig, ...) sample). That means if your effective YARP config now contains more clusters than before (because of config merging from multiple sources, or you accidentally broadened routes/clusters), Swagger UI will list more services/APIs.
      • Switching from AddAbpSwaggerGenWithOAuth to AddAbpSwaggerGenWithOidc generally affects authentication method in Swagger UI, not which endpoints are included. The “shows all APIs” symptom is much more consistent with the gateway’s swagger endpoints being generated for more clusters (or the proxy now allowing access to more swagger-json endpoints).
    • Definitive setup guidance when ReverseProxy is inside appsettings.json:

      1. Keep ReverseProxy section in appsettings.json.
      2. Remove AddYarpJson() (optional) if you deleted yarp.json and don’t want that custom provider anymore.
      3. Keep YARP registration + mapping (required): the gateway must still register YARP and call endpoints.MapReverseProxy() (as shown in the migration guide).

    References (validated):

    • ABP migration guide (Ocelot → YARP) showing AddYarpJson(), IProxyConfigProvider-based Swagger endpoints, and MapReverseProxy(): https://abp.io/docs/latest/release-info/migration-guides/pro/migrating-to-yarp
    • ABP “Adding new API gateways” (YARP config in appsettings.json / ReverseProxy): https://abp.io/docs/latest/solution-templates/microservice/adding-new-api-gateways
    • Swagger integration (hide ABP endpoints if needed): https://abp.io/docs/latest/API/Swagger-Integration#hide-abp-endpoints-on-swagger-ui

    This response was generated by AI. If it didn’t solve your problem, feel free to post a new answer — our support team will jump in to help you soon.

  • User Avatar
    0
    DominaTang created
    1. All yarp cofnig are within "ReverseProxy": {} section in appsettings.config 2)Gateway has app.UseEndpoints(endpoints => endpoints.MapReverseProxy());
  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    Could you check the Routes section in your old yarp.json vs the current appsettings.json?

    If your original routes were matching specific paths (e.g. only -public controllers), but the new config uses broader catch-all patterns, that would explain why more APIs are visible now — the Swagger UI reflects what's actually routed through YARP.

    Also, you can create a new microservice template project with ABP Studio and compare the gateway configuration with yours. That should make it easier to spot any differences.

    Thanks.

  • User Avatar
    0
    DominaTang created

    Here is our settings:

    "ReverseProxy": {
        "Routes": {
          "ClientServicePublic": {
            "ClusterId": "ClientService",
            "Match": {
              "Path": "/api/client-service-public/{**catch-all}"
            }
          },
          "ClientServiceSwagger": {
            "ClusterId": "ClientService",
            "Match": {
              "Path": "/swagger-json/ClientService/swagger/v1/swagger.json"
            },
            "Transforms": [
              { "PathRemovePrefix": "/swagger-json/ClientService" }
            ]
          },
          "IdentityPublic": {
            "ClusterId": "Identity",
            "Match": {
              "Path": "/api/identity-public/{**catch-all}"
            }
          },
          "IdentitySwagger": {
            "ClusterId": "Identity",
            "Match": {
              "Path": "/swagger-json/Identity/swagger/v1/swagger.json"
            },
            "Transforms": [
              { "PathRemovePrefix": "/swagger-json/Identity" }
            ]
          },
          "SignalRNegotiate": {
            "ClusterId": "ClientServiceSignalR",
            "Match": {
              "Path": "/signalr/negotiate",
              "Methods": [ "POST", "OPTIONS" ]
            }
          },
          "SignalRHub": {
            "ClusterId": "ClientServiceSignalR",
            "Match": {
              "Path": "/signalr/{**catch-all}",
              "Methods": [ "GET", "POST", "PUT", "DELETE", "OPTIONS" ]
            }
          }
        },
        "Clusters": {
          "ClientService": {
            "Destinations": {
              "ClientService": {
                "Address": "https://localhost:44368/"
              }
            }
          },
          "ClientServiceSignalR": {
            "Destinations": {
              "ClientService": { "Address": "https://localhost:44368/" }
            },
            "SessionAffinity": {
              "Enabled": true,
              "Policy": "Cookie",
              "AffinityKeyName": "ASP.NET_SessionId",
              "Cookie": {
                "Expiration": "00:30:00"
              }
            }
          },
          "Identity": {
            "Destinations": {
              "Identity": {
                "Address": "https://localhost:44388/"
              }
            }
          }
        }
      }
    
  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    Can you share your Gateway project source code to liming.ma@volosoft.com?

    Thanks.

  • User Avatar
    0
    DominaTang created

    Figured out the reason, We have same micro service, controllers end with "-public", we want to available to public gateway. Here is AI's answer:

    Ocelot uses MMLib.SwaggerForOcelot which downloads all downstream swagger.json files and merges them into the gateway's own swagger.json. So when Swagger UI requests /swagger/v1/swagger.json, it gets a locally generated document that goes through the full SwaggerGen pipeline — including DocInclusionPredicate and DocumentFilter. Swagger UI → /swagger/v1/swagger.json (gateway's OWN doc) ↓ SwaggerGen pipeline runs ↓ DocInclusionPredicate ✅ fires DocumentFilter ✅ fires ↓ Merged & filtered result

    YARP simply forwards the request to the downstream service and returns the raw response. The gateway's SwaggerGen pipeline is never involved. Swagger UI → /swagger-json/ClientService/swagger/v1/swagger.json ↓ YARP proxies request to https://localhost:44368/swagger/v1/swagger.json ↓ Raw downstream swagger.json returned directly ↓ DocInclusionPredicate ❌ never fires DocumentFilter ❌ never fires

    The solution is add a SwaggerDoc to this MicroSerivce with name "public" and at public gateway yarp setting using: "Transforms": [ { "PathSet": "/swagger/public/swagger.json" } ]

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    Hi,

    The key difference is that Ocelot processes and filters the downstream swagger.json through the gateway's SwaggerGen pipeline (DocInclusionPredicate, DocumentFilter), while YARP simply proxies the raw response from downstream services without any filtering.

    Using a separate SwaggerDoc (e.g., "public") in your microservices and pointing the YARP transform to it via PathSet is a clean solution.

    For reference, the ABP microservice template takes a different approach — it uses PathRemovePrefix to proxy the default swagger.json from each downstream service, assuming each microservice is already split by responsibility and all its APIs should be exposed through the gateway. Your approach with separate SwaggerDoc groups works well when a single microservice needs to expose only a subset of its APIs through the gateway.

    Thanks.

Boost Your Development
ABP Live Training
Packages
See Trainings
Mastering ABP Framework Book
The Official Guide
Mastering
ABP Framework
Learn More
Mastering ABP Framework Book
Made with ❤️ on ABP v10.3.0-preview. Updated on March 26, 2026, 13:52
1
ABP Assistant
🔐 You need to be logged in to use the chatbot. Please log in first.