<?xml version="1.0"?>
<?rfc toc="yes"?>
<?rfc strict="yes"?>
<?rfc symrefs="yes" ?>
<?rfc sortrefs="yes"?>
<?rfc compact="yes"?>
<?rfc comments="yes"?>
<?rfc inline="yes"?>
<?rfc-ext xml2rfc-backend="202007"?>
<?github-issue-label query-method?>
<!DOCTYPE rfc [
  <!ENTITY MAY "<bcp14>MAY</bcp14>">
  <!ENTITY MUST "<bcp14>MUST</bcp14>">
  <!ENTITY MUST-NOT "<bcp14>MUST NOT</bcp14>">
  <!ENTITY OPTIONAL "<bcp14>OPTIONAL</bcp14>">
  <!ENTITY RECOMMENDED "<bcp14>RECOMMENDED</bcp14>">
  <!ENTITY REQUIRED "<bcp14>REQUIRED</bcp14>">
  <!ENTITY SHALL "<bcp14>SHALL</bcp14>">
  <!ENTITY SHALL-NOT "<bcp14>SHALL NOT</bcp14>">
  <!ENTITY SHOULD "<bcp14>SHOULD</bcp14>">
  <!ENTITY SHOULD-NOT "<bcp14>SHOULD NOT</bcp14>">
]>
<rfc category="std" ipr="trust200902" docName="draft-ietf-httpbis-safe-method-w-body-11" submissionType="IETF" consensus="true" version="3" xmlns:xi="http://www.w3.org/2001/XInclude">
  <front>
    <title>
      The HTTP QUERY Method
    </title>

    <author initials="J." surname="Reschke" fullname="Julian Reschke">
      <organization abbrev="greenbytes">greenbytes GmbH</organization>
      <address>
        <postal>
          <street>Hafenweg 16</street>
          <city>Münster</city><code>48155</code>
          <country>Germany</country>
        </postal>
        <email>julian.reschke@greenbytes.de</email>
        <uri>https://greenbytes.de/tech/webdav/</uri>
      </address>
    </author>
    <author initials="J.M." surname="Snell" fullname="James M Snell">
      <organization>Cloudflare</organization>
      <address>
        <email>jasnell@gmail.com</email>
      </address>
    </author>
    <author initials="M." surname="Bishop" fullname="Mike Bishop">
      <organization>Akamai</organization>
      <address>
        <email>mbishop@evequefou.be</email>
      </address>
    </author>

    <date year="2025" month="May" day="19"/>

    <area>Web and Internet Transport</area>
    <workgroup>HTTP</workgroup>
    <keyword>http</keyword>
    <keyword>query</keyword>
    <keyword>method</keyword>

    <abstract>
      <t>
        This specification defines a new HTTP method, QUERY, as a safe, idempotent
        request method that can carry request content.
      </t>
    </abstract>

    <note title="Editorial Note" removeInRFC="true">
      <t>
        Discussion of this draft takes place on the HTTP working group
        mailing list (ietf-http-wg@w3.org), which is archived at
        <eref target="https://lists.w3.org/Archives/Public/ietf-http-wg/"/>.
      </t>
      <t>
        Working Group information can be found at <eref target="https://httpwg.org/"/>;
        source code and issues list for this draft can be found at
        <eref target="https://github.com/httpwg/http-extensions/labels/query-method"/>.
      </t>
      <t>
        The changes in this draft are summarized in <xref target="changes.since.10"/>.
      </t>
    </note>

  </front>

  <middle>

  <section title="Introduction" anchor="introduction">
    <t>
      This specification defines the HTTP QUERY request method as a means of
      making a safe, idempotent request (<xref target="HTTP" section="9.2"/>) that contains content.
    </t>
    <t>
      Most often, this is desirable when the data conveyed in a request is
      too voluminous to be encoded into the request's URI. For example,
      this is a common query pattern:
    </t>
<artwork type="http-message">
GET /feed?q=foo&amp;limit=10&amp;sort=-published HTTP/1.1
Host: example.org
</artwork>
    <t>
      However, for a query with parameters that are complex or large,
      encoding it in the request URI may not be the best option because
    </t>
    <ul>
      <li>often size limits are not known ahead of time because a request can pass through many uncoordinated
      systems (but note that <xref section="4.1" target="HTTP"/> recommends senders and recipients to support at least 8000 octets),</li>
      <li>expressing certain kinds of data in the target URI is inefficient because of the overhead of encoding that data into a valid URI, and</li>
      <li>encoding queries directly into the request URI effectively casts every possible combination of query inputs as distinct
          resources.</li>
    </ul>
    <t>
      As an alternative to using GET, many implementations make use of the
      HTTP POST method to perform queries, as illustrated in the example
      below. In this case, the input to the query operation is
      passed as the request content as opposed to using the
      request URI's query component.
    </t>
    <t>
      A typical use of HTTP POST for requesting a query is:
    </t>
<artwork type="http-message">
POST /feed HTTP/1.1
Host: example.org
Content-Type: application/x-www-form-urlencoded

q=foo&amp;limit=10&amp;sort=-published
</artwork>
    <t>
      This variation, however, suffers from the same basic limitation as GET
      in that it is not readily apparent -- absent specific knowledge of the
      resource and server to which the request is being sent -- that a safe,
      idempotent query is being performed.
    </t>
    <t>
      The QUERY method provides a solution that spans the gap between the use of GET and POST, with
      the example above being expressed as:
    </t>
