dotnet / aspnetcore

ASP.NET Core is a cross-platform .NET framework for building modern cloud-based web applications on Windows, Mac, or Linux.
https://asp.net
MIT License
35.2k stars 9.94k forks source link

Server URLs in OpenAPI document are incorrect when application used with .NET Aspire #57332

Open martincostello opened 1 month ago

martincostello commented 1 month ago

Is there an existing issue for this?

Describe the bug

When an OpenAPI document is being used as part of an application running with .NET Aspire, the servers array of the OpenAPI document is populated with incorrect URLs.

This then causes operations using Swagger UI to fail:

image

In this case, the application is running on http://localhost:50000 and https://localhost:50001.

I think the issue is that headers such as X-Forwarded-For aren't being taken into account.

https://github.com/dotnet/aspnetcore/blob/08b60af1bca8cffff8ba0a72164fb7505ffe114d/src/OpenApi/src/Services/OpenApiDocumentService.cs#L190-L198

If I use my own transformer to always populate the server URLs, which uses the configured ForwardedHeadersOptions, then I get the correct host and port.

{
  "openapi": "3.0.1",
  "info": {
    "title": "London Travel",
    "description": "London Travel is an Amazon Alexa skill for checking the status for travel in London.",
    "termsOfService": "https://londontravel.martincostello.com/terms-of-service/",
    "contact": {
      "name": "Martin Costello",
      "url": "https://github.com/martincostello/alexa-london-travel-site"
    },
    "license": {
      "name": "Apache 2.0",
      "url": "https://www.apache.org/licenses/LICENSE-2.0.html"
    },
    "version": ""
  },
  "servers": [
    {
      "url": "https://localhost:50001"
    }
  ]
}

If this is disabled and the built-in development-time support is used, the wrong URLs are rendered.

{
  "openapi": "3.0.1",
  "info": {
    "title": "London Travel",
    "description": "London Travel is an Amazon Alexa skill for checking the status for travel in London.",
    "termsOfService": "https://londontravel.martincostello.com/terms-of-service/",
    "contact": {
      "name": "Martin Costello",
      "url": "https://github.com/martincostello/alexa-london-travel-site"
    },
    "license": {
      "name": "Apache 2.0",
      "url": "https://www.apache.org/licenses/LICENSE-2.0.html"
    },
    "version": ""
  },
  "servers": [
    {
      "url": "https://localhost:65076"
    },
    {
      "url": "http://localhost:65077"
    }
  ]
}

Expected Behavior

The correct URL(s) are included in the servers array of the OpenAPI document taking into account any HTTP forwarded headers.

Steps To Reproduce

  1. Clone https://github.com/martincostello/alexa-london-travel-site/commit/23c2af944e9741ecbf192631261128af11db7258
  2. Open the solution in Visual Studio
  3. Launch the LondonTravel.Site.AppHost project
  4. Wait for the applications to load
  5. View the contents of the document at https://localhost:50001/openapi/api.json

Exceptions (if any)

No response

.NET Version

9.0.100-preview.7.24407.12

Anything else?

No response

captainsafia commented 3 weeks ago

@martincostello The transformer strategy is a good way to solve this problem.

A while back with modeled Swagger UI as an Aspire resource (https://github.com/davidfowl/AspireSwaggerUI/blob/146163aec403305770861098d3c16578a0d5dd99/SwaggerUi.Aspire.Hosting/SwaggerUiExtensions.cs) and configured forwarding for requests using Aspire's endpoint forwarding rules. In this approach, the Swagger UI is served outside the API resource instance and mimics a pattern similar to what we would do if we served an API testing UI in Aspire.

I'll stick this in the backlog for now as we evaluate how first class OpenAPI docs become in Aspire/Aspire dashboard. In the short-term, we can doc why this issue happens and how to resolve.