On Fri, Jul 24, 2015 at 2:09 PM,  <ic...@apache.org> wrote:
> Author: icing
> Date: Fri Jul 24 12:09:44 2015
> New Revision: 1692486
>
> URL: http://svn.apache.org/r1692486
> Log:
> new Protocols directive and core API changes to enable protocol switching on 
> HTTP Upgrade or ALPN, implemented in mod_ssl and mod_h2
>
[]
> Modified:
[]
>     httpd/httpd/trunk/server/core.c
[]
> ==============================================================================
> --- httpd/httpd/trunk/server/core.c (original)
> +++ httpd/httpd/trunk/server/core.c Fri Jul 24 12:09:44 2015
[]
> @@ -5226,6 +5253,73 @@ static void core_dump_config(apr_pool_t
[]
> +static int core_upgrade_handler(request_rec *r)
> +{
> +    conn_rec *c = r->connection;
> +    const char *upgrade = apr_table_get(r->headers_in, "Upgrade");
> +
> +    if (upgrade && *upgrade) {
> +        const char *conn = apr_table_get(r->headers_in, "Connection");
> +        if (ap_find_token(r->pool, conn, "upgrade")) {
> +            apr_array_header_t *offers = NULL;
> +            const char *err;
> +
> +            err = ap_parse_token_list_strict(r->pool, upgrade, &offers, 0);
> +            if (err) {
> +                ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02910)
> +                              "parsing Upgrade header: %s", err);
> +                return DECLINED;
> +            }
> +
> +            if (offers && offers->nelts > 0) {
> +                const char *protocol = ap_select_protocol(c, r, r->server,
> +                                                          offers);
> +                if (strcmp(protocol, ap_run_protocol_get(c))) {
> +                    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, 
> APLOGNO(02909)
> +                                  "Upgrade selects '%s'", protocol);
> +                    /* Let the client know what we are upgrading to. */
> +                    apr_table_clear(r->headers_out);
> +                    apr_table_setn(r->headers_out, "Upgrade", protocol);
> +                    apr_table_setn(r->headers_out, "Connection", "Upgrade");
> +
> +                    r->status = HTTP_SWITCHING_PROTOCOLS;
> +                    r->status_line = ap_get_status_line(r->status);
> +                    ap_send_interim_response(r, 1);
> +
> +                    ap_switch_protocol(c, r, r->server, protocol);
> +
> +                    /* make sure httpd closes the connection after this */
> +                    c->keepalive = AP_CONN_CLOSE;
> +                    ap_lingering_close(c);
> +
> +                    if (c->sbh) {
> +                        ap_update_child_status_from_conn(c->sbh,
> +                                                         SERVER_CLOSING, c);
> +                    }
> +
> +                    return DONE;
> +                }
> +            }
> +        }
> +    }
> +
> +    return DECLINED;
> +}
> +
> +static int core_upgrade_storage(request_rec *r)
> +{
> +    if ((r->method_number == M_OPTIONS) && r->uri && (r->uri[0] == '*') &&
> +        (r->uri[1] == '\0')) {
> +        return core_upgrade_handler(r);
> +    }
> +    return DECLINED;
> +}
> +
>  static void register_hooks(apr_pool_t *p)
>  {
>      errorlog_hash = apr_hash_make(p);
> @@ -5248,10 +5342,12 @@ static void register_hooks(apr_pool_t *p
[]
> +    
> ap_hook_map_to_storage(core_upgrade_storage,NULL,NULL,APR_HOOK_REALLY_FIRST);
[]
> +    ap_hook_handler(core_upgrade_handler,NULL,NULL,APR_HOOK_REALLY_FIRST);

I wonder how these handlers interact with mod_proxy_wstunnel which
needs to handle the Upgrade by itself (after the HTTP header has been
forwarded to the backend).

I'm not sure we can upgrade unconditionally really first in the chain.

Reply via email to