<artwork type="http-message">
QUERY /feed HTTP/1.1
Host: example.org
Content-Type: application/x-www-form-urlencoded

q=foo&amp;limit=10&amp;sort=-published
</artwork>
    <t>
      As with POST, the input to the query operation is passed as the content of the request
      rather than as part of the request URI. Unlike POST, however, the method is explicitly safe
      and idempotent, allowing functions like caching and automatic retries to operate.
    </t>
    <t>Summarizing:</t>
    <table>
      <name>Summary of relevant method properties</name>
      <thead>
        <tr>
          <th/>
          <th>GET</th>
          <th>QUERY</th>
          <th>POST</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td>Safe</td>
          <td>yes</td>
          <td>yes</td>
          <td>potentially no</td>
        </tr>
        <tr>
          <td>Idempotent</td>
          <td>yes</td>
          <td>yes</td>
          <td>potentially no</td>
        </tr>
        <tr>
          <td>Cacheable</td>
          <td>yes</td>
          <td>yes</td>
          <td>yes, but only for future GET or HEAD requests</td>
        </tr>
        <tr>
          <td>Content (body)</td>
          <td>"no defined semantics"</td>
          <td>expected (semantics per target resource)</td>
          <td>expected (semantics per target resource)</td>
        </tr>
      </tbody>
    </table>

    <section title="Terminology" anchor="terminology">
      <t>
        This document uses terminology defined in <xref section="3" target="HTTP"/>.
      </t>
      <t>
        Furthermore, it uses the terms <em>URI query parameter</em> for parameters
        in the query component of a URI (<xref target="HTTP" section="4.2.2"/>) and
        <em>query content</em> for the request content (<xref target="HTTP" section="6.4"/>)
        of a QUERY request.
      </t>
    </section>

    <section title="Notational Conventions" anchor="notational.conventions">
      <t>
        The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL
        NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED",
        "MAY", and "OPTIONAL" in this document are to be interpreted as
        described in BCP 14 <xref target="RFC2119"/> <xref target="RFC8174"/> when, and only when, they
        appear in all capitals, as shown here.
      </t>
    </section>

  </section>

  <section title="QUERY" anchor="query">
    <t>
      The QUERY method is used to initiate a server-side query. Unlike
      the HTTP GET method, which requests that a server return a
      representation of the resource identified by the target URI
      (as defined by <xref target="HTTP" section="7.1"/>), the QUERY
      method is used to ask the server to perform a query operation
      (described by the request content) over some set of data at the
      resource. The content returned in response to a QUERY
      cannot be assumed to be a representation of the resource identified by
      the target URI.
    </t>
    <t>
      The content of the request and it's media type define the query.
      Implementations &MAY; use a request content of any media type with
      the QUERY method, provided that it has appropriate query semantics.
    </t>
    <t>
      As for all HTTP methods in general, the target URI's query part
      takes part in identifying the resource being queried and therefore is
      not part of the actual query. Whether and how the URI's query part
      directly affects the result of the query is implementation specific
      and out of scope for this specification.
    </t>
    <t>
      QUERY requests are both safe and idempotent with regard to the
      resource identified by the request URI. That is, QUERY requests do not
      alter the state of the identified resource. However, while processing a
      QUERY request, a server can be expected to allocate computing and memory
      resources or even create additional HTTP resources through which the
      response can be retrieved.
    </t>
    <t>
      A successful response to a QUERY request is expected to provide some
      indication as to the final disposition of the operation. For
      instance, a successful query that yields no results can be represented
      by a 204 (No Content, <xref target="HTTP" section="15.3.5"/>) response. If the response includes content,
      it is expected to describe the results of the operation.
    </t>

    <section title="Content-Location and Location Fields" anchor="location">
      <t>
        A successful response (2xx, <xref target="HTTP" section="15.3"/>)
        can include a Content-Location
        header field containing an
        identifier for a resource corresponding to the results of the
        operation; see <xref target="HTTP" section="8.7"/> for details. This represents a claim from the server that a client can send
        a GET request for the indicated URI to retrieve the results of the query
        operation just performed. The indicated resource might be temporary.
      </t>
      <t>
        A server can create or locate a resource that identifies the query
        operation for future use. If the server does so, the URI of the resource
        can be included in the Location header field of the 2xx response (see <xref
        target="HTTP" section="10.2.2"/>). This represents a claim that a client can
        send a GET request to the indicated URI to repeat the query operation just
        performed without resending the query content. This resource might be
        temporary; if a future request fails, the client can retry using the
        original QUERY resource and the previously submitted content.
      </t>
    </section>

    <section title="Redirection" anchor="redirection">
      <t>
        In some cases, the server may choose to respond indirectly to the QUERY
        request by redirecting the user agent to a different URI (see
        <xref target="HTTP" section="15.4"/>). The semantics of the redirect
        response do not differ from other methods.
      </t>
      <t>
        For instance, a 303 (See Other, <xref target="HTTP" section="15.4.4"/>)
        response would indicate that the Location field identifies an
        alternate URI from which the results can be retrieved
        using a GET request (this use case is also covered by the
        use of the Location response field in a 2xx response).
      </t>
      <t>
        On the other hand, response codes 307 (Temporary Redirect, <xref target="HTTP" section="15.4.8"/>) and 308
        (Permanent Redirect, <xref target="HTTP" section="15.4.9"/>) can be used to request the user agent to redo
        the QUERY request on the URI specified by the Location field.
      </t>
      <t>
        Various non-normative examples of successful
        QUERY responses are illustrated in <xref target="examples"/>.
      </t>
    </section>

    <section title="Conditional Requests" anchor="conditional">
      <t>
        A conditional QUERY requests that the selected representation
        (i.e., the query results, after any content negotiation) be
        returned in the response only under the circumstances described by the
        conditional header field(s), as defined in
        <xref target="HTTP" section="13"/>.
      </t>
    </section>

    <section title="Caching" anchor="caching">
      <t>
        The response to a QUERY method is cacheable; a cache &MAY; use it to satisfy subsequent
        QUERY requests as per <xref target="HTTP-CACHING" section="4"/>).
      </t>
      <t>
        The cache key for a QUERY request (see <xref target="HTTP-CACHING" section="2"/>) &MUST;
        incorporate the request content. When doing so, caches &SHOULD; first normalize request
        content to remove semantically insignificant differences, thereby improving cache
        efficiency, by:
      </t>
      <ul>
        <li>Removing content encoding(s) (<xref target="HTTP" section="8.4"/>).</li>
        <li>Normalizing based upon knowledge of format conventions, as indicated by any
          media subtype suffix in the request's Content-Type field (e.g., "+json", see
          <xref target="RFC6838" section="4.2.8"/>).</li>
        <li>Normalizing based upon knowledge of the semantics of the content itself, as indicated by
          the request's Content-Type field.</li>
      </ul>
      <t>
        Note that any such normalization is performed solely for the purpose of generating a cache key; it
        does not change the request itself.
      </t>
    </section>

    <section title="Range Requests" anchor="range">
      <t>
        The semantics of Range Requests for QUERY are identical to those for GET,
        as defined in <xref target="HTTP" section="14"/>.
      </t>
    </section>

  </section>

  <section title="The &quot;Accept-Query&quot; Header Field" anchor="field.accept-query">
    <t>
      The "Accept-Query" response header field can be used by a resource to
      directly signal support for the QUERY method while identifying
      the specific query format media type(s) that may be used.
    </t>
    <t>
      Accept-Query contains a list of media ranges (<xref target="HTTP" section="12.5.1"/>)
      using "Structured Fields" syntax (<xref target="STRUCTURED-FIELDS"/>).
      Media ranges are represented by a List Structured Header Field of either Tokens or
      Strings, containing the media range value without parameters.
    </t>
    <t>
      Media type parameters, if any, are mapped to Structured Field Parameters of type
      String or Token. The choice of Token vs. String is semantically insignificant. That is,
      recipients &MAY; convert Tokens to Strings, but &MUST-NOT; process them
      differently based on the received type.
    </t>
    <t>
      Media types do not exactly map to Tokens, for instance they
      allow a leading digit. In cases like these, the String format needs to
      be used.
    </t>
    <t>
      The only supported uses of wildcards are "*/*", which matches any type,
      or "xxxx/*", which matches any subtype of the indicated type.
    </t>
    <t>
      The order of types listed in the field value is not significant.
    </t>
    <t>
      The value of the Accept-Query field applies to every URI on the server that shares the same path; in
      other words, the query component is ignored. If requests to the same resource return
      different Accept-Query values, the most recently received fresh value (per
      <xref target="HTTP-CACHING" section="4.2"/>) is used.
    </t>
    <t>
      Example:
    </t>
    <artwork type="example">
