utoipa icon indicating copy to clipboard operation
utoipa copied to clipboard

Order is not preserved for `response.content_types`

Open okdistribute opened this issue 1 year ago • 2 comments

Given the following path,

#[utoipa::path(
    request_body(content=MyRequest, content_type="application/json"),
    responses(
        (status = 200, content_type=["application/json", "application/cbor"], description = "RPC call was successful", body = FindByIdResponse),
        (status = 400, content_type=["application/json", "application/cbor"], description = "Bad Request", body = RpcError),
        (status = 401, content_type=["application/json", "application/cbor"], description = "Forbidden", body = RpcError),
        (status = 500, content_type=["application/json", "application/cbor"], description = "Internal Server Error", body = RpcError)
    ),
)]

The resulting spec will not be serialized in the same order it is specified. I see application/cbor come first in the list.

This matters because in Swagger UI, the first one in the list is the default example, which should be JSON because it is not possible to play with CBOR in the browser.

        "responses": {
          "200": {
            "description": "RPC call was successful",
            "content": {
              "application/cbor": {
                "schema": {
                  "$ref": "#/components/schemas/FindByIdResponse"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FindByIdResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RpcError"
                }
              },
              "application/cbor": {
                "schema": {
                  "$ref": "#/components/schemas/RpcError"
                }
              }
            }
          },
          "401": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RpcError"
                }
              },
              "application/cbor": {
                "schema": {
                  "$ref": "#/components/schemas/RpcError"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/cbor": {
                "schema": {
                  "$ref": "#/components/schemas/RpcError"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RpcError"
                }
              }
            }
          }
        },
        ```

okdistribute avatar Jul 26 '22 06:07 okdistribute

This is currently unimplemented. The content_type in content object is BTreeMap which is sorted by natural order (A-Z) now in master and in 1.1.0 and below it is just a HashMap which does not preserve order. Even the current natural order would not be sufficient since it would always make the cbor as a first choice. Instead there would be a need to preserve the definition order.

This would need custom sorting to be implemented and I can see why someone would want that for Swagger UI. This is something that could be addressed in future PRs.

juhaku avatar Jul 26 '22 07:07 juhaku

Thank you that would be great

okdistribute avatar Jul 28 '22 22:07 okdistribute