http-extensions icon indicating copy to clipboard operation
http-extensions copied to clipboard

Header to request always using QUERY over GET

Open jamesagnew opened this issue 3 years ago • 10 comments

First, apologies if this is not the right venue for this comment.

I'd like to suggest an enhancement to draft-ietf-httpbis-safe-method-w-body-02.

I work on the HL7 FHIR standard, which is a healthcare scoped exchange API standard layered on HTTP.

The FHIR search API supports searching using either GET (with search parameters on the URL) or POST (with search parameters in the body). A common complaint is that the GET mechanism is inappropriate on many networks because the search parameters are PII/PHI and should therefore never appear in a URL that may be logged by network infrastructure.

I think a useful addition to this draft would be a server/response header indicating that QUERY should always be used in place of GET. This could be thought of as a similar function to a server using Strict-Transport-Security to request that clients always use HTTPS.

One potential syntax could be as an addition to the Accept-Query header, perhaps by a syntax like:

Accept-Query: application/x-www-form-urlencoded; preferred

jamesagnew avatar Jan 31 '22 22:01 jamesagnew

Am 31.01.2022 um 23:52 schrieb James Agnew:

First, apologies if this is not the right venue for this comment.

No worries, it's the right place.

I'd like to suggest an enhancement to draft-ietf-httpbis-safe-method-w-body-02 https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-safe-method-w-body-02.

I work on the HL7 FHIR http://hl7.org/fhir/ standard, which is a healthcare scoped exchange API standard layered on HTTP.

The FHIR search API supports searching using either GET (with search parameters on the URL) or POST (with search parameters in the body). A common complaint is that the GET mechanism is inappropriate on many networks because the search parameters are PII/PHI and should therefore never appear in a URL that may be logged by network infrastructure.

I think a useful addition to this draft would be a server/response header indicating that QUERY should always be used in place of GET. This could be thought of as a similar function to a server using |Strict-Transport-Security| to request that clients always use HTTPS.

Hmm. When GET is used, the potential leakage has already happened. Do you think that client would stop using GET unless you actually fail the request?

(so I'm not sure how this would work in practice)

One potential syntax could be as an addition to the |Accept-Query| header, perhaps by a syntax like:

|Accept-Query: application/x-www-form-urlencoded; preferred |

That tells the client that QUERY is supported and "application/x-www-form-urlencoded" is accepted, but not that GET is discouraged (but yes, it could be understood as a signal for that if a client cares about that).

I don't believe the "preferred" parameter would work; this would need to be a defined media type parameter for "application/x-www-form-urlencoded".

Best regards, Julian

reschke avatar Feb 01 '22 09:02 reschke

@reschke Appreciate the response!

Hmm. When GET is used, the potential leakage has already happened. Do you think that client would stop using GET unless you actually fail the request?

At least in our case, the typical interaction is for the client to begin the interaction with an OPTIONS request to probe the server's capabilities. So that would be the opportunity for the client to discover that the server wants QUERY and not GET.

Accept-Query: application/x-www-form-urlencoded; preferred That tells the client that QUERY is supported and "application/x-www-form-urlencoded" is accepted, but not that GET is discouraged (but yes, it could be understood as a signal for that if a client cares about that).

The thing I was suggesting is tacking the ; preferred bit on at the end, as an indication that this is what the server wants. At least to me this feels to be in line with how content negotiation works in the Accept header.

I guess ultimately this is not a perfect solution to this problem, but ultimately I don't think there is a perfect solution given that HTTP interactions begin with an unsolicited message from the client. At least to me this feels like an incremental improvement though.

Either way, I do love the broader QUERY verb proposal. It'll be a big net positive for API development on the web.

jamesagnew avatar Feb 01 '22 14:02 jamesagnew

The thing I was suggesting is tacking the ; preferred bit on at the end, as an indication that this is what the server wants. At least to me this feels to be in line with how content negotiation works in the Accept header.

By sending "Accept-Query" the server already can signal that it supports QUERY; so I don't think that overloading the media type is helpful here.

reschke avatar Feb 01 '22 15:02 reschke

Sure - What I'm suggesting is that to me at least, it would be nice for the server to be able to indicate that not only is this supported, but it's preferred. I don't see those two declarations as equivalent.

jamesagnew avatar Feb 01 '22 16:02 jamesagnew

What would, say, Accept-Query: text/plain; preferred mean? Is there actually an equivalence between GET and QUERY + application/x-www-form-urlencoded defined in the draft? (I looked and didn't see any, but I may have missed it.)

If there isn't a general equivalence, only an application-specific one, and if the use case depends on your clients doing an application-specific OPTIONS check anyway, perhaps this signal would make more sense as an application-specific one. ("I speak version 2 of such-and-such HTTP-based API" or so, where version 2 uses QUERY over GET.)

davidben avatar Feb 01 '22 16:02 davidben

Interesting point. In my mind there is an implied equivalence between GET /endpoint?foo=bar and

QUERY /endpoint
Content-Type: application/x-www-form-urlencoded

foo=bar

It's kind of orthogonal to the initial request here, but is that desirable to the authors? I think it'd be good to spell out as a SHOULD at least.

To the more direct question, Accept-Query: text/plain; preferred just means that the server would prefer clients to send queries in "QUERY with text" format instead of "GET with URL params" format. It doesn't specify what that means, but then again it also doesn't specify what it means when it's not preferred.

jamesagnew avatar Feb 01 '22 18:02 jamesagnew

That's a good point. Even Accept-Query is only useful at a layer where you know about your HTTP-based API. In which case, it's a convenient way to signal application-specific QUERY-based APIs, provided they can be expressed as MIME types.

Though, if the whole scheme presupposes prior knowledge, for your application, maybe Accept-Query as-is suffices? It sounds like you already know you prefer QUERY. May as well just say that, when known available (via Accept-Query or whatever else), FHIR clients must use the QUERY-based API over the GET-based API.

(Separately, with my browser-TLS-person hat on, if you're concerned about network infrastructure logging URLs, might I suggest using HTTPS? 😉 )

davidben avatar Feb 01 '22 19:02 davidben

"Use HTTPS" was the first thing that came to mind for me, too. :)

I don't think a site-wide mechanism is workable or desirable; E.g., a single resource sending a header that flips all GETs into QUERYs might have disastrous unintended effects in a variety of situations. Something more granular is required.

The most well-worn path is giving the client information that it can act upon to create the query; e.g., a HTML form. That has a number of advantages, and my initial inclination is to let solutions develop in that space before we look to create a hammer like this.

mnot avatar Feb 02 '22 05:02 mnot

"Use HTTPS" was the first thing that came to mind for me, too. :)

Agreed, but that still leaves bookmarks/logfiles etc as concern.

reschke avatar Feb 02 '22 09:02 reschke

Certainly no disagreement on the need to use HTTPS everywhere.

Often the requirements I hear about for "no PII in URLs" come from organizational policies, and in at least one case a national regulatory directive - these are the kinds of folks that often come to us with complaints about GET syntax.

One argument I've heard that does resonate is that even with "HTTPS everywhere" policies, things like access logs are problematic wherever you're terminating your TLS. Access logs of course often contain the full URL but rarely contain the request body, so anything you can do to discourage PII in the URL is beneficial to people with these concerns.

jamesagnew avatar Feb 02 '22 15:02 jamesagnew