Accept-Query: "application/jsonpath", application/sql;charset="UTF-8"</artwork>
    <t>
      Although the syntax for this field appears to be similar to other
      fields, such as "Accept" (<xref target="HTTP" section="12.5.1"/>),
      it is a Structured Field and thus &MUST; be processed as specified in
      <xref target="STRUCTURED-FIELDS" section="4"/>.
    </t>
  </section>

  <section title="Security Considerations">
    <t>
      The QUERY method is subject to the same general security
      considerations as all HTTP methods as described in
      <xref target="HTTP"/>.
    </t>
    <t>
      It can be used as an alternative to passing request
      information in the URI (e.g., in the query component). This is preferred in some
      cases, as the URI is more likely to be logged or otherwise processed
      by intermediaries than the request content. In other cases, where the query
      contains sensitive information, the potential for logging of the URI might
      motivate the use of QUERY over GET.
    </t>
    <t>
      If a server creates a temporary resource to represent the results of a QUERY
      request (e.g., for use in the Location or Content-Location field) and the request
      contains sensitive information that cannot be logged, then the URI of this
      resource &SHOULD; be chosen such that it does not include any sensitive
      portions of the original request content.
    </t>
    <t>
      Caches that normalize QUERY content incorrectly or in ways that are
      significantly different from how the resource processes the content
      can return an incorrect response if normalization results in a false positive.
    </t>
    <t>
      A QUERY request from user agents implementing CORS (Cross-Origin Resource Sharing)
      will require a "preflight" request,
      as QUERY does not belong to the set of CORS-safelisted methods
      (see "<eref target="https://fetch.spec.whatwg.org/#methods">Methods</eref>" in
      <xref target="FETCH"/>).
    </t>
  </section>

  <section title="IANA Considerations" anchor="iana.considerations">

    <section title="Registration of QUERY method" anchor="method.registration">
      <t>
        IANA is requested to add the QUERY method to the HTTP
        Method Registry at <eref brackets="angle" target="http://www.iana.org/assignments/http-methods"/>
        (see <xref target="HTTP" section="16.3.1"/>).
      </t>
      <table>
        <thead>
          <tr>
            <th>Method Name</th>
            <th>Safe</th>
            <th>Idempotent</th>
            <th>Specification</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td>QUERY</td>
            <td>Yes</td>
            <td>Yes</td>
            <td><xref target="query"/></td>
          </tr>
        </tbody>
      </table>
    </section>

    <section title="Registration of Accept-Query field" anchor="field.registration">
      <t>
        IANA is requested to add the Accept-Query field to the HTTP Field Name
        Registry at <eref brackets="angle" target="https://www.iana.org/assignments/http-fields"/>
        (see <xref target="HTTP" section="16.1.1"/>).
      </t>
      <table>
        <thead>
          <tr>
            <th>Field Name</th>
            <th>Status</th>
            <th>Structured Type</th>
            <th>Reference</th>
            <th>Comments</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td>Accept-Query</td>
            <td>permanent</td>
            <td>List</td>
            <td><xref target="field.accept-query"/> of this document.</td>
            <td></td>
          </tr>
        </tbody>
      </table>
    </section>
</section>
</middle>
<back>
  <references title="Normative References">
    <xi:include href="https://www.rfc-editor.org/refs/bibxml/reference.RFC.2119.xml"/>
    <xi:include href="https://www.rfc-editor.org/refs/bibxml/reference.RFC.8174.xml"/>
    <reference anchor="HTTP">
      <front>
        <title>HTTP Semantics</title>
        <author fullname="Roy T. Fielding" initials="R." surname="Fielding" role="editor"/>
        <author fullname="Mark Nottingham" initials="M." surname="Nottingham" role="editor"/>
        <author fullname="Julian Reschke" initials="J." surname="Reschke" role="editor"/>
        <date year="2022" month="June"/>
      </front>
      <seriesInfo name="STD" value="97"/>
      <seriesInfo name="RFC" value="9110"/>
    </reference>
    <reference anchor="HTTP-CACHING">
      <front>
        <title>HTTP Caching</title>
        <author fullname="Roy T. Fielding" initials="R." surname="Fielding" role="editor"/>
        <author fullname="Mark Nottingham" initials="M." surname="Nottingham" role="editor"/>
        <author fullname="Julian Reschke" initials="J." surname="Reschke" role="editor"/>
        <date year="2022" month="June"/>
      </front>
      <seriesInfo name="STD" value="98"/>
      <seriesInfo name="RFC" value="9111"/>
    </reference>
    <reference anchor="STRUCTURED-FIELDS">
      <front>
        <title>Structured Field Values for HTTP</title>
        <author initials="M." surname="Nottingham" fullname="Mark Nottingham">
          <organization>Cloudflare</organization>
        </author>
        <author initials="P-H." surname="Kamp" fullname="Poul-Henning Kamp">
          <organization>The Varnish Cache Project</organization>
        </author>
        <date year="2024" month="September"/>
      </front>
      <seriesInfo name="RFC" value="9651"/>
    </reference>
  </references>
  <references title="Informative References">
    <reference anchor="FETCH" target="https://fetch.spec.whatwg.org">
      <front>
        <title>FETCH</title>
        <author><organization>WHATWG</organization></author>
      </front>
    </reference>
    <xi:include href="https://www.rfc-editor.org/refs/bibxml/reference.RFC.6838.xml"/>
    <xi:include href="https://www.rfc-editor.org/refs/bibxml/reference.RFC.8259.xml"/>
    <xi:include href="https://www.rfc-editor.org/refs/bibxml/reference.RFC.9535.xml"/>
    <reference anchor="URL" target="https://url.spec.whatwg.org">
      <front>
        <title>URL</title>
        <author><organization>WHATWG</organization></author>
      </front>
    </reference>
    <reference anchor="XSLT" target='https://www.w3.org/TR/2017/REC-xslt-30-20170608/'>
      <front>
        <title>XSL Transformations (XSLT) Version 3.0</title>
        <author fullname='Michael Kay' surname='Kay' initials='M.'/>
        <date year='2017' month='June' day='08'/>
      </front>
      <seriesInfo name='W3C Recommendation' value='REC-xslt-30-20170608'/>
      <annotation>
        Latest version available at
        <eref target='https://www.w3.org/TR/xslt-30/'/>.
      </annotation>
    </reference>
  </references>

  <section title="Examples" anchor="examples">
    <t>
      The examples below are for illustrative purposes only; if one needs to
      send queries that are actually this short, it is likely better to use GET.
    </t>
    <t>
      The media type used in most examples is "application/x-www-form-urlencoded"
      (as used in POST requests from browser user clients, defined in
      "<eref target="https://url.spec.whatwg.org/#application/x-www-form-urlencoded">application/x-www-form-urlencoded</eref>" in
      <xref target="URL"/>).
      The Content-Length fields have been omitted for brevity.
    </t>

    <section title="Simple Query" anchor="example.simple">
      <t>A simple query with a direct response:</t>
<artwork type="http-message">
QUERY /contacts HTTP/1.1
Host: example.org
Content-Type: application/x-www-form-urlencoded
Accept: application/json

