Skip to content

RequestBody in GET requests are rendered as query parameter #1003

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

Closed
OnnoH opened this issue Dec 29, 2020 · 3 comments
Closed

RequestBody in GET requests are rendered as query parameter #1003

OnnoH opened this issue Dec 29, 2020 · 3 comments

Comments

@OnnoH
Copy link

OnnoH commented Dec 29, 2020

Describe the bug
I know it's uncommon for GET requests to have a RequestBody, but sometimes the payload can be quite large for the query parameter in the URL to handle it. Using a RequestBody makes more sense, but the generator does not render it. Instead a query parameter entry is there and when executed in the Swagger UI the following exception is thrown:

org.springframework.http.converter.HttpMessageNotReadableException: Required request body is missing:

To Reproduce
Steps to reproduce the behavior:

  • Spring Boot 2.4.0
  • springdoc-openapi v1.5.2
  • modules: springdoc-openapi-ui, springdoc-openapi-security, springdoc-openapi-data-rest
  • JSON result (excerpt)
    "/api/{domain}/ids/search": {
      "get": {
        "tags": [
          "Get Controller"
        ],
        "summary": "Get a list of all visible documents from a givendomain filtered by the given list of id's",
        "description": "Sample Request Body:\n\n{ \"ids\" : [ 1010334, 1010356 ] }",
        "operationId": "getDomainDocumentsByListOfIds",
        "parameters": [
          {
            "name": "domain",
            "in": "path",
            "description": "Name of domain",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "ids",
            "in": "query",
            "required": true,
            "schema": {
              "type": "object"
            }
          },
          {
            "name": "pageable",
            "in": "query",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/Pageable"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QueryResult"
                }
              }
            }
          }
        }
      }
    },
  • SampleController (excerpt)
@RequestMapping(value = "/api/{domain}/ids/search", method = RequestMethod.GET,
          produces = {MediaType.APPLICATION_JSON_VALUE})
@Transactional(readOnly = true)
@Operation(summary = "Get a list of all visible documents from a given domain filtered by the given list of id's",
          description = "Sample Request Body:\n\n"
                  + "{ \"ids\" : [ 1010334, 1010356 ] }")
@Parameter(name = "domain", description = "Name of domain", in = ParameterIn.PATH)
public QueryResult getDomainDocumentsByListOfIds(@PathVariable String domain,
                                                          @RequestBody Object ids,
                                                          final Pageable pageable,
                                                          HttpServletRequest request) {
    Path path = parser.parsePath(domain, request.getQueryString());
    validator.validatePath(path, HttpMethod.GET);

    List<Long> fetchIds = parseRequestBody(ids);
    path.setSearchIds(fetchIds);

    return this.documentService.getByDomain(path.getDomain(),
              path.getSearchFilter(), pageable, null);
}

Expected behavior

  • Similar to a PUT request, I would expect
  • Sample JSON (excerpt)
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": {
                  "type": "object"
                }
              }
            }
          },
          "required": true
        },

Screenshots
Some Swagger UI screenshots from the actual API

The 'old' Springfox-GET
Screenshot 2020-12-29 at 16 44 38

The 'new' GET
Screenshot 2020-12-29 at 16 45 46

The 'new PUT
Screenshot 2020-12-29 at 16 46 18

@bnasslahsen
Copy link
Collaborator

bnasslahsen commented Dec 29, 2020

springdoc-openapi only supports OpenAPI 3, where : GET, DELETE and HEAD are no longer allowed to have request body because it does not have defined semantics as per RFC 7231.

There are some workarounds, but you will get invalid spec...

@okohub
Copy link

okohub commented Aug 23, 2022

@bnasslahsen RFC 7231 is now obsolete, RFC 9110 is published on June.

https://www.rfc-editor.org/rfc/rfc9110.html#section-9.3.1-6

This section now says;

Although request message framing is independent of the method used, content received in a GET request has no generally defined semantics, cannot alter the meaning or target of the request, and might lead some implementations to reject the request and close the connection because of its potential as a request smuggling attack (Section 11.2 of [HTTP/1.1]). A client SHOULD NOT generate content in a GET request unless it is made directly to an origin server that has previously indicated, in or out of band, that such a request has a purpose and will be adequately supported. An origin server SHOULD NOT rely on private agreements to receive content, since participants in HTTP communication are often unaware of intermediaries along the request chain.

What do you think about this?

@bnasslahsen
Copy link
Collaborator

@okohub,

We support OAS 3, which clearly states: GET, DELETE and HEAD are no longer allowed to have request body because it does not have defined semantics ...

@springdoc springdoc locked as resolved and limited conversation to collaborators Aug 24, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants