Commit a2f36703 authored by Stefan Eissing's avatar Stefan Eissing
Browse files

Merge of r1767936,1768160,1769192,1769550 from trunk:

mod_http2: new directive 'H2PushResource' to enable early pushes before 
     processing of the main request starts. Resources are announced to the 
     client in Link headers on a 103 early hint response. 
     All responses with status code <400 are inspected for Link header and
     trigger pushes accordingly. 304 still does prevent pushes.
     'H2PushResource' can mark resources as 'critical' which gives them higher
     priority than the main resource. This leads to preferred scheduling for
     processing and, when content is available, will send it first. 'critical'
     is also recognized on Link headers.
     
mod_proxy_http2: uris in Link headers are now mapped back to a suitable
     local url when available. Relative uris with an absolute path are mapped
     as well. This makes reverse proxy mapping available for resources
     announced in this header. 
     With 103 interim responses being forwarded to the main client connection,
     this effectively allows early pushing of resources by a reverse proxied
     backend server.
     adding support for newly proposed 103 status code.



git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1769595 13f79535-47bb-0310-9956-ffa450edef68
parent 0fd6f16a
Loading
Loading
Loading
Loading
+21 −0
Original line number Diff line number Diff line
@@ -2,6 +2,27 @@

Changes with Apache 2.4.24

  *) mod_http2: new directive 'H2PushResource' to enable early pushes before 
     processing of the main request starts. Resources are announced to the 
     client in Link headers on a 103 early hint response. 
     All responses with status code <400 are inspected for Link header and
     trigger pushes accordingly. 304 still does prevent pushes.
     'H2PushResource' can mark resources as 'critical' which gives them higher
     priority than the main resource. This leads to preferred scheduling for
     processing and, when content is available, will send it first. 'critical'
     is also recognized on Link headers. [Stefan Eissing]
     
  *) mod_proxy_http2: uris in Link headers are now mapped back to a suitable
     local url when available. Relative uris with an absolute path are mapped
     as well. This makes reverse proxy mapping available for resources
     announced in this header. 
     With 103 interim responses being forwarded to the main client connection,
     this effectively allows early pushing of resources by a reverse proxied
     backend server. [Stefan Eissing]
     
  *) mod_proxy_http2: adding support for newly proposed 103 status code.
     [Stefan Eissing]
     
  *) mpm_unix: Apache fails to start if previously crashed then restarted with
     the same PID (e.g. in container).  PR 60261.
     [Val <valentin.bremond gmail.com>, Yann Ylavic]
+38 −0
Original line number Diff line number Diff line
@@ -933,5 +933,43 @@ H2TLSCoolDownSecs 0
        </usage>
    </directivesynopsis>
    
    <directivesynopsis>
        <name>H2PushResource</name>
        <description>Declares resources for early pushing to the client</description>
        <syntax>H2PushResource [add] path [critical]</syntax>
        <contextlist>
            <context>server config</context>
            <context>virtual host</context>
            <context>directory</context>
            <context>.htaccess</context>
        </contextlist>
        <compatibility>Available in version 2.4.24 and later.</compatibility>
        
        <usage>
            <p>
                When added to a directory/location HTTP/2 PUSHes will be attempted
                for all paths added via this directive. This directive can be used
                several times for the same location.
            </p>
            <p>
                This directive pushes resources much earlier than adding 
                <code>Link</code> headers via <module>mod_headers</module>.
                <module>mod_http2</module> announces these resources in a
                <code>103 Early Hints</code> interim response to the client.
                That means that clients not supporting PUSH will still get
                early preload hints.
            </p>
            <p>
                In contrast to setting <code>Link</code> response headers 
                via <module>mod_headers</module>, this directive will only
                take effect on HTTP/2 connections. 
            </p>
            <p>
                By adding <code>critical</code> to such a resource, the server
                will give processing it more preference and send its data, once
                available, before the data from the main request.
            </p>
        </usage>
    </directivesynopsis>
    
</modulesynopsis>
+1 −2
Original line number Diff line number Diff line
@@ -776,8 +776,7 @@ static void fixup_vary(request_rec *r)
     * its comma-separated fieldname values, and then add them to varies
     * if not already present in the array.
     */
    apr_table_do((int (*)(void *, const char *, const char *))uniq_field_values,
                 (void *) varies, r->headers_out, "Vary", NULL);
    apr_table_do(uniq_field_values, varies, r->headers_out, "Vary", NULL);

    /* If we found any, replace old Vary fields with unique-ified value */

+0 −2
Original line number Diff line number Diff line
@@ -55,8 +55,6 @@ extern const char *H2_MAGIC_TOKEN;
/* Initial default window size, RFC 7540 ch. 6.5.2 */
#define H2_INITIAL_WINDOW_SIZE      ((64*1024)-1)

#define H2_HTTP_2XX(a)      ((a) >= 200 && (a) < 300)