select=surname,givenname,email&amp;limit=10&amp;match=%22email=*@example.*%22
</artwork>

      <t>Response:</t>
<artwork type="http-message">
HTTP/1.1 200 OK
Content-Type: application/json

[
  { "surname": "Smith",
    "givenname": "John",
    "email": "smith@example.org" },
  { "surname": "Jones",
    "givenname": "Sally",
    "email": "sally.jones@example.com" },
  { "surname": "Dubois",
    "givenname": "Camille",
    "email": "camille.dubois@example.net" }
]
</artwork>
    </section>

    <section title="Discovery of QUERY support" anchor="example.discovery.method">
      <t>
        A simple way to discover support for QUERY is provided by the OPTIONS
        (<xref target="HTTP" section="9.3.7"/>) method:
      </t>
<artwork type="http-message">
OPTIONS /contacts HTTP/1.1
Host: example.org

</artwork>
      <t>Response:</t>
<artwork type="http-message">
HTTP/1.1 200 OK
Allow: GET, QUERY, OPTIONS, HEAD
</artwork>
      <t>
        The Allow response field (<xref target="HTTP" section="10.2.1"/>) denotes the set of
        supported methods on the specified resource.
      </t>
      <t>
        There are alternatives to the use of OPTIONS. For instance, a QUERY request
        can be tried without prior knowledge of server support. The server would then
        either process the request, or could respond with a 4xx status such as 405 (Method Not Allowed,
        <xref target="HTTP" section="15.5.6"/>), including the Allow response field.
      </t>
    </section>

    <section title="Discovery of QUERY Formats" anchor="example.discovery.formats">
      <t>
        Discovery of supported media types for QUERY is possible via the Accept-Query
        (<xref target="field.accept-query"/>) response field:
      </t>
<artwork type="http-message">
HEAD /contacts HTTP/1.1
Host: example.org

</artwork>
      <t>Response:</t>
<artwork type="http-message">
HTTP/1.1 200 OK
Content-Type: application/xhtml
Accept-Query: application/x-www-form-urlencoded, application/sql
</artwork>
      <t>
        Responses to which request methods will contain Accept-Query will depend on
        the resource being accessed.
      </t>
      <t>
        An alternative to checking Accept-Query would be to make a QUERY request, and then
        -- in case of a 4xx status such as 415 (Unsupported Media Type, <xref target="HTTP" section="15.5.16"/>) response --
        to inspect the Accept (<xref target="HTTP" section="12.5.1"/>) response field:
      </t>
<artwork type="http-message">
HTTP/1.1 415 Unsupported Media Type
Content-Type: application/xhtml
Accept: application/x-www-form-urlencoded, application/sql
</artwork>
    </section>

    <section title="Content-Location, Location, and Indirect Responses" anchor="example.content-location.location.indirect">
      <t>
        As described in <xref target="location"/>, the Content-Location and Location response fields in success responses
        (2xx, <xref target="HTTP" section="15.3"/>) provide a way to identify alternate resources
        that will respond to GET requests, either for the received result of the request, or for future
        requests to perform the same operation. Going back to the example from <xref target="example.simple"/>:
      </t>
<artwork type="http-message">
QUERY /contacts HTTP/1.1
Host: example.org
Content-Type: application/x-www-form-urlencoded
Accept: application/json

select=surname,givenname,email&amp;limit=10&amp;match=%22email=*@example.*%22
</artwork>
        <t>Response:</t>
<artwork type="http-message">
HTTP/1.1 200 OK
Content-Type: application/json
Content-Location: /contacts/stored-results/17
Location: /contacts/stored-queries/42
Last-Modified: Sat, 25 Aug 2012 23:34:45 GMT
Date: Sun, 17 Nov 2024, 16:10:24 GMT

[
  { "surname": "Smith",
    "givenname": "John",
    "email": "smith@example.org" },
  { "surname": "Jones",
    "givenname": "Sally",
    "email": "sally.jones@example.com" },
  { "surname": "Dubois",
    "givenname": "Camille",
    "email": "camille.dubois@example.net" }
]
</artwork>

      <section title="Using Content-Location" anchor="example.content-location">
        <t>
          The Content-Location response field received above identifies a resource holding
          the result for the QUERY response it appeared on:
        </t>
<artwork type="http-message">
GET /contacts/stored-results/17 HTTP/1.1
Host: example.org
Accept: application/json

</artwork>
        <t>Response:</t>
<artwork type="http-message">
HTTP/1.1 200 OK
Last-Modified: Sat, 25 Aug 2012 23:34:45 GMT
Date: Sun, 17 Nov 2024, 16:10:25 GMT

[
  { "surname": "Smith",
    "givenname": "John",
    "email": "smith@example.org" },
  { "surname": "Jones",
    "givenname": "Sally",
    "email": "sally.jones@example.com" },
  { "surname": "Dubois",
    "givenname": "Camille",
    "email": "camille.dubois@example.net" }
]
</artwork>
      </section>

      <section title="Using Location" anchor="example.location">
        <t>
          The Location response field identifies a resource that will respond to GET
          with a fresh result for the QUERY response it appeared on.
        </t>
<artwork type="http-message">
GET /contacts/stored-queries/42 HTTP/1.1
Host: example.org
Accept: application/json

