Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

With SchemaType.Swagger2, GET requests with parameters generate invalid swagger.json #390

Closed
gcelet opened this issue Feb 27, 2023 · 3 comments
Labels
enhancement New feature or request implemented requested feature has been implemented

Comments

@gcelet
Copy link

gcelet commented Feb 27, 2023

Hi,

Some tools we use force us to generate the swagger.json in Swagger 2.0 format rather than Open API 3.0 format.

In the Swagger 2.0 format, structural errors are reported by editor.swagger.io for GET requests with parameters.
For the same endpoint in Open Api 3.0 format, no errors are reported.

I don't know if the problem is in FastEndpoints swagger generation or in NSwag library for this case.

Here is the API showing the problem:

using FastEndpoints.Swagger;
using FastEndpoints;
using NJsonSchema;

var builder = WebApplication.CreateBuilder();
builder.Services.AddFastEndpoints(opts =>
{
    opts.SourceGeneratorDiscoveredTypes = new[] { typeof(FastEndpointsBugGetSwagger20.Features.Endpoint) }; 
});
builder.Services.AddSwaggerDoc(shortSchemaNames: true, addJWTBearerAuth: false,
settings: opts =>
{
    opts.SchemaType = SchemaType.Swagger2;
});

var app = builder.Build();
app.UseFastEndpoints();
app.UseSwaggerGen();
app.Run();
namespace FastEndpointsBugGetSwagger20.Features;

using FastEndpoints;
using System.Net.Mime;
using System.Net;

public class Endpoint : Endpoint<MyRequest, MyResponse[]>
{
    public override void Configure()
    {
        Get("/api/user/search");
        AllowAnonymous();
        Description(b => b
                .Accepts<MyRequest>(MediaTypeNames.Application.Json)
                .Produces(statusCode: (int)HttpStatusCode.OK,
                    contentType: MediaTypeNames.Application.Json, responseType: typeof(MyResponse[])),
            clearDefaults: true
        );

        EndpointSummary endpointSummary = new()
        {
            ExampleRequest = new MyRequest
            {
                Age = 80,
            },
            Responses = new Dictionary<int, string>
        {
            { (int)HttpStatusCode.OK, "Success" },
        },
            ResponseExamples = new Dictionary<int, object>
        {
            { (int)HttpStatusCode.OK, new MyResponse[] {new MyResponse { FirstName = "marlon", LastName= "brando", Age = 80} }},
        }
        };
        Summary(endpointSummary);
    }

    public override async Task HandleAsync(MyRequest request, CancellationToken ct)
    {
        var response = new[] { new MyResponse { FirstName = "marlon", LastName = "brando", Age = 80 } }
            .Where(r => r.Age == request.Age)
            .ToArray();

        await SendAsync(response, cancellation: ct);
    }
}

public class MyRequest
{
    public int Age { get; set; }
}

public class MyResponse
{
    public string? FirstName { get; set; }
    public string? LastName { get; set; }
    public int Age { get; set; }
}

And here are the errors reported:

Errors
 
Structural error at paths./api/user/search.get.parameters.0
should NOT have additional properties
additionalProperty: schema
Jump to line 20
Structural error at paths./api/user/search.get.parameters.0
should have required property 'type'
missingProperty: type
Jump to line 20
Structural error at paths./api/user/search.get.responses.200.examples
should be object
Jump to line 35

In addition, here is the generated swagger.json:

