Re: [#153] PUSH_PROMISE headers

James M Snell <jasnell@gmail.com> Sat, 29 June 2013 04:46 UTC

Return-Path: <ietf-http-wg-request@listhub.w3.org>
X-Original-To: ietfarch-httpbisa-archive-bis2Juki@ietfa.amsl.com
Delivered-To: ietfarch-httpbisa-archive-bis2Juki@ietfa.amsl.com
Received: from localhost (localhost [127.0.0.1]) by ietfa.amsl.com (Postfix) with ESMTP id 0DFEC21F9DC9 for <ietfarch-httpbisa-archive-bis2Juki@ietfa.amsl.com>; Fri, 28 Jun 2013 21:46:11 -0700 (PDT)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: -10.599
X-Spam-Level:
X-Spam-Status: No, score=-10.599 tagged_above=-999 required=5 tests=[AWL=0.000, BAYES_00=-2.599, RCVD_IN_DNSWL_HI=-8]
Received: from mail.ietf.org ([12.22.58.30]) by localhost (ietfa.amsl.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id x0i2UdWyE03K for <ietfarch-httpbisa-archive-bis2Juki@ietfa.amsl.com>; Fri, 28 Jun 2013 21:46:05 -0700 (PDT)
Received: from frink.w3.org (frink.w3.org [128.30.52.56]) by ietfa.amsl.com (Postfix) with ESMTP id A446B21F9E52 for <httpbisa-archive-bis2Juki@lists.ietf.org>; Fri, 28 Jun 2013 21:46:05 -0700 (PDT)
Received: from lists by frink.w3.org with local (Exim 4.72) (envelope-from <ietf-http-wg-request@listhub.w3.org>) id 1Usn2H-0007dk-ES for ietf-http-wg-dist@listhub.w3.org; Sat, 29 Jun 2013 04:45:21 +0000
Resent-Date: Sat, 29 Jun 2013 04:45:21 +0000
Resent-Message-Id: <E1Usn2H-0007dk-ES@frink.w3.org>
Received: from maggie.w3.org ([128.30.52.39]) by frink.w3.org with esmtp (Exim 4.72) (envelope-from <jasnell@gmail.com>) id 1Usn21-0007cj-59 for ietf-http-wg@listhub.w3.org; Sat, 29 Jun 2013 04:45:05 +0000
Received: from mail-oa0-f41.google.com ([209.85.219.41]) by maggie.w3.org with esmtps (TLS1.0:RSA_ARCFOUR_SHA1:16) (Exim 4.72) (envelope-from <jasnell@gmail.com>) id 1Usn1z-0007h8-ML for ietf-http-wg@w3.org; Sat, 29 Jun 2013 04:45:04 +0000
Received: by mail-oa0-f41.google.com with SMTP id n10so3117336oag.28 for <ietf-http-wg@w3.org>; Fri, 28 Jun 2013 21:44:37 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :cc:content-type; bh=uhwm00yC1SQwnLpCMV+yQ7+7O9COpXR4D2UgnGZV9Z4=; b=Y0NEQvDTiZ1AjYZcPrUe4LVybVQ09tobeWgRJkV7XuYzVeBAvWrbscJY8p75GZ/vQ3 nX8sjphIppDkgCmNOeObcjGY8f+JE5Tloc3kDLkbP09AUgQmhAaR+HZqhymBLYwpj32G 6Xlf2Xccq+zifQKm4qPPx55YJ9gSZr+gEsDOedgjO5oFK+NOn1biVjbA2ztQGCzjiRnD vigcD02FUEztMLFp0oJ0BPVdUxaL9lKZJtryydCMTNEVmbMkrib8ubcN30NwQFxYWAog bfRsMxxFuakhNBzZZDsatVEjH0pDUFUkBkpI7q6I2R7L9/N0aGt2O8oYCZi9PhXfHGmo o7uQ==
X-Received: by 10.60.125.100 with SMTP id mp4mr733388oeb.60.1372481077812; Fri, 28 Jun 2013 21:44:37 -0700 (PDT)
MIME-Version: 1.0
Received: by 10.60.55.8 with HTTP; Fri, 28 Jun 2013 21:44:17 -0700 (PDT)
In-Reply-To: <CABkgnnVGh9dLkfDrO2fq5TsnxwEu0Dff=LqJEJR5Odq2ibfDMg@mail.gmail.com>
References: <CABkgnnVGh9dLkfDrO2fq5TsnxwEu0Dff=LqJEJR5Odq2ibfDMg@mail.gmail.com>
From: James M Snell <jasnell@gmail.com>
Date: Fri, 28 Jun 2013 21:44:17 -0700
Message-ID: <CABP7RbcoSSSKJq3YbZ2ypw-xb0uOgFQcjcQP9tJdkgEjPfJVMA@mail.gmail.com>
To: Martin Thomson <martin.thomson@gmail.com>
Cc: HTTP Working Group <ietf-http-wg@w3.org>
Content-Type: text/plain; charset="UTF-8"
Received-SPF: pass client-ip=209.85.219.41; envelope-from=jasnell@gmail.com; helo=mail-oa0-f41.google.com
X-W3C-Hub-Spam-Status: No, score=-3.5
X-W3C-Hub-Spam-Report: AWL=-2.696, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_LOW=-0.7, SPF_PASS=-0.001
X-W3C-Scan-Sig: maggie.w3.org 1Usn1z-0007h8-ML 0ae44c9423dbf9eb3a17924e11565237
X-Original-To: ietf-http-wg@w3.org
Subject: Re: [#153] PUSH_PROMISE headers
Archived-At: <http://www.w3.org/mid/CABP7RbcoSSSKJq3YbZ2ypw-xb0uOgFQcjcQP9tJdkgEjPfJVMA@mail.gmail.com>
Resent-From: ietf-http-wg@w3.org
X-Mailing-List: <ietf-http-wg@w3.org> archive/latest/18405
X-Loop: ietf-http-wg@w3.org
Resent-Sender: ietf-http-wg-request@w3.org
Precedence: list
List-Id: <ietf-http-wg.w3.org>
List-Help: <http://www.w3.org/Mail/>
List-Post: <mailto:ietf-http-wg@w3.org>
List-Unsubscribe: <mailto:ietf-http-wg-request@w3.org?subject=unsubscribe>

Let's take a step back and consider what a pushed stream is...

A pushed stream is essentially an "Implied GET". This means that a
server is going to assume that the client was going to send a GET for
the pushed resource. This also means that the server has to make some
assumptions about the make up of that implied GET.

Now, consider how HTTP caching works. When a cache receives a request
for a resource, how does it determine whether or not it has a
representation of the resource already available? Does it look at the
request headers or the response headers? Obviously, it looks at the
request headers. It uses the response headers when populating the
cache.

So, if we look at the pushed resource sent by the server, what we need
is for A) the server to first let us know about the implied GET
request.. which means pushing down a set of request headers then B)
the server to send the actual resource, which means pushing down the
response headers.

Already in our design for pushed resources, we have the server sending
a PUSH_PROMISE frame that contains a header block, followed by a
HEADERS frame that also contains a headers block. It stands to reason
that the PUSH_PROMISE frame would contain the set of request headers
that the server is assuming for the implied GET. These are delivered
to the client, which uses those to determine whether or not a cached
representation of the resource is already available (just as any cache
would do using the request headers). The server would then send it's
response headers in a HEADERS frame, just as it would any response to
any other kind of GET.

Two examples to show how this naturally fits... First, let's look at a
normal GET request sent by the client to the server...

Client                 Server
------                 ------
  |                        |
  | ---------------------> |
  |   HEADERS              |
  |     GET                |
  |     /images/f.jpg      |
  |     If-Match: etag1    |
  |     Accept: image/jpeg |
  |                        |
  | <--------------------- |
  |   HEADERS              |
  |     200                |
  |     Content-Type:      |
  |       image/jpeg       |
  |     Content-Length:    |
  |       123              |
  |                        |
  | <--------------------- |
  |   DATA....DATA....     |
  |                        |

Now consider the same resource being pushed by the server using PUSH_PROMISE...

Client                 Server
------                 ------
  |                        |
  | <--------------------- |
  |   PUSH_PROMISE         |
  |     GET                |
  |     /images/f.jpg      |
  |     If-Match: etag1    |
  |     Accept: image/jpeg |
  |                        |
  | <--------------------- |
  |   HEADERS              |
  |     200                |
  |     Content-Type:      |
  |       image/jpeg       |
  |     Content-Length:    |
  |       123              |
  |                        |
  | <--------------------- |
  |   DATA....DATA....     |
  |                        |


Note that the only difference here is the direction and type of the
first frame. Everything else is identical. The PUSH_PROMISE contains
everything the client needs to determine whether or not it already has
the resource in it's local cache (request URI, etag, content-type...).

There's no need to get any more complicated than this. We already
require two distinct header blocks for every request. We already send
two distinct header blocks for each pushed stream. We already indicate
that a pushed stream is an implied GET. To make it work, we simply
state that the PUSH_PROMISE contains the Request headers that the
server has assumed for the implied GET request, while the HEADERS
frame sent later contains the Response headers. If the request headers
in the PUSH_PROMISE end up not being adequate enough to properly
determine if the resource is already cached, then we treat it as just
another cache miss.

On Fri, Jun 28, 2013 at 5:21 PM, Martin Thomson
<martin.thomson@gmail.com> wrote:
> https://github.com/http2/http2-spec/issues/153
>
> The current text describes PUSH_PROMISE as having a few request
> headers, plus some response headers, but it's quite vague.
>
> I think that if this is going to be properly workable across a wide
> range of uses with lots of different headers, PUSH_PROMISE needs to
> include two sets of headers: the ones that it overrides from the
> associated request (:path being foremost of those) and the ones that
> it provides as a "preview" of the response (e.g., ETag might allow
> caches to determine if they were interested in the rest of the
> response).
>