</artwork>
        <t>
          In this example, one entry was removed at 2024-11-17T16:12:01Z (as indicated in
          the Last-Modified field), so the response only contains two entries:
        </t>
<artwork type="http-message">
HTTP/1.1 200 OK
Content-Type: application/json
Last-Modified: Sun, 17 November 2024, 16:12:01 GMT
ETag: "42-1"
Date: Sun, 17 Nov 2024, 16:13:17 GMT

[
  { "surname": "Smith",
    "givenname": "John",
    "email": "smith@example.org" },
  { "surname": "Dubois",
    "givenname": "Camille",
    "email": "camille.dubois@example.net" }
]
</artwork>
        <t>
          Assuming no change in the query result, a subsequent conditional GET request with
        </t>
<artwork type="http-message">
If-None-Match: "42-1"
</artwork>
        <t>
          would result in a 304 response (Not Modified, <xref target="HTTP" section="15.4.5"/>).
        </t>
        <t>
          Note that there's no guarantee that the server will implement this resource
          indefinitely, so, after an error response, the client would need to redo
          the original QUERY request in order to obtain a new alternative location.
        </t>
      </section>

      <section title="Indirect Responses" anchor="example.indirect">
        <t>
          Servers can send "indirect" responses (<xref target="redirection"/>) using the status code 303 (See Other,
          <xref target="HTTP" section="15.4.4"/>).
        </t>
        <t>
          Given the request at the beginning of <xref target="example.content-location.location.indirect"/>,
          a server might respond with:
        </t>
<artwork type="http-message">
HTTP/1.1 303 See Other
Content-Type: text/plain
Date: Sun, 17 Nov 2024, 16:13:17 GMT
Location: /contacts/stored-queries/42

See stored query at "/contacts/stored-queries/42".
</artwork>
        <t>
          This is similar to including Location on a direct response, except that no result
          for the query is returned. This allows the server to only generate an alternative
          resource. This resource could then be used as shown in
          <xref target="example.location"/>.
        </t>
      </section>
    </section>

    <section title="More Query Formats" anchor="example.more.query.formats">
      <t>
        The following examples show requests on a JSON-shaped (<xref target="RFC8259"/>) database of
        RFC errata.
      </t>
      <t>
        The request below uses XSLT (<xref target="XSLT"/>) to extract errata information summarized per year and
        the defined errata types.
      </t>
<artwork type="http-message">
QUERY /errata.json HTTP/1.1
Host: example.org
Content-Type: application/xslt+xml
Accept: application/xml, text/csv

<![CDATA[<transform xmlns="http://www.w3.org/1999/XSL/Transform"
  xmlns:j="http://www.w3.org/2005/xpath-functions"
  version="3.0">

  <output method="text"/>

  <param name="input"/>

  <variable name="json"
    select="json-to-xml(unparsed-text($input))"/>

  <variable name="sc">errata_status_code</variable>
  <variable name="sd">submit_date</variable>

  <template match="/">
    <text>year, total, rejected, verified, hdu, reported</text>
    <text>&#10;</text>
    <variable name="en" select="$json//j:map"/>
    <for-each-group select="$en"
      group-by="substring-before(j:string[@key=$sd],'-')">
      <sort select="current-grouping-key()"/>
      <variable name="year" select="current-grouping-key()"/>
      <variable name="errata" select=
        "$en[$year=substring-before(j:string[@key=$sd],'-')]"/>
      <value-of select="concat(
        $year,
        ', ',
        count($errata),
        ', ',
        count($errata['Rejected'=j:string[@key=$sc]]),
        ', ',
        count($errata['Verified'=j:string[@key=$sc]]),
        ', ',
        count(
          $errata['Held for Document Update'=j:string[@key=$sc]]),
        ', ',
        count($errata['Reported'=j:string[@key=$sc]]),
        '&#10;')"/>
    </for-each-group>
  </template>

</transform>]]>
</artwork>
    <t>
      Response:
    </t>
<artwork type="http-message">
HTTP/1.1 200 OK
Content-Type: text/csv
Accept-Query: "application/jsonpath", "application/xslt+xml"
Date: Wed, 19 Feb 2025, 17:10:01 GMT

year, total, rejected, verified, hdu, reported
2000, 14, 0, 14, 0, 0
2001, 72, 1, 70, 1, 0
2002, 124, 8, 104, 12, 0
2003, 63, 0, 61, 2, 0
2004, 89, 1, 83, 5, 0
2005, 156, 10, 96, 50, 0
2006, 444, 54, 176, 214, 0
2007, 429, 48, 188, 193, 0
2008, 423, 52, 165, 206, 0
2009, 331, 39, 148, 144, 0
2010, 538, 80, 232, 222, 4
2011, 367, 47, 170, 150, 0
2012, 348, 54, 149, 145, 0
2013, 341, 61, 169, 106, 5
2014, 342, 73, 180, 72, 17
2015, 343, 79, 145, 89, 30
2016, 295, 46, 122, 82, 45
2017, 303, 46, 120, 84, 53
2018, 350, 61, 118, 98, 73
2019, 335, 47, 131, 94, 63
2020, 387, 68, 117, 123, 79
2021, 321, 44, 148, 63, 66
2022, 358, 37, 198, 40, 83
2023, 262, 38, 121, 33, 70
2024, 322, 33, 125, 23, 141
9999, 1, 0, 0, 1, 0
</artwork>
    <t>
      Note the Accept-Query response field indicating that another query format -- JSONPath
      (<xref target="RFC9535"/>) -- is supported as well. The request below would report the
      identifiers of all rejected errata submitted since 2024:
    </t>