{
  "x-generator": "NSwag v13.18.2.0 (NJsonSchema v10.8.0.0 (Newtonsoft.Json v10.0.0.0))",
  "swagger": "2.0",
  "info": {
    "title": "FastEndpointsBugGetSwagger20",
    "version": "1.0.0"
  },
  "host": "localhost:5120",
  "schemes": [
    "http"
  ],
  "consumes": [
    "application/json"
  ],
  "produces": [
    "application/json"
  ],
  "paths": {
    "/api/user/search": {
      "get": {
        "tags": [
          "Api"
        ],
        "operationId": "FastEndpointsBugGetSwagger20FeaturesEndpoint",
        "parameters": [
          {
            "name": "Age",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "x-nullable": false,
            "description": "Success",
            "schema": {
              "type": "array",
              "items": {
                "$ref": "#/definitions/MyResponse"
              }
            },
            "examples": [
              {
                "firstName": "marlon",
                "lastName": "brando",
                "age": 80
              }
            ]
          }
        }
      }
    }
  },
  "definitions": {
    "MyResponse": {
      "type": "object",
      "required": [
        "age"
      ],
      "properties": {
        "firstName": {
          "type": "string"
        },
        "lastName": {
          "type": "string"
        },
        "age": {
          "type": "integer",
          "format": "int32"
        }
      }
    },
    "MyRequest": {
      "type": "object",
      "required": [
        "age"
      ]
    }
  }
}
@dj-nitehawk
Copy link
Member

well...
absolutely no attention was given to support OAS2.0 as i thought people didn't use that anymore.
anywho... 5.7.2.6-beta should take care of that...
check it out and let me know if there's anything that's not working.
cheers!

@dj-nitehawk dj-nitehawk added enhancement New feature or request implemented requested feature has been implemented labels Feb 27, 2023
@gcelet
Copy link
Author

gcelet commented Feb 28, 2023

@dj-nitehawk Thank you for your quick reply and fix.

I tried with the latest version (5.7.2.8-beta): the errors for the GET route parameters have disappeared. 🙏

However, there are still errors on the examples: I will look at your patch to see if I can do a PR for this case.

Here is the remaining error:

Errors
Hide
 
Structural error at paths./api/user/search.get.responses.200.examples
should be object
Jump to line 35

Here is the now generated swagger:

{
  "x-generator": "NSwag v13.18.2.0 (NJsonSchema v10.8.0.0 (Newtonsoft.Json v10.0.0.0))",
  "swagger": "2.0",
  "info": {
    "title": "FastEndpointsBugGetSwagger20",
    "version": "1.0.0"
  },
  "host": "localhost:5120",
  "schemes": [
    "http"
  ],
  "consumes": [
    "application/json"
  ],
  "produces": [
    "application/json"
  ],
  "paths": {
    "/api/user/search": {
      "get": {
        "tags": [
          "Api"
        ],
        "operationId": "FastEndpointsBugGetSwagger20FeaturesEndpoint",
        "parameters": [
          {
            "type": "integer",
            "name": "Age",
            "in": "query",
            "required": true,
            "format": "int32",
            "x-nullable": false
          }
        ],
        "responses": {
          "200": {
            "x-nullable": false,
            "description": "Success",
            "schema": {
              "type": "array",
              "items": {
                "$ref": "#/definitions/MyResponse"
              }
            },
            "examples": [
              {
                "firstName": "marlon",
                "lastName": "brando",
                "age": 80
              }
            ]
          }
        }
      }
    }
  },
  "definitions": {
    "MyResponse": {
      "type": "object",
      "required": [
        "age"
      ],
      "properties": {
        "firstName": {
          "type": "string"
        },
        "lastName": {
          "type": "string"
        },
        "age": {
          "type": "integer",
          "format": "int32"
        }
      }
    },
    "MyRequest": {
      "type": "object",
      "required": [
        "age"
      ]
    }
  }
}

dj-nitehawk added a commit that referenced this issue Feb 28, 2023
@dj-nitehawk
Copy link
Member

this one actually looks like a bug in nswag where it produces the incorrect swagger spec when the response schema is an array type.

the only solution i could figure out was to make the example a json string.

if (ctx.Settings.SchemaType == SchemaType.Swagger2 &&
example is JToken token &&
token.Type == JTokenType.Array)
{
example = token.ToString();
}

give v5.7.2.9-beta a try.

do send in a PR if that's not good enough or if you can come up with a more elegant solution.

cheers!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request implemented requested feature has been implemented
Development

No branches or pull requests

2 participants