Server Push and Status Codes

Mark Nottingham <> Wed, 24 August 2016 04:30 UTC

Return-Path: <>
Received: from localhost (localhost []) by (Postfix) with ESMTP id B972412D0A4 for <>; Tue, 23 Aug 2016 21:30:27 -0700 (PDT)
X-Virus-Scanned: amavisd-new at
X-Spam-Flag: NO
X-Spam-Score: -7.469
X-Spam-Status: No, score=-7.469 tagged_above=-999 required=5 tests=[BAYES_00=-1.9, HEADER_FROM_DIFFERENT_DOMAINS=0.001, RCVD_IN_DNSWL_HI=-5, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, RP_MATCHES_RCVD=-0.548, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001] autolearn=ham autolearn_force=no
Received: from ([]) by localhost ( []) (amavisd-new, port 10024) with ESMTP id ukpvsq3MFLmV for <>; Tue, 23 Aug 2016 21:30:25 -0700 (PDT)
Received: from ( []) (using TLSv1.2 with cipher DHE-RSA-AES128-SHA (128/128 bits)) (No client certificate requested) by (Postfix) with ESMTPS id 0EE4412D0D8 for <>; Tue, 23 Aug 2016 21:30:24 -0700 (PDT)
Received: from lists by with local (Exim 4.80) (envelope-from <>) id 1bcPmo-0003bV-IN for; Wed, 24 Aug 2016 04:27:34 +0000
Resent-Date: Wed, 24 Aug 2016 04:27:34 +0000
Resent-Message-Id: <>
Received: from ([]) by with esmtps (TLS1.2:DHE_RSA_AES_128_CBC_SHA1:128) (Exim 4.80) (envelope-from <>) id 1bcPmZ-0003Zl-15 for; Wed, 24 Aug 2016 04:27:19 +0000
Received: from ([]) by with esmtps (TLS1.2:DHE_RSA_AES_256_CBC_SHA256:256) (Exim 4.80) (envelope-from <>) id 1bcPmW-0006T7-VW for; Wed, 24 Aug 2016 04:27:18 +0000
Received: from [] (unknown []) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by (Postfix) with ESMTPSA id 618A722E256 for <>; Wed, 24 Aug 2016 00:26:39 -0400 (EDT)
From: Mark Nottingham <>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: quoted-printable
Message-Id: <>
Date: Wed, 24 Aug 2016 14:26:38 +1000
To: HTTP Working Group <>
Mime-Version: 1.0 (Mac OS X Mail 9.3 \(3124\))
X-Mailer: Apple Mail (2.3124)
Received-SPF: pass client-ip=;;
X-W3C-Hub-Spam-Status: No, score=-8.4
X-W3C-Hub-Spam-Report: AWL=1.201, BAYES_00=-1.9, RCVD_IN_DNSWL_LOW=-0.7, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001, W3C_AA=-1, W3C_DB=-1, W3C_IRA=-1, W3C_IRR=-3, W3C_WL=-1
X-W3C-Scan-Sig: 1bcPmW-0006T7-VW 1fae3f5154198a06c8fcb346afb86bc4
Subject: Server Push and Status Codes
Archived-At: <>
X-Mailing-List: <> archive/latest/32340
Precedence: list
List-Id: <>
List-Help: <>
List-Post: <>
List-Unsubscribe: <>

In principle, any HTTP status code can be pushed in a response. Success (2xx), redirection (300, 301, 302, 303, 307, 308) and eror (4xx and 5xx) status codes all have the same caching semantics (as long as you pay attention to rules like those for heuristics), described in RFC7234.

This implies that if they are pushed to the client, any of these status codes should behave as if the client had requested them previously and stored the response. For example, a 403 (Forbidden) can be pushed and stored just as a 200 (OK) -- even if this would be of very limited use.

That said, a few things to consider:

* 304 (Not Modified) has special interaction with caches and validation; I'll cover that separately.

* Other 3xx Redirection codes indicate, when pushed, that if the client were to make that request, it will be redirected. That does not mean that the `Location` header's URL should be followed immediately; it is only upon an actual request from the client that it should be acted upon. In other words, 3xx redirects SHOULD be cached just like anything else (i.e., if the headers allow it), and used if the client makes a request to the URL.

* 1xx Informational codes don't make much sense as a Push payload, because the headers they convey are lost in most implementations (to be subsumed by the headers in the final response). For example, the headers on a 100 (Continue) response are a no-op; effectively, it's a one-bit "go ahead" signal. Since HTTP/2 already has protocol-level signalling mechanisms, it's probably best to say that 1xx responses SHOULD NOT be sent in Server Push, and MUST be ignored when received.

* 401 (Unauthorized) has the side effect of prompting the user for their credentials. Again, this does not mean that the User Agent ought to do so when receiving a pushed 401; rather, this could be seen as a mechanism to avoid the round trip that would otherwise be required -- just as in other intended uses of Server Push. Presumably, the PUSH_PROMISE for such a request would omit the `Authentication` header field.

* 407 (Proxy Authenticate) is probably best not to push, since it's confusing authority of the network vs. the origin. Clients SHOULD ignore such pushes.

* Many other 4xx and 5xx status codes don't have any practical use in Server Push; e.g., 405 (Method Not Allowed), 408 (Request Timeout), 411 (Length Required) and 414 (URI Too Long) are all reactions to problems with the request. Since the server has sent that request, their use is somewhat self-defeating; however, this does not mean that a client encountering them should generate an error, or fail to use the response. At the very least, if the response is available in devtools, debugging will be easier; additionally, someone might find a creative, appropriate use for them some day.

Does this approach make sense?

Mark Nottingham