<artwork type="http-message">
QUERY /errata.json HTTP/1.1
Host: example.org
Content-Type: application/jsonpath
Accept: application/json

$..[
     ?@.errata_status_code=="Rejected"
     &amp;&amp; @.submit_date>"2024"
   ]
   ["doc-id"]
</artwork>
      <t>
        Response:
      </t>
<artwork type="http-message">
HTTP/1.1 200 OK
Content-Type: application/json
Accept-Query: "application/jsonpath", "application/xslt+xml"
Date: Thu, 20 Feb 2025, 09:55:42 GMT
Last-Modified: Thu, 20 Feb 2025 06:10:01 GMT

[
  "RFC1185","RFC8407","RFC6350","RFC8467","RFC1157","RFC9543",
  "RFC9076","RFC7656","RFC2822","RFC9460","RFC2104","RFC6797",
  "RFC9499","RFC9557","RFC2131","RFC2328","RFC9001","RFC3325",
  "RFC9438","RFC2526","RFC2985","RFC7643","RFC9132","RFC6376",
  "RFC9110","RFC9460","RFC7748","RFC9497","RFC8463","RFC4035",
  "RFC7239","RFC9083","RFC9537","RFC9537","RFC9420","RFC9000",
  "RFC9656","RFC9110","RFC2324","RFC2549","RFC6797","RFC2549",
  "RFC8894"
]
</artwork>
    </section>
</section>

<section title="Change Log" anchor="change.log" removeInRFC="true">
<section title="Since draft-ietf-httpbis-safe-method-w-body-00" anchor="changes.since.00">
<ul>
  <li>Use "example/query" media type instead of undefined "text/query" (<eref target="https://github.com/httpwg/http-extensions/issues/1450"/>)</li>
  <li>In <xref target="field.accept-query"/>, adjust the grammar to just define the field value (<eref target="https://github.com/httpwg/http-extensions/issues/1470"/>)</li>
  <li>Update to latest HTTP core spec, and adjust terminology accordingly (<eref target="https://github.com/httpwg/http-extensions/issues/1473"/>)</li>
  <li>Reference RFC 8174 and markup bcp14 terms (<eref target="https://github.com/httpwg/http-extensions/issues/1497"/>)</li>
  <li>Update HTTP reference (<eref target="https://github.com/httpwg/http-extensions/issues/1524"/>)</li>
  <li>Relax restriction of generic XML media type in request content (<eref target="https://github.com/httpwg/http-extensions/issues/1535"/>)</li>
</ul>
</section>
<section title="Since draft-ietf-httpbis-safe-method-w-body-01" anchor="changes.since.01">
<ul>
  <li>Add minimal description of cacheability (<eref target="https://github.com/httpwg/http-extensions/issues/1552"/>)</li>
  <li>Use "QUERY" as method name (<eref target="https://github.com/httpwg/http-extensions/issues/1614"/>)</li>
  <li>Update HTTP reference (<eref target="https://github.com/httpwg/http-extensions/issues/1669"/>)</li>
</ul>
</section>
<section title="Since draft-ietf-httpbis-safe-method-w-body-02" anchor="changes.since.02">
<ul>
  <li>In <xref target="field.accept-query"/>, slightly rephrase statement about significance of ordering (<eref target="https://github.com/httpwg/http-extensions/issues/1896"/>)</li>
  <li>Throughout: use "content" instead of "payload" or "body" (<eref target="https://github.com/httpwg/http-extensions/issues/1915"/>)</li>
  <li>Updated references (<eref target="https://github.com/httpwg/http-extensions/issues/2157"/>)</li>
</ul>
</section>
<section title="Since draft-ietf-httpbis-safe-method-w-body-03" anchor="changes.since.03">
<ul>
  <li>In <xref target="field.accept-query"/>, clarify scope (<eref target="https://github.com/httpwg/http-extensions/issues/1913"/>)</li>
</ul>
</section>
<section title="Since draft-ietf-httpbis-safe-method-w-body-04" anchor="changes.since.04">
<ul>
  <li>Describe role of Content-Location and Location fields (<eref target="https://github.com/httpwg/http-extensions/issues/1745"/>)</li>
  <li>Added Mike Bishop as author (<eref target="https://github.com/httpwg/http-extensions/issues/2837"/>)</li>
  <li>Use "target URI" instead of "effective request URI" (<eref target="https://github.com/httpwg/http-extensions/issues/2883"/>)</li>
</ul>
</section>
<section title="Since draft-ietf-httpbis-safe-method-w-body-05" anchor="changes.since.05">
<ul>
  <li>Updated language and examples about redirects and method rewriting (<eref target="https://github.com/httpwg/http-extensions/issues/1917"/>)</li>
  <li>Add QUERY example to introduction (<eref target="https://github.com/httpwg/http-extensions/issues/2171"/>)</li>
  <li>Update "Sensitive information in QUERY URLs" (<eref target="https://github.com/httpwg/http-extensions/issues/2853"/>)</li>
  <li>Field registration for "Accept-Query" (<eref target="https://github.com/httpwg/http-extensions/issues/2903"/>)</li>
