Search code examples
restapihttp-get

API: Which verb should we use with array parameters


For example, we need to have an API method, which get array as input (array of id of devices) and returns list of these devices (full information about each device).

So, there are all attributes of GET method, but it's a bad idea to pass it in url (array can be big), so, it would be better to pass it in body:

    [HttpGet("api/deviceNames")]
    [ProducesResponseType(typeof(List<DeviceInfo>), StatusCodes.Status200OK)]
    public IActionResult GetDeviceNamesByIds([FromBody]List<string> deviceIds)
    {
        var d = _deviceService.GetDevicesByIds(deviceIds);

        return Ok(d);
    }

It works and works fine. But many authors don't recommend to use body for GET methods, e.g. https://groups.yahoo.com/neo/groups/rest-discuss/conversations/messages/9962?guccounter=1

Yes. In other words, any HTTP request message is allowed to contain a message body, and thus must parse messages with that in mind. Server semantics for GET, however, are restricted such that a body, if any, has no semantic meaning to the request. The requirements on parsing are separate from the requirements on method semantics.

So, yes, you can send a body with GET, and no, it is never useful to do so.

This is part of the layered design of HTTP/1.1 that will become clear again once the spec is partitioned (work in progress).

....Roy

but, from other side:

Update The RFC2616 referenced as "HTTP/1.1 spec" is now obsolete. In 2014 it was replaced by RFCs 7230-7237. Quote "the message-body SHOULD be ignored when handling the request" has been deleted. It's now just "Request message framing is independent of method semantics, even if the method doesn't define any use for a message body" The 2nd quote "The GET method means retrieve whatever information ... is identified by the Request-URI" was deleted. - From a comment


Solution

  • RFC 7231 didn't change the semantics

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

    It doesn't work fine - not really. The problem is that the caching semantics of HTTP don't consider the request body; general purpose components are going to assume that the server respects the standardized semantics, and therefore are not going to be digging in the message-body of the request to look to see if the request array matches any of the previously cached representations.

    That in turn means, in order to prevent problems with compliant components, you are going to have to disable caching of your resource.

    Since caching is an important constraint in the REST architectural style, this is clearly a step in the wrong direction.

    If you must use a payload, then you should probably be looking at POST, rather than GET. See also: SOAP, GraphQL.

    But POST is not idempotent at all

    That's right. There's a trade-off that needs to be made.