Subject: trailers and pseudo-headers

From: Julian Reschke <[email-masked]>
Date: Wed, 02 Jul 2014 08:26:57 +0200

Hi there,

should we say something about the case where a HEADERS frame containing 
trailing header fields contains pseudo-headers such as ":status"?

Allowed? Forbidden? Bad idea?

Best regards, Julian

---

From: Mark Nottingham <[email-masked]>
Date: Wed, 2 Jul 2014 16:49:20 +1000

On 2 Jul 2014, at 4:26 pm, Julian Reschke <[email-masked]> wrote:

> Hi there,
> 
> should we say something about the case where a HEADERS frame containing trailing header fields contains pseudo-headers such as ":status"?
> 

My .02 - probably, although <http://httpwg.github.io/specs/rfc7230.html#chunked.trailer.part> says:

> A sender must not generate a trailer that contains a field necessary for message framing (e.g., Transfer-Encoding and Content-Length), routing (e.g., Host), request modifiers (e.g., controls and conditionals in Section 5 of [RFC7231]), authentication (e.g., see [RFC7235]and [RFC6265]), response control data (e.g., see Section 7.1 of [RFC7231]), or determining how to process the payload (e.g., Content-Encoding, Content-Type, Content-Range, and Trailer).

... which kind of already goes there. Maybe just note that they fall under that requirement?

--
Mark Nottingham   https://www.mnot.net/

---

From: Julian Reschke <[email-masked]>
Date: Wed, 02 Jul 2014 08:56:58 +0200

> ... which kind of already goes there. Maybe just note that they fall under that requirement?

Si.

The reason I ask is that people might start putting ":status" into a 
trailer and expect that to have an effect (it would be nice to have that 
feature, but it wouldn't map to 1.1...).

Best regards, Julian

---

From: "Poul-Henning Kamp" <[email-masked]>
Date: Wed, 02 Jul 2014 07:35:40 +0000

>feature, but it wouldn't map to 1.1...).

It would also be pretty pointless:  It would just shift the buffering
responsibility from the server to the client.

-- 
Poul-Henning Kamp       | UNIX since Zilog Zeus 3.20
[email-masked]         | TCP/IP since RFC 956
FreeBSD committer       | BSD since 4.3-tahoe    
Never attribute to malice what can adequately be explained by incompetence.

---

From: Julian Reschke <[email-masked]>
Date: Wed, 02 Jul 2014 09:43:49 +0200

> responsibility from the server to the client.

What I meant is: an *additional* :status (such as in first claiming 
everything is ok -- 200, then start streaming and failing, and then send 
a 500 in the trailers).

Best regards, Julian

---

From: "Poul-Henning Kamp" <[email-masked]>
Date: Wed, 02 Jul 2014 08:02:55 +0000

>everything is ok -- 200, then start streaming and failing, and then send 

And if that is a risk, the client can do only one thing:  Buffer the
response, until it is sure what the :status will be.

---

From: Julian Reschke <[email-masked]>
Date: Wed, 02 Jul 2014 10:14:01 +0200

> response, until it is sure what the :status will be.

Hm? That would imply buffering all responses before displaying them?

---

From: "Poul-Henning Kamp" <[email-masked]>
Date: Wed, 02 Jul 2014 08:17:59 +0000

>Hm? That would imply buffering all responses before displaying them?

Exactly...  :status must be final and definitive before the client
can decide how to present or process the body.

---

From: "Eric J. Bowman" <[email-masked]>
Date: Wed, 2 Jul 2014 03:46:11 -0600

> can decide how to present or process the body.

I'm not sure how to interpret your position here PHK, but this would be
a major step backwards for the Web.

-Eric

---

From: "Poul-Henning Kamp" <[email-masked]>
Date: Wed, 02 Jul 2014 09:56:24 +0000

>a major step backwards for the Web.

My position is that :status can *never* go into trailers (which I think
should be unsupported btw.)

HTTP/1 has always worked this way:  The first thing the server tells
you is the status code, and there is no way it can change that
subsequently:  Once you've seen 200, 301, 404 or 502, you know what
use the object body can be to you and dispatch accordingly.

---

From: Mark Nottingham <[email-masked]>
Date: Wed, 2 Jul 2014 19:58:43 +1000

Personally - very strong +1. This is fundamental. Yes, it sucks, but it’s how HTTP works, and we can’t change it here.

--
Mark Nottingham   http://www.mnot.net/

---

From: Alvaro Lopez Ortega <[email-masked]>
Date: Wed, 2 Jul 2014 12:05:47 +0200

> should be unsupported btw.)

It does make good sense. Actually, I cannot think of a better approach that
wouldn't imply the whole response.

All the best,
Alvaro

---

