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

Allow requestBody for the DELETE method. #1801

Open
adjenks opened this issue Jan 8, 2019 · 11 comments

Comments

Projects
None yet
6 participants
@adjenks
Copy link

commented Jan 8, 2019

I would like the specification to allow a requestBody in the DELETE method and other methods without explicitly defined semantics.

One of the answers in this StackOverflow post states: "The spec does not explicitly forbid or discourage it, so I would tend to say it is allowed."
I would agree with that statement.

Currently the OpenAPI spec says "The requestBody is only supported in HTTP methods where the HTTP 1.1 specification RFC7231 has explicitly defined semantics for request bodies."

I think this should raise a notice, but not be unsupported and raise an error.

@keenle

This comment has been minimized.

Copy link

commented Jan 11, 2019

The way I read the latest specification for Operation requestBody I think it does not strictly prohibit DELETE body:

The request body applicable for this operation. The requestBody is only supported in HTTP methods where the HTTP 1.1 specification RFC7231 has explicitly defined semantics for request bodies. In other cases where the HTTP spec is vague, requestBody SHALL be ignored by consumers.

"... not supported ..." and "... SHALL ..." parts - no clear "cannot have" message.

It would be better to have more concrete language defining that it is allowed to put requestBody property under delete method in Open API v3 spec so existing UI tools stop showing errors when body encountered.

@handrews

This comment has been minimized.

Copy link
Contributor

commented Jan 11, 2019

@keenle UI tools are correct to show an error as the spec says that any such request SHALL be ignored. If your UI tool is trying to show you where you are doing things that don't work, it should highlight this as an error.

@adjenks regarding

"The spec does not explicitly forbid or discourage it, so I would tend to say it is allowed."

"no defined semantics" is standards-ese for "seriously, don't do this, literally anything can happen, but for some reason (probably historical weirdness or difficulty of reliable enforcement) we can't outright forbid it"

Anytime you see "no defined semantics" or "the behavior is undefined" in an RFC, you should stay far away from it.

@keenle

This comment has been minimized.

Copy link

commented Jan 11, 2019

@handrews , agreed on UI behavior in response to the current definition of requestBody in Open API specification. My ask is rather to the specification to allow requestBody as RFC-7231 does not prohibit the payload with DELETE request:

A payload within a DELETE request message has no defined semantics; sending a payload body on a DELETE request might cause some existing implementations to reject the request.

I see the point in your suggestion to stay away from undefined stuff, though there are live services out there which accept payload with DELETE. The approach does make sense in certain scenarios which are out of the scope of this issue.

@adjenks

This comment has been minimized.

Copy link
Author

commented Jan 12, 2019

Users may be documenting an existing legacy API that cannot change, so there may be a DELETE method requiring a body. I understand it's not recommended, but because behavior is "undefined" in the RFC, I think it should be declared as "undefined" in OpenAPI, not "unsupported". Other methods explicitly prohibit the use of a body such as TRACE:

A client MUST NOT send a message body in a TRACE request.

So I believe the same distinction should be made in OpenAPI.

@darrelmiller

This comment has been minimized.

Copy link
Member

commented Jan 12, 2019

@adjenks While I understand the desire to be able to describe existing APIs that have less than ideal behavior, we have to balance that with opening the door for more people to create new APIs that make this same mistake because we allow it.

I don't know why the HTTP spec is explicit about the request body being not allowed on some methods and not on others.

@handrews

This comment has been minimized.

Copy link
Contributor

commented Jan 12, 2019

I don't know why the HTTP spec is explicit about the request body being not allowed on some methods and not on others.

RFC 2616 didn't talk about request bodies for GET, DELETE, or TRACE at all, so I assume when they were working on RFC 7231 they locked things down as much as they could get away with.

RFC 2616 doesn't specifically allow them, it was just pretty light on details of method semantics in general. Part of the reason for the 723x RFCs was to improve that situation.

@notEthan

This comment has been minimized.

Copy link
Contributor

commented Feb 19, 2019

@darrelmiller

