Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion include/h2o.h
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,10 @@ struct st_h2o_hostconf_t {
* if server push should be used
*/
unsigned push_preload : 1;
/**
* if cross origin pushes should be authorized
*/
unsigned allow_cross_origin_push : 1;
/**
* casper settings
*/
Expand Down Expand Up @@ -1306,7 +1310,7 @@ void h2o_extract_push_path_from_link_header(h2o_mem_pool_t *pool, const char *va
const h2o_url_scheme_t *input_scheme, h2o_iovec_t input_authority,
const h2o_url_scheme_t *base_scheme, h2o_iovec_t *base_authority,
void (*cb)(void *ctx, const char *path, size_t path_len, int is_critical), void *cb_ctx,
h2o_iovec_t *filtered_value);
h2o_iovec_t *filtered_value, int allow_cross_origin_push);
/**
* return a bitmap of compressible types, by parsing the `accept-encoding` header
*/
Expand Down
1 change: 1 addition & 0 deletions include/h2o/socket/uv-binding.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#define h2o__uv_binding_h

#include <uv.h>
#include <sys/time.h>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this an unrelated change?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is, but it's intentional, my system gets warnings because gettimeofday below isn't defined. I'm happy to submit the fix as a separate PR, if you prefer.


#if !(defined(UV_VERSION_MAJOR) && UV_VERSION_MAJOR == 1)
#error "libh2o (libuv binding) requires libuv version 1.x.y"
Expand Down
18 changes: 18 additions & 0 deletions lib/core/configurator.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ struct st_core_config_vars_t {
struct {
unsigned reprioritize_blocking_assets : 1;
unsigned push_preload : 1;
unsigned allow_cross_origin_push : 1;
h2o_casper_conf_t casper;
} http2;
struct {
Expand Down Expand Up @@ -84,6 +85,7 @@ static int on_core_exit(h2o_configurator_t *_self, h2o_configurator_context_t *c
/* exitting from host-level configuration */
ctx->hostconf->http2.reprioritize_blocking_assets = self->vars->http2.reprioritize_blocking_assets;
ctx->hostconf->http2.push_preload = self->vars->http2.push_preload;
ctx->hostconf->http2.allow_cross_origin_push = self->vars->http2.allow_cross_origin_push;
ctx->hostconf->http2.casper = self->vars->http2.casper;
} else if (ctx->pathconf != NULL) {
/* exitting from path or extension-level configuration */
Expand Down Expand Up @@ -501,6 +503,18 @@ static int on_config_http2_push_preload(h2o_configurator_command_t *cmd, h2o_con
return 0;
}

static int on_config_http2_allow_cross_origin_push(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
{
struct st_core_configurator_t *self = (void *)cmd->configurator;
ssize_t on;

if ((on = h2o_configurator_get_one_of(cmd, node, "OFF,ON")) == -1)
return -1;
self->vars->http2.allow_cross_origin_push = (int)on;

return 0;
}

static int on_config_http2_casper(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
{
static const h2o_casper_conf_t defaults = {
Expand Down Expand Up @@ -964,6 +978,10 @@ void h2o_configurator__init_core(h2o_globalconf_t *conf)
H2O_CONFIGURATOR_FLAG_GLOBAL | H2O_CONFIGURATOR_FLAG_HOST |
H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
on_config_http2_push_preload);
h2o_configurator_define_command(&c->super, "http2-allow-cross-origin-push",
H2O_CONFIGURATOR_FLAG_GLOBAL | H2O_CONFIGURATOR_FLAG_PATH |
H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
on_config_http2_allow_cross_origin_push);
h2o_configurator_define_command(&c->super, "http2-casper", H2O_CONFIGURATOR_FLAG_GLOBAL | H2O_CONFIGURATOR_FLAG_HOST,
on_config_http2_casper);
h2o_configurator_define_command(&c->super, "file.mime.settypes",
Expand Down
3 changes: 2 additions & 1 deletion lib/core/request.c
Original file line number Diff line number Diff line change
Expand Up @@ -751,7 +751,8 @@ h2o_iovec_t h2o_push_path_in_link_header(h2o_req_t *req, const char *value, size

h2o_extract_push_path_from_link_header(&req->pool, value, value_len, req->path_normalized, req->input.scheme,
req->input.authority, req->res_is_delegated ? req->scheme : NULL,
req->res_is_delegated ? &req->authority : NULL, do_push_path, req, &ret);
req->res_is_delegated ? &req->authority : NULL, do_push_path, req, &ret,
req->hostconf->http2.allow_cross_origin_push);

return ret;
}
Expand Down
10 changes: 6 additions & 4 deletions lib/core/util.c
Original file line number Diff line number Diff line change
Expand Up @@ -580,7 +580,8 @@ size_t h2o_stringify_proxy_header(h2o_conn_t *conn, char *buf)
}

static h2o_iovec_t to_push_path(h2o_mem_pool_t *pool, h2o_iovec_t url, h2o_iovec_t base_path, const h2o_url_scheme_t *input_scheme,
h2o_iovec_t input_authority, const h2o_url_scheme_t *base_scheme, h2o_iovec_t *base_authority)
h2o_iovec_t input_authority, const h2o_url_scheme_t *base_scheme, h2o_iovec_t *base_authority,
int allow_cross_origin_push)
{
h2o_url_t parsed, resolved;

Expand All @@ -602,7 +603,8 @@ static h2o_iovec_t to_push_path(h2o_mem_pool_t *pool, h2o_iovec_t url, h2o_iovec
h2o_url_resolve(pool, &base, &parsed, &resolved);
if (input_scheme != resolved.scheme)
goto Invalid;
if (!h2o_lcstris(input_authority.base, input_authority.len, resolved.authority.base, resolved.authority.len))
if (!allow_cross_origin_push &&
!h2o_lcstris(input_authority.base, input_authority.len, resolved.authority.base, resolved.authority.len))
goto Invalid;

return resolved.path;
Expand All @@ -615,7 +617,7 @@ void h2o_extract_push_path_from_link_header(h2o_mem_pool_t *pool, const char *va
const h2o_url_scheme_t *input_scheme, h2o_iovec_t input_authority,
const h2o_url_scheme_t *base_scheme, h2o_iovec_t *base_authority,
void (*cb)(void *ctx, const char *path, size_t path_len, int is_critical), void *cb_ctx,
h2o_iovec_t *filtered_value)
h2o_iovec_t *filtered_value, int allow_cross_origin_push)
{
h2o_iovec_t iter = h2o_iovec_init(value, value_len), token_value;
const char *token;
Expand Down Expand Up @@ -658,7 +660,7 @@ void h2o_extract_push_path_from_link_header(h2o_mem_pool_t *pool, const char *va
/* push the path */
if (!nopush && preload) {
h2o_iovec_t path = to_push_path(pool, h2o_iovec_init(url_with_brackets.base + 1, url_with_brackets.len - 2), base_path,
input_scheme, input_authority, base_scheme, base_authority);
input_scheme, input_authority, base_scheme, base_authority, allow_cross_origin_push);
if (path.len != 0)
(*cb)(cb_ctx, path.base, path.len, critical);
}
Expand Down
13 changes: 13 additions & 0 deletions srcdoc/configure/http2_directives.mt
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,19 @@ EOT
)->(sub {});
?>

<?
$ctx->{directive}->(
name => "http2-allow-cross-origin-push",
levels => [ qw(global path) ],
since => '2.3',
default => 'http2-allow-cross-origin-push: OFF',
desc => << 'EOT',
A boolean flag (<code>ON</code> or <code>OFF</code>) indicating whether if the server should push resources belonging to a different authority.
EOT
)->(sub {
?>
? })

? })

? })
2 changes: 1 addition & 1 deletion t/00unit/lib/core/util.c
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ static void test_extract_push_path_from_link_header(void)
h2o_iovec_t input = h2o_iovec_init(_input, strlen(_input)), filtered; \
struct expected_t expected[] = {__VA_ARGS__, {NULL}}, *e = expected; \
h2o_extract_push_path_from_link_header(&pool, input.base, input.len, base_path, &H2O_URL_SCHEME_HTTP, input_authority, \
_base_scheme, _base_authority, check_path, &e, &filtered); \
_base_scheme, _base_authority, check_path, &e, &filtered, 0); \
ok(e->path == NULL); \
if (_filtered_expected != NULL) { \
ok(h2o_memis(filtered.base, filtered.len, _filtered_expected, strlen(_filtered_expected))); \
Expand Down
40 changes: 40 additions & 0 deletions t/40server-push.t
Original file line number Diff line number Diff line change
Expand Up @@ -253,4 +253,44 @@ EOT
like $resp, qr{\nid\s*responseEnd\s.*\s/index\.js\n.*\s/index.txt}is, "receives index.js then /index.txt";
};