</ul>
</section>
<section title="Since draft-ietf-httpbis-safe-method-w-body-06" anchor="changes.since.06">
<ul>
  <li>Improve language about sensitive information in URIs (<eref target="https://github.com/httpwg/http-extensions/issues/1895"/>)</li>
  <li>Guidance about what's possible with GET wrt URI length (<eref target="https://github.com/httpwg/http-extensions/issues/1914"/>)</li>
  <li>Clarified description of conditional queries (<eref target="https://github.com/httpwg/http-extensions/issues/1917"/>)</li>
  <li>Editorial changes to Introduction (ack Will Hawkins, <eref target="https://github.com/httpwg/http-extensions/pull/2859"/>)</li>
  <li>Added Security Consideration with respect to Normalization (<eref target="https://github.com/httpwg/http-extensions/issues/2896"/>)</li>
  <li>Added CORS considerations (<eref target="https://github.com/httpwg/http-extensions/issues/2898"/>)</li>
  <li>Make Accept-Query a Structured Field (<eref target="https://github.com/httpwg/http-extensions/issues/2934"/>)</li>
  <li>SQL media type is application/sql (RFC6922) (<eref target="https://github.com/httpwg/http-extensions/issues/2936"/>)</li>
  <li>Added overview table to introduction (<eref target="https://github.com/httpwg/http-extensions/issues/2951"/>)</li>
  <li>Reference HTTP spec for terminology (<eref target="https://github.com/httpwg/http-extensions/issues/2953"/>)</li>
  <li>Moved BCP14 related text into subsection (<eref target="https://github.com/httpwg/http-extensions/issues/2954"/>)</li>
  <li>Move examples into index (<eref target="https://github.com/httpwg/http-extensions/issues/2957"/>)</li>
</ul>
</section>
<section title="Since draft-ietf-httpbis-safe-method-w-body-07" anchor="changes.since.07">
<ul>
  <li>Examples Section revised (<eref target="https://github.com/httpwg/http-extensions/issues/1906"/>)</li>
  <li>Discuss Range Requests (<eref target="https://github.com/httpwg/http-extensions/issues/2979"/>)</li>
</ul>
</section>
<section title="Since draft-ietf-httpbis-safe-method-w-body-08" anchor="changes.since.08">
<ul>
  <li>Mention the role of the query part of the request URI (<eref target="https://github.com/httpwg/http-extensions/issues/3004"/>)</li>
  <li>Avoid term 'query parameters' (<eref target="https://github.com/httpwg/http-extensions/issues/3019"/>)</li>
  <li>Add missing references, fixed terminology (<eref target="https://github.com/httpwg/http-extensions/issues/3021"/>)</li>
  <li>Add Acknowledgements/Contributors sections; moved Ashok to Contributors (<eref target="https://github.com/httpwg/http-extensions/issues/3029"/>)</li>
  <li>Hopefully more clarity wrt query content vs URI query component (<eref target="https://github.com/httpwg/http-extensions/issues/3059"/>)</li>
</ul>
</section>
<section title="Since draft-ietf-httpbis-safe-method-w-body-09" anchor="changes.since.09">
<ul>
  <li>Clarify cacheability of POST (<eref target="https://github.com/httpwg/http-extensions/issues/3068"/>)</li>
  <li>Rephrase text that suggests a media type definition can override URI semantics (<eref target="https://github.com/httpwg/http-extensions/issues/3069"/>)</li>
  <li>Restrict description of Content-Location and Location semantics to 2xx responses (<eref target="https://github.com/httpwg/http-extensions/issues/3070"/>)</li>
  <li>Slightly rephrase semantics for Content-Location (<eref target="https://github.com/httpwg/http-extensions/issues/3071"/>)</li>
</ul>
</section>
<section title="Since draft-ietf-httpbis-safe-method-w-body-10" anchor="changes.since.10">
<ul>
  <li>Editorial nits (<eref target="https://github.com/httpwg/http-extensions/pull/3080"/>, ack martinthomson)</li>
  <li>Fix references in <xref target="example.discovery.formats"/> (<eref target="https://github.com/httpwg/http-extensions/pull/3090"/>, ack Rahul Gupta)</li>
  <li>Update James' affiliation (<eref target="https://github.com/httpwg/http-extensions/pull/3094"/>)</li>
  <li>Review references to HTTP  (<eref target="https://github.com/httpwg/http-extensions/pull/3097"/>)</li>
  <li>Address most Rahul Gupta's additional feedback (<eref target="https://github.com/httpwg/http-extensions/pull/3101"/>)</li>
</ul>
</section>
</section>

<section title="Acknowledgements" anchor="acknowledgements" numbered="false">
<t>
  We thank all members of the HTTP Working Group for ideas, reviews, and feedback.
</t>
<t>
  The following individuals deserve special recognition:
  Carsten Bormann,
  Mark Nottingham,
  Martin Thomson,
  Michael Thornburgh,
  Roberto Polli,
  Roy Fielding, and
  Will Hawkins.
</t>
</section>

<section title="Contributors" anchor="contributors" numbered="false">
<t>
  Ashok Malhotra participated in early discussions leading to this
  specification:
</t>
<author initials="A." surname="Malhotra" fullname="Ashok Malhotra">
  <address>
    <email>malhotrasahib@gmail.com</email>
  </address>
</author>
</section>
</back>
</rfc>