While I understand the desire to be able to describe existing APIs that have less than ideal behavior, we have to balance that with opening the door for more people to create new APIs that make this same mistake because we allow it.

I wouldn't expect people to creating APIs to constrain themselves by OpenAPI. when I create an API, first comes the needed functionality, and documenting it with OpenAPI or whatever tool I am using, that comes after. I wouldn't worry about "opening the door" for unencouraged behavior as that's not really OpenAPI's door to hold.

I'm using OpenAPI to document an API that does use delete with a request body, and is not going to change. seems to me I should be able to describe this API with a valid OpenAPI document.

@n2ygk

This comment has been minimized.

Copy link

commented Apr 22, 2019

{json:api} explicitly defines a DELETE request body for updating to-many relationships and it has quite well-defined semantics: Remove only the supplied set of resource identifier objects from the (potentially larger) full list of related resource identifier objects.

I am unable to fully represent a {json:api} schema with OAS if it explicitly prohibits what RFC 7231 allows (as undefined but not prohibited). Please (re)consider allowing a request body for DELETE.

@adjenks

This comment has been minimized.

Copy link
Author

commented Apr 23, 2019

@n2ygk Very interesting....

@adjenks

This comment has been minimized.

Copy link
Author

commented Apr 23, 2019

If one does want to support a request body in their API, they must consider the caching consequences. As stated in RFC7234:

A cache MUST invalidate the effective Request URI (Section 5.5 of
[RFC7230]) as well as the URI(s) in the Location and Content-Location
response header fields (if present) when a non-error status code is
received in response to an unsafe request method.

So, using the example in {json:api}:

DELETE /articles/1/relationships/comments HTTP/1.1
Content-Type: application/vnd.api+json
Accept: application/vnd.api+json

{
  "data": [
    { "type": "comments", "id": "12" },
    { "type": "comments", "id": "13" }
  ]
}

The cache for the resource /articles/1/relationships/comments will be cleared. Imagine this sequence of events:

  1. GET /articles/1/relationships/comments
  2. Server returns 1000 comments
  3. GET /articles/1/relationships/comments
  4. Browser uses cached resource and saves time and energy.
  5. The above example DELETE request is made and it deletes objects 12 and 13 and returns 200.
  6. The browser interprets this as having deleted the resource at /articles/1/relationships/comments and it clears the cache.
  7. GET /articles/1/relationships/comments
  8. Browser fetches 998 comments.

Originally I thought this might be a problem that the cache is being messed with, but really it's a good thing, since you don't want it to use the cached 1000 comments when there are only 998. So having it invalidate the base resource is good. However, it will not invalidate /articles/1/relationships/comments/12 and /articles/1/relationships/comments/13. Therefore fetching a single comment may return invalid results if they were previously requested, cached, deleted via a batch request, and requested again, since the cache may be used.

Overall, if you do choose to create a batch delete method on your API, whether or not anyone recommends it, make sure to check your cache settings and think about how these settings will interact with DELETE requests.

To mitigate this you could disable caching of individual resources, but the client would then have to fetch every time. Using standard HTTP/1 you can't invalidate arbitrary caches, so deleting 12, and 13 in a batch wouldn't clear their cache, as mentioned before, unless you HTTP/2 server push which allows you to send arbitrary other resources along with the response for another request, so your response to a batch delete could pack with it the invalidation of those two resources.

There's a lot to consider here. I do think that it would be great to support a batch delete operation in multiple standards and protocols, but it needs to be thoroughly discussed and everyone would have to cooperate on the appropriate course of action.

It is also interesting to consider that using a custom method, which is the commonly recommended way to perform a batch delete request, such as POST /deleteComments, will also not invalidate any caches associated with the resources that your request intended to delete.

@keenle

This comment has been minimized.

Copy link

commented May 6, 2019

Tiny fact that is missing from this discussion and totally worth mentioning since it can be an obstacle on a path of upgrading from Swagger v2 to Open API v3 is that with Swagger v2 one can declare payload for DELETE method.

Swagger UI can render DELETE endpoint with payload.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.