subtest "cross-origin push" => sub {
sub test {
my ($allow_cross_origin, $must_match) = @_;
my $server = spawn_h2o(sub {
my ($port, $tls_port) = @_;
return << "EOT";
http2-allow-cross-origin-push: $allow_cross_origin
hosts:
"127.0.0.1:$tls_port":
paths:
/:
mruby.handler: |
Proc.new do |env|
case env["PATH_INFO"]
when "/index.txt"
push_paths = []
push_paths << "https://127.0.0.1.xip.io/index.js"
[399, push_paths.empty? ? {} : {"link" => push_paths.map{|p| "<#{p}>; rel=preload"}.join("\\n")}, []]
else
[399, {}, []]
end
end
file.dir: t/assets/doc_root
"127.0.0.1.xip.io:$tls_port":
paths:
/:
file.dir: t/assets/doc_root
EOT
});
my $resp = `nghttp -v -m 2 -n --stat https://127.0.0.1:$server->{tls_port}/index.txt`;
if ($must_match) {
like $resp, qr{\s+200\s+16\s+/index\.js\n}is, "receives index.js";
} else {
unlike $resp, qr{\s+200\s+16\s+/index\.js\n}is, "does not receive index.js";
}
};
test("ON", 1);
test("OFF", 0);
};

done_testing;