From: Julian Reschke <[email-masked]>
Date: Wed, 02 Jul 2014 12:12:33 +0200

On 2014-07-02 11:58, Mark Nottingham wrote:
> ...

I agree.

The reason why I raised this is that in HTTP/1.1, the HTTP status isn't 
a header field, so the issue doesn't come up. In HTTP/2, it's a pseudo 
header field, so it *could* appear in trailers, and thus people might be 
tempted to take advantage of it.

Best regards, Julian

---

From: "Poul-Henning Kamp" <[email-masked]>
Date: Wed, 02 Jul 2014 10:22:37 +0000

>tempted to take advantage of it.

I think the best way to handle this textually, is to explain that :header
are not really headers, but a sleigh of hand HTTP/2 uses to transmit
the non-header protocol fields, and that this does not change the
semantics of those fields in any way.

---

From: Michael Sweet <[email-masked]>
Date: Wed, 02 Jul 2014 07:12:41 -0400

Julian,

On Jul 2, 2014, at 3:43 AM, Julian Reschke <[email-masked]> wrote:
> What I meant is: an *additional* :status (such as in first claiming everything is ok -- 200, then start streaming and failing, and then send a 500 in the trailers).

As you've noted, you can't do that in HTTP/1.1, and in fact this would be a case where I would emit 100 (continue) to the client to let them know they can continue sending data, then follow up with a final status code (200, 500, whatever) once I'd processed the message body and any trailers in the request.

_________________________________________________________
Michael Sweet, Senior Printing System Engineer, PWG Chair

---

From: Julian Reschke <[email-masked]>
Date: Wed, 02 Jul 2014 14:04:29 +0200

> As you've noted, you can't do that in HTTP/1.1, and in fact this would be a case where I would emit 100 (continue) to the client to let them know they can continue sending data, then follow up with…

When I said "streaming" I was referring to the process of sending the 
payload in the response.

There are many cases where a server would say "200", and then start a 
complicated process that might fail half-way. In HTTP/1.1, signalling an 
error in this situation is hard (abort the chunked transfer or close the 
connection). It would be good if HTTP/2 can do better here.

Best regards, Julian

---

From: "Poul-Henning Kamp" <[email-masked]>
Date: Wed, 02 Jul 2014 12:09:26 +0000

>connection). It would be good if HTTP/2 can do better here.

I thought that was what RST_STREAM was for ?

---

From: Julian Reschke <[email-masked]>
Date: Wed, 02 Jul 2014 14:25:12 +0200

> I thought that was what RST_STREAM was for ?

Well, yes, we can say "something went wrong", but that's all.

Best regards, Julian

---

From: Willy Tarreau <[email-masked]>
Date: Wed, 2 Jul 2014 14:25:22 +0200

> semantics of those fields in any way.

Explaining does not solve everything. It's very clear that content-length
may only appear once, still we've had to deal with the multiple C-L case
due to bogus application servers or intermediaries and even indicate in
the spec how to process them :-/

I think here we should take the first steps and write an explicit "MUST NOT
be sent" and a "SHOULD reset the stream if received" in the spec so that
everyone acts correctly and people cannot develop such crap without noticing.

Willy

---

From: <[email-masked]>
Date: Wed, 2 Jul 2014 13:34:24 +0000

>>>complicated process that might fail half-way. In HTTP/1.1, signalling

>>>an error in this situation is hard (abort the chunked transfer or close

>>>the connection). It would be good if HTTP/2 can do better here.

I agree.

> Well, yes, we can say "something went wrong", but that's all.

Technically you can "say" 12 different "wrongs" with the error codes [1] (and one "no wrong").

Why not have an optional error message like the "additional debug data" in GOAWAY?

e.g.

  0                   1                   2                   3

  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

|                        Error Code (32)                        |

+---------------------------------------------------------------+

|                  Additional Error Data (*)                    |

+---------------------------------------------------------------+

[1] http://http2.github.io/http2-spec/#ErrorCodes

This email message is intended only for the use of the named recipient. Information contained in this email message and its attachments may be privileged, confidential and protected from disclosure. If you are not the intended recipient, please do not read, copy, use or disclose this communication to others. Also please notify the sender by replying to this message and then delete it from your system.

---

From: Martin Thomson <[email-masked]>
Date: Wed, 2 Jul 2014 10:23:56 -0700

> Allowed? Forbidden? Bad idea?

I've added a commit to the PR that I created that deals with
pseudo-headers.  This forbids their use under the same conditions as
other malformed headers.  That is, that they should be treated as a
stream header, but notes that tunnels and other intermediaries might
not even need to check, so aren't required to.  This point is
especially relevant for trailers and other HEADERS frames, which -
unless we decide to remove them (see other issue regarding
END_SEGMENT) - will be ignored by pretty much everyone.