#define H2_STREAM_CLIENT_INITIATED(id)      (id&0x01)

#define H2_ALEN(a)          (sizeof(a)/sizeof((a)[0]))
+74 −6
Original line number Diff line number Diff line
@@ -73,7 +73,6 @@ static void *h2_config_create(apr_pool_t *pool,
                              const char *prefix, const char *x)
{
    h2_config *conf = (h2_config *)apr_pcalloc(pool, sizeof(h2_config));
    
    const char *s = x? x : "unknown";
    char *name = apr_pstrcat(pool, prefix, "[", s, "]", NULL);
    
@@ -96,7 +95,7 @@ static void *h2_config_create(apr_pool_t *pool,
    conf->priorities           = NULL;
    conf->push_diary_size      = DEF_VAL;
    conf->copy_files           = DEF_VAL;
    
    conf->push_list            = NULL;
    return conf;
}

@@ -110,12 +109,11 @@ void *h2_config_create_dir(apr_pool_t *pool, char *x)
    return h2_config_create(pool, "dir", x);
}

void *h2_config_merge(apr_pool_t *pool, void *basev, void *addv)
static void *h2_config_merge(apr_pool_t *pool, void *basev, void *addv)
{
    h2_config *base = (h2_config *)basev;
    h2_config *add = (h2_config *)addv;
    h2_config *n = (h2_config *)apr_pcalloc(pool, sizeof(h2_config));

    char *name = apr_pstrcat(pool, "merged[", add->name, ", ", base->name, "]", NULL);
    n->name = name;

@@ -143,10 +141,25 @@ void *h2_config_merge(apr_pool_t *pool, void *basev, void *addv)
    }
    n->push_diary_size      = H2_CONFIG_GET(add, base, push_diary_size);
    n->copy_files           = H2_CONFIG_GET(add, base, copy_files);
    
    if (add->push_list && base->push_list) {
        n->push_list        = apr_array_append(pool, base->push_list, add->push_list);
    }
    else {
        n->push_list        = add->push_list? add->push_list : base->push_list;
    }
    return n;
}

void *h2_config_merge_dir(apr_pool_t *pool, void *basev, void *addv)
{
    return h2_config_merge(pool, basev, addv);
}

void *h2_config_merge_svr(apr_pool_t *pool, void *basev, void *addv)
{
    return h2_config_merge(pool, basev, addv);
}

int h2_config_geti(const h2_config *conf, h2_config_var_t var)
{
    return (int)h2_config_geti64(conf, var);
@@ -521,6 +534,59 @@ static const char *h2_conf_set_copy_files(cmd_parms *parms,
    return "value must be On or Off";
}

static void add_push(apr_pool_t *pool, h2_config *conf, h2_push_res *push)
{
    h2_push_res *new;
    if (!conf->push_list) {
        conf->push_list = apr_array_make(pool, 10, sizeof(*push));
    }
    new = apr_array_push(conf->push_list);
    new->uri_ref = push->uri_ref;
    new->critical = push->critical;
}

static const char *h2_conf_add_push_res(cmd_parms *cmd, void *dirconf,
                                        const char *arg1, const char *arg2,
                                        const char *arg3)
{
    h2_config *dconf = (h2_config*)dirconf ;
    h2_config *sconf = (h2_config*)h2_config_sget(cmd->server);
    h2_push_res push;
    const char *last = arg3;
    
    memset(&push, 0, sizeof(push));
    if (!strcasecmp("add", arg1)) {
        push.uri_ref = arg2;
    }
    else {
        push.uri_ref = arg1;
        last = arg2;
        if (arg3) {
            return "too many parameter";
        }
    }
    
    if (last) {
        if (!strcasecmp("critical", last)) {
            push.critical = 1;
        }
        else {
            return "unknown last parameter";
        }
    }

    /* server command? set both */
    if (cmd->path == NULL) {
        add_push(cmd->pool, sconf, &push);
        add_push(cmd->pool, dconf, &push);
    }
    else {
        add_push(cmd->pool, dconf, &push);
    }

    return NULL;
}

#define AP_END_CMD     AP_INIT_TAKE1(NULL, NULL, NULL, RSRC_CONF, NULL)

const command_rec h2_cmds[] = {
@@ -561,7 +627,9 @@ const command_rec h2_cmds[] = {
    AP_INIT_TAKE1("H2PushDiarySize", h2_conf_set_push_diary_size, NULL,
                  RSRC_CONF, "size of push diary"),
    AP_INIT_TAKE1("H2CopyFiles", h2_conf_set_copy_files, NULL,
                  OR_ALL, "on to perform copy of file data"),
                  OR_FILEINFO, "on to perform copy of file data"),
    AP_INIT_TAKE123("H2PushResource", h2_conf_add_push_res, NULL,
                   OR_FILEINFO, "add a resource to be pushed in this location/on this server."),
    AP_END_CMD
};

Loading