summaryrefslogtreecommitdiffstats
path: root/debian/vendor-h2o/lib/handler/configurator
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-13 21:12:02 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-13 21:12:02 +0000
commit77e50caaf2ef81cd91075cf836fed0e75718ffb4 (patch)
tree53b7b411290b63192fc9e924a3b6b65cdf67e9d0 /debian/vendor-h2o/lib/handler/configurator
parentAdding upstream version 1.8.3. (diff)
downloaddnsdist-77e50caaf2ef81cd91075cf836fed0e75718ffb4.tar.xz
dnsdist-77e50caaf2ef81cd91075cf836fed0e75718ffb4.zip
Adding debian version 1.8.3-2.debian/1.8.3-2
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'debian/vendor-h2o/lib/handler/configurator')
-rw-r--r--debian/vendor-h2o/lib/handler/configurator/access_log.c143
-rw-r--r--debian/vendor-h2o/lib/handler/configurator/compress.c172
-rw-r--r--debian/vendor-h2o/lib/handler/configurator/errordoc.c203
-rw-r--r--debian/vendor-h2o/lib/handler/configurator/expires.c123
-rw-r--r--debian/vendor-h2o/lib/handler/configurator/fastcgi.c388
-rw-r--r--debian/vendor-h2o/lib/handler/configurator/file.c197
-rw-r--r--debian/vendor-h2o/lib/handler/configurator/headers.c74
-rw-r--r--debian/vendor-h2o/lib/handler/configurator/headers_util.c143
-rw-r--r--debian/vendor-h2o/lib/handler/configurator/http2_debug_state.c46
-rw-r--r--debian/vendor-h2o/lib/handler/configurator/mruby.c177
-rw-r--r--debian/vendor-h2o/lib/handler/configurator/proxy.c392
-rw-r--r--debian/vendor-h2o/lib/handler/configurator/redirect.c76
-rw-r--r--debian/vendor-h2o/lib/handler/configurator/reproxy.c81
-rw-r--r--debian/vendor-h2o/lib/handler/configurator/status.c87
-rw-r--r--debian/vendor-h2o/lib/handler/configurator/throttle_resp.c73
15 files changed, 2375 insertions, 0 deletions
diff --git a/debian/vendor-h2o/lib/handler/configurator/access_log.c b/debian/vendor-h2o/lib/handler/configurator/access_log.c
new file mode 100644
index 0000000..de63808
--- /dev/null
+++ b/debian/vendor-h2o/lib/handler/configurator/access_log.c
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2014 DeNA Co., Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+#include "h2o.h"
+#include "h2o/configurator.h"
+
+typedef H2O_VECTOR(h2o_access_log_filehandle_t *) st_h2o_access_log_filehandle_vector_t;
+
+struct st_h2o_access_log_configurator_t {
+ h2o_configurator_t super;
+ st_h2o_access_log_filehandle_vector_t *handles;
+ st_h2o_access_log_filehandle_vector_t _handles_stack[H2O_CONFIGURATOR_NUM_LEVELS + 1];
+};
+
+static int on_config(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
+{
+ struct st_h2o_access_log_configurator_t *self = (void *)cmd->configurator;
+ const char *path, *fmt = NULL;
+ int escape = H2O_LOGCONF_ESCAPE_APACHE;
+ h2o_access_log_filehandle_t *fh;
+
+ switch (node->type) {
+ case YOML_TYPE_SCALAR:
+ path = node->data.scalar;
+ break;
+ case YOML_TYPE_MAPPING: {
+ yoml_t *t;
+ /* get path */
+ if ((t = yoml_get(node, "path")) == NULL) {
+ h2o_configurator_errprintf(cmd, node, "could not find mandatory key `path`");
+ return -1;
+ }
+ if (t->type != YOML_TYPE_SCALAR) {
+ h2o_configurator_errprintf(cmd, t, "`path` must be scalar");
+ return -1;
+ }
+ path = t->data.scalar;
+ /* get format */
+ if ((t = yoml_get(node, "format")) != NULL) {
+ if (t->type != YOML_TYPE_SCALAR) {
+ h2o_configurator_errprintf(cmd, t, "`format` must be a scalar");
+ return -1;
+ }
+ fmt = t->data.scalar;
+ }
+ /* get escape */
+ if ((t = yoml_get(node, "escape")) != NULL) {
+ switch (h2o_configurator_get_one_of(cmd, t, "apache,json")) {
+ case 0:
+ escape = H2O_LOGCONF_ESCAPE_APACHE;
+ break;
+ case 1:
+ escape = H2O_LOGCONF_ESCAPE_JSON;
+ break;
+ default:
+ return -1;
+ }
+ }
+ } break;
+ default:
+ h2o_configurator_errprintf(cmd, node, "node must be a scalar or a mapping");
+ return -1;
+ }
+
+ if (!ctx->dry_run) {
+ if ((fh = h2o_access_log_open_handle(path, fmt, escape)) == NULL)
+ return -1;
+ h2o_vector_reserve(NULL, self->handles, self->handles->size + 1);
+ self->handles->entries[self->handles->size++] = fh;
+ }
+
+ return 0;
+}
+
+static int on_config_enter(h2o_configurator_t *_self, h2o_configurator_context_t *ctx, yoml_t *node)
+{
+ struct st_h2o_access_log_configurator_t *self = (void *)_self;
+ size_t i;
+
+ /* push the stack pointer */
+ ++self->handles;
+
+ /* link the handles */
+ memset(self->handles, 0, sizeof(*self->handles));
+ h2o_vector_reserve(NULL, self->handles, self->handles[-1].size + 1);
+ for (i = 0; i != self->handles[-1].size; ++i) {
+ h2o_access_log_filehandle_t *fh = self->handles[-1].entries[i];
+ self->handles[0].entries[self->handles[0].size++] = fh;
+ h2o_mem_addref_shared(fh);
+ }
+
+ return 0;
+}
+
+static int on_config_exit(h2o_configurator_t *_self, h2o_configurator_context_t *ctx, yoml_t *node)
+{
+ struct st_h2o_access_log_configurator_t *self = (void *)_self;
+ size_t i;
+
+ /* register all handles, and decref them */
+ for (i = 0; i != self->handles->size; ++i) {
+ h2o_access_log_filehandle_t *fh = self->handles->entries[i];
+ if (ctx->pathconf != NULL)
+ h2o_access_log_register(ctx->pathconf, fh);
+ h2o_mem_release_shared(fh);
+ }
+ /* free the vector */
+ free(self->handles->entries);
+
+ /* pop the stack pointer */
+ --self->handles;
+
+ return 0;
+}
+
+void h2o_access_log_register_configurator(h2o_globalconf_t *conf)
+{
+ struct st_h2o_access_log_configurator_t *self = (void *)h2o_configurator_create(conf, sizeof(*self));
+
+ self->super.enter = on_config_enter;
+ self->super.exit = on_config_exit;
+ self->handles = self->_handles_stack;
+
+ h2o_configurator_define_command(&self->super, "access-log", H2O_CONFIGURATOR_FLAG_ALL_LEVELS, on_config);
+}
diff --git a/debian/vendor-h2o/lib/handler/configurator/compress.c b/debian/vendor-h2o/lib/handler/configurator/compress.c
new file mode 100644
index 0000000..c023dd5
--- /dev/null
+++ b/debian/vendor-h2o/lib/handler/configurator/compress.c
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 2015 DeNA Co., Ltd., Kazuho Oku
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+#include "h2o.h"
+#include "h2o/configurator.h"
+
+#define DEFAULT_GZIP_QUALITY 1
+#define DEFAULT_BROTLI_QUALITY 1
+
+struct compress_configurator_t {
+ h2o_configurator_t super;
+ h2o_compress_args_t *vars, _vars_stack[H2O_CONFIGURATOR_NUM_LEVELS + 1];
+};
+
+static const h2o_compress_args_t all_off = {0, {-1}, {-1}}, all_on = {100, {DEFAULT_GZIP_QUALITY}, {DEFAULT_BROTLI_QUALITY}};
+
+static int on_config_gzip(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
+{
+ struct compress_configurator_t *self = (void *)cmd->configurator;
+ int mode;
+
+ if ((mode = (int)h2o_configurator_get_one_of(cmd, node, "OFF,ON")) == -1)
+ return -1;
+
+ *self->vars = all_off;
+ if (mode != 0)
+ self->vars->gzip.quality = DEFAULT_GZIP_QUALITY;
+
+ return 0;
+}
+
+static int obtain_quality(yoml_t *node, int min_quality, int max_quality, int default_quality, int *slot)
+{
+ int tmp;
+ if (node->type != YOML_TYPE_SCALAR)
+ return -1;
+ if (strcasecmp(node->data.scalar, "OFF") == 0) {
+ *slot = -1;
+ return 0;
+ }
+ if (strcasecmp(node->data.scalar, "ON") == 0) {
+ *slot = default_quality;
+ return 0;
+ }
+ if (sscanf(node->data.scalar, "%d", &tmp) == 1 && (min_quality <= tmp && tmp <= max_quality)) {
+ *slot = tmp;
+ return 0;
+ }
+ return -1;
+}
+
+static int on_config_compress_min_size(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
+{
+ struct compress_configurator_t *self = (void *)cmd->configurator;
+ return h2o_configurator_scanf(cmd, node, "%zu", &self->vars->min_size);
+}
+
+static int on_config_compress(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
+{
+ struct compress_configurator_t *self = (void *)cmd->configurator;
+ size_t i;
+
+ switch (node->type) {
+ case YOML_TYPE_SCALAR:
+ if (strcasecmp(node->data.scalar, "OFF") == 0) {
+ *self->vars = all_off;
+ } else if (strcasecmp(node->data.scalar, "ON") == 0) {
+ *self->vars = all_on;
+ } else {
+ h2o_configurator_errprintf(cmd, node, "scalar argument must be either of: `OFF`, `ON`");
+ return -1;
+ }
+ break;
+ case YOML_TYPE_SEQUENCE:
+ *self->vars = all_off;
+ for (i = 0; i != node->data.sequence.size; ++i) {
+ yoml_t *element = node->data.sequence.elements[i];
+ if (element->type == YOML_TYPE_SCALAR && strcasecmp(element->data.scalar, "gzip") == 0) {
+ self->vars->gzip.quality = DEFAULT_GZIP_QUALITY;
+ } else if (element->type == YOML_TYPE_SCALAR && strcasecmp(element->data.scalar, "br") == 0) {
+ self->vars->brotli.quality = DEFAULT_BROTLI_QUALITY;
+ } else {
+ h2o_configurator_errprintf(cmd, element, "element of the sequence must be either of: `gzip`, `br`");
+ return -1;
+ }
+ }
+ break;
+ case YOML_TYPE_MAPPING:
+ *self->vars = all_off;
+ for (i = 0; i != node->data.mapping.size; ++i) {
+ yoml_t *key = node->data.mapping.elements[i].key;
+ yoml_t *value = node->data.mapping.elements[i].value;
+ if (key->type == YOML_TYPE_SCALAR && strcasecmp(key->data.scalar, "gzip") == 0) {
+ if (obtain_quality(value, 1, 9, DEFAULT_GZIP_QUALITY, &self->vars->gzip.quality) != 0) {
+ h2o_configurator_errprintf(
+ cmd, value, "value of gzip attribute must be either of `OFF`, `ON` or an integer value between 1 and 9");
+ return -1;
+ }
+ } else if (key->type == YOML_TYPE_SCALAR && strcasecmp(key->data.scalar, "br") == 0) {
+ if (obtain_quality(value, 0, 11, DEFAULT_BROTLI_QUALITY, &self->vars->brotli.quality) != 0) {
+ h2o_configurator_errprintf(
+ cmd, value, "value of br attribute must be either of `OFF`, `ON` or an integer between 0 and 11");
+ return -1;
+ }
+ } else {
+ h2o_configurator_errprintf(cmd, key, "key must be either of: `gzip`, `br`");
+ return -1;
+ }
+ }
+ break;
+ default:
+ h2o_fatal("unexpected node type");
+ break;
+ }
+
+ return 0;
+}
+
+static int on_config_enter(h2o_configurator_t *configurator, h2o_configurator_context_t *ctx, yoml_t *node)
+{
+ struct compress_configurator_t *self = (void *)configurator;
+
+ ++self->vars;
+ self->vars[0] = self->vars[-1];
+ return 0;
+}
+
+static int on_config_exit(h2o_configurator_t *configurator, h2o_configurator_context_t *ctx, yoml_t *node)
+{
+ struct compress_configurator_t *self = (void *)configurator;
+
+ if (ctx->pathconf != NULL && (self->vars->gzip.quality != -1 || self->vars->brotli.quality != -1))
+ h2o_compress_register(ctx->pathconf, self->vars);
+
+ --self->vars;
+ return 0;
+}
+
+void h2o_compress_register_configurator(h2o_globalconf_t *conf)
+{
+ struct compress_configurator_t *c = (void *)h2o_configurator_create(conf, sizeof(*c));
+
+ c->super.enter = on_config_enter;
+ c->super.exit = on_config_exit;
+ h2o_configurator_define_command(&c->super, "compress", H2O_CONFIGURATOR_FLAG_ALL_LEVELS, on_config_compress);
+ h2o_configurator_define_command(&c->super, "compress-minimum-size",
+ H2O_CONFIGURATOR_FLAG_ALL_LEVELS | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
+ on_config_compress_min_size);
+ h2o_configurator_define_command(&c->super, "gzip", H2O_CONFIGURATOR_FLAG_ALL_LEVELS | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
+ on_config_gzip);
+ c->vars = c->_vars_stack;
+ c->vars->gzip.quality = -1;
+ c->vars->brotli.quality = -1;
+}
diff --git a/debian/vendor-h2o/lib/handler/configurator/errordoc.c b/debian/vendor-h2o/lib/handler/configurator/errordoc.c
new file mode 100644
index 0000000..ab24923
--- /dev/null
+++ b/debian/vendor-h2o/lib/handler/configurator/errordoc.c
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2015-2016 DeNA Co., Ltd., Kazuho Oku
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+#include "h2o.h"
+#include "h2o/configurator.h"
+
+struct errordoc_configurator_t {
+ h2o_configurator_t super;
+ h2o_mem_pool_t pool;
+ H2O_VECTOR(h2o_errordoc_t) * vars, _vars_stack[H2O_CONFIGURATOR_NUM_LEVELS + 1];
+};
+
+static int scan_and_check_status(h2o_configurator_command_t *cmd, yoml_t *value, int *slot)
+{
+ if (value->type != YOML_TYPE_SCALAR) {
+ h2o_configurator_errprintf(cmd, value, "status must be must be either of: scalar, sequence of scalar");
+ return -1;
+ }
+ if (h2o_configurator_scanf(cmd, value, "%d", slot) != 0)
+ return -1;
+ if (!(400 <= *slot && *slot <= 599)) {
+ h2o_configurator_errprintf(cmd, value, "status must be within range of 400 to 599");
+ return -1;
+ }
+ return 0;
+}
+
+static int register_errordoc(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *hash)
+{
+ struct errordoc_configurator_t *self = (void *)cmd->configurator;
+ int status[200];
+ size_t status_len = 0;
+ int parsed;
+ const char *url = NULL;
+ size_t i, j, k;
+ yoml_t *key, *value;
+
+ for (i = 0; i != hash->data.mapping.size; ++i) {
+ key = hash->data.mapping.elements[i].key;
+ value = hash->data.mapping.elements[i].value;
+ if (key->type != YOML_TYPE_SCALAR)
+ goto UnknownKeyError;
+ if (strcmp(key->data.scalar, "status") == 0) {
+ if (status_len != 0)
+ goto KeyAlreadyDefinedError;
+
+ if (value->type == YOML_TYPE_SEQUENCE) {
+ if (value->data.sequence.size == 0) {
+ h2o_configurator_errprintf(cmd, value, "status sequence must not be empty");
+ return -1;
+ }
+ for (j = 0; j != value->data.sequence.size; ++j) {
+ if (scan_and_check_status(cmd, value->data.sequence.elements[j], &parsed) != 0)
+ return -1;
+ /* check the scanned status hasn't already appeared */
+ for (k = 0; k != status_len; ++k) {
+ if (status[k] == parsed) {
+ h2o_configurator_errprintf(cmd, value, "status %d appears multiple times", status[k]);
+ return -1;
+ }
+ }
+ status[status_len++] = parsed;
+ }
+ } else {
+ if (scan_and_check_status(cmd, value, &parsed) != 0)
+ return -1;
+ status[status_len++] = parsed;
+ }
+
+ } else if (strcmp(key->data.scalar, "url") == 0) {
+ if (url != NULL)
+ goto KeyAlreadyDefinedError;
+ if (value->type != YOML_TYPE_SCALAR) {
+ h2o_configurator_errprintf(cmd, value, "URL must be a scalar");
+ return -1;
+ }
+ url = value->data.scalar;
+ } else {
+ goto UnknownKeyError;
+ }
+ }
+
+ if (status_len == 0) {
+ h2o_configurator_errprintf(cmd, hash, "mandatory key `status` is not defined");
+ return -1;
+ }
+ if (url == NULL) {
+ h2o_configurator_errprintf(cmd, hash, "mandatory key `url` is not defined");
+ return -1;
+ }
+
+ h2o_iovec_t _url = h2o_strdup(&self->pool, url, SIZE_MAX);
+ for (i = 0; i != status_len; ++i){
+ /* register */
+ h2o_vector_reserve(&self->pool, self->vars, self->vars->size + 1);
+ h2o_errordoc_t *errordoc = self->vars->entries + self->vars->size++;
+ errordoc->status = status[i];
+ errordoc->url = _url;
+ }
+
+ return 0;
+
+UnknownKeyError:
+ h2o_configurator_errprintf(cmd, key, "key must be either of: `status`, `url`");
+ return -1;
+KeyAlreadyDefinedError:
+ h2o_configurator_errprintf(cmd, key, "the key cannot be defined more than once");
+ return -1;
+}
+
+static int on_config_errordoc(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
+{
+ switch (node->type) {
+ case YOML_TYPE_SEQUENCE: {
+ size_t i;
+ for (i = 0; i != node->data.sequence.size; ++i) {
+ yoml_t *e = node->data.sequence.elements[i];
+ if (e->type != YOML_TYPE_MAPPING) {
+ h2o_configurator_errprintf(cmd, e, "element must be a mapping");
+ return -1;
+ }
+ if (register_errordoc(cmd, ctx, e) != 0)
+ return -1;
+ }
+ return 0;
+ }
+ case YOML_TYPE_MAPPING:
+ return register_errordoc(cmd, ctx, node);
+ default:
+ break;
+ }
+
+ h2o_configurator_errprintf(cmd, node, "argument must be either of: sequence, mapping");
+ return -1;
+}
+
+static int on_config_enter(h2o_configurator_t *_self, h2o_configurator_context_t *ctx, yoml_t *node)
+{
+ struct errordoc_configurator_t *self = (void *)_self;
+
+ if (self->vars == self->_vars_stack) {
+ /* entering global level */
+ h2o_mem_init_pool(&self->pool);
+ }
+
+ /* copy vars */
+ memset(&self->vars[1], 0, sizeof(self->vars[1]));
+ h2o_vector_reserve(&self->pool, &self->vars[1], self->vars[0].size);
+ h2o_memcpy(self->vars[1].entries, self->vars[0].entries, sizeof(self->vars[0].entries[0]) * self->vars[0].size);
+ self->vars[1].size = self->vars[0].size;
+
+ ++self->vars;
+ return 0;
+}
+
+static int on_config_exit(h2o_configurator_t *_self, h2o_configurator_context_t *ctx, yoml_t *node)
+{
+ struct errordoc_configurator_t *self = (void *)_self;
+
+ if (ctx->pathconf != NULL && self->vars->size != 0)
+ h2o_errordoc_register(ctx->pathconf, self->vars->entries, self->vars->size);
+
+ --self->vars;
+ if (self->vars == self->_vars_stack) {
+ /* exitting global level */
+ h2o_mem_clear_pool(&self->pool);
+ }
+
+ return 0;
+}
+
+void h2o_errordoc_register_configurator(h2o_globalconf_t *conf)
+{
+ struct errordoc_configurator_t *c = (void *)h2o_configurator_create(conf, sizeof(*c));
+
+ /* set default vars */
+ c->vars = c->_vars_stack;
+
+ /* setup handlers */
+ c->super.enter = on_config_enter;
+ c->super.exit = on_config_exit;
+
+ /* reproxy: ON | OFF */
+ h2o_configurator_define_command(&c->super, "error-doc", H2O_CONFIGURATOR_FLAG_ALL_LEVELS, on_config_errordoc);
+}
diff --git a/debian/vendor-h2o/lib/handler/configurator/expires.c b/debian/vendor-h2o/lib/handler/configurator/expires.c
new file mode 100644
index 0000000..01d404d
--- /dev/null
+++ b/debian/vendor-h2o/lib/handler/configurator/expires.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2014 DeNA Co., Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+#include <inttypes.h>
+#include <stdio.h>
+#include <string.h>
+#include "h2o.h"
+#include "h2o/configurator.h"
+
+struct expires_configurator_t {
+ h2o_configurator_t super;
+ h2o_expires_args_t **args;
+ h2o_expires_args_t *_args_stack[H2O_CONFIGURATOR_NUM_LEVELS + 1];
+};
+
+static int on_config_expires(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
+{
+ struct expires_configurator_t *self = (void *)cmd->configurator;
+ uint64_t value;
+ char unit[32];
+
+ if (strcasecmp(node->data.scalar, "OFF") == 0) {
+ free(*self->args);
+ *self->args = NULL;
+ } else if (sscanf(node->data.scalar, "%" SCNu64 " %31s", &value, unit) == 2) {
+ /* convert value to seconds depending on the unit */
+ if (strncasecmp(unit, H2O_STRLIT("second")) == 0) {
+ /* ok */
+ } else if (strncasecmp(unit, H2O_STRLIT("minute")) == 0) {
+ value *= 60;
+ } else if (strncasecmp(unit, H2O_STRLIT("hour")) == 0) {
+ value *= 60 * 60;
+ } else if (strncasecmp(unit, H2O_STRLIT("day")) == 0) {
+ value *= 24 * 60 * 60;
+ } else if (strncasecmp(unit, H2O_STRLIT("month")) == 0) {
+ value *= 30 * 24 * 60 * 60;
+ } else if (strncasecmp(unit, H2O_STRLIT("year")) == 0) {
+ value *= 365 * 30 * 24 * 60 * 60;
+ } else {
+ /* TODO add support for H2O_EXPIRES_MODE_MAX_ABSOLUTE that sets the Expires header? */
+ h2o_configurator_errprintf(cmd, node, "unknown unit:`%s` (see --help)", unit);
+ return -1;
+ }
+ /* save the value */
+ if (*self->args == NULL)
+ *self->args = h2o_mem_alloc(sizeof(**self->args));
+ (*self->args)->mode = H2O_EXPIRES_MODE_MAX_AGE;
+ (*self->args)->data.max_age = value;
+ } else {
+ h2o_configurator_errprintf(cmd, node,
+ "failed to parse the value, should be in form of: `<number> <unit>` or `OFF` (see --help)");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int on_config_enter(h2o_configurator_t *_self, h2o_configurator_context_t *ctx, yoml_t *node)
+{
+ struct expires_configurator_t *self = (void *)_self;
+
+ if (self->args[0] != NULL) {
+ /* duplicate */
+ assert(self->args[0]->mode == H2O_EXPIRES_MODE_MAX_AGE);
+ self->args[1] = h2o_mem_alloc(sizeof(**self->args));
+ *self->args[1] = *self->args[0];
+ } else {
+ self->args[1] = NULL;
+ }
+ ++self->args;
+ return 0;
+}
+
+static int on_config_exit(h2o_configurator_t *_self, h2o_configurator_context_t *ctx, yoml_t *node)
+{
+ struct expires_configurator_t *self = (void *)_self;
+
+ if (*self->args != NULL) {
+ /* setup */
+ if (ctx->pathconf != NULL) {
+ h2o_expires_register(ctx->pathconf, *self->args);
+ }
+ /* destruct */
+ assert((*self->args)->mode == H2O_EXPIRES_MODE_MAX_AGE);
+ free(*self->args);
+ *self->args = NULL;
+ }
+
+ --self->args;
+ return 0;
+}
+
+void h2o_expires_register_configurator(h2o_globalconf_t *conf)
+{
+ struct expires_configurator_t *c = (void *)h2o_configurator_create(conf, sizeof(*c));
+
+ /* set default vars */
+ c->args = c->_args_stack;
+
+ /* setup handlers */
+ c->super.enter = on_config_enter;
+ c->super.exit = on_config_exit;
+ h2o_configurator_define_command(&c->super, "expires", H2O_CONFIGURATOR_FLAG_ALL_LEVELS | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
+ on_config_expires);
+}
diff --git a/debian/vendor-h2o/lib/handler/configurator/fastcgi.c b/debian/vendor-h2o/lib/handler/configurator/fastcgi.c
new file mode 100644
index 0000000..bf89b7b
--- /dev/null
+++ b/debian/vendor-h2o/lib/handler/configurator/fastcgi.c
@@ -0,0 +1,388 @@
+/*
+ * Copyright (c) 2015 DeNA Co., Ltd. Kazuho Oku
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+#include <arpa/inet.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <pwd.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/un.h>
+#include "h2o.h"
+#include "h2o/configurator.h"
+#include "h2o/serverutil.h"
+
+struct fastcgi_configurator_t {
+ h2o_configurator_t super;
+ h2o_fastcgi_config_vars_t *vars;
+ h2o_fastcgi_config_vars_t _vars_stack[H2O_CONFIGURATOR_NUM_LEVELS + 1];
+};
+
+static int on_config_timeout_io(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
+{
+ struct fastcgi_configurator_t *self = (void *)cmd->configurator;
+ return h2o_configurator_scanf(cmd, node, "%" SCNu64, &self->vars->io_timeout);
+}
+
+static int on_config_timeout_keepalive(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
+{
+ struct fastcgi_configurator_t *self = (void *)cmd->configurator;
+ return h2o_configurator_scanf(cmd, node, "%" SCNu64, &self->vars->keepalive_timeout);
+}
+
+static int on_config_document_root(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
+{
+ struct fastcgi_configurator_t *self = (void *)cmd->configurator;
+
+ if (node->data.scalar[0] == '\0') {
+ /* unset */
+ self->vars->document_root = h2o_iovec_init(NULL, 0);
+ } else if (node->data.scalar[0] == '/') {
+ /* set */
+ self->vars->document_root = h2o_iovec_init(node->data.scalar, strlen(node->data.scalar));
+ } else {
+ h2o_configurator_errprintf(cmd, node, "value does not start from `/`");
+ return -1;
+ }
+ return 0;
+}
+
+static int on_config_send_delegated_uri(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
+{
+ struct fastcgi_configurator_t *self = (void *)cmd->configurator;
+ ssize_t v;
+
+ if ((v = h2o_configurator_get_one_of(cmd, node, "OFF,ON")) == -1)
+ return -1;
+ self->vars->send_delegated_uri = (int)v;
+ return 0;
+}
+
+static int on_config_connect(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
+{
+ struct fastcgi_configurator_t *self = (void *)cmd->configurator;
+ const char *hostname = "127.0.0.1", *servname = NULL, *type = "tcp";
+
+ /* fetch servname (and hostname) */
+ switch (node->type) {
+ case YOML_TYPE_SCALAR:
+ servname = node->data.scalar;
+ break;
+ case YOML_TYPE_MAPPING: {
+ yoml_t *t;
+ if ((t = yoml_get(node, "host")) != NULL) {
+ if (t->type != YOML_TYPE_SCALAR) {
+ h2o_configurator_errprintf(cmd, t, "`host` is not a string");
+ return -1;
+ }
+ hostname = t->data.scalar;
+ }
+ if ((t = yoml_get(node, "port")) == NULL) {
+ h2o_configurator_errprintf(cmd, node, "cannot find mandatory property `port`");
+ return -1;
+ }
+ if (t->type != YOML_TYPE_SCALAR) {
+ h2o_configurator_errprintf(cmd, node, "`port` is not a string");
+ return -1;
+ }
+ servname = t->data.scalar;
+ if ((t = yoml_get(node, "type")) != NULL) {
+ if (t->type != YOML_TYPE_SCALAR) {
+ h2o_configurator_errprintf(cmd, t, "`type` is not a string");
+ return -1;
+ }
+ type = t->data.scalar;
+ }
+ } break;
+ default:
+ h2o_configurator_errprintf(cmd, node,
+ "value must be a string or a mapping (with keys: `port` and optionally `host` and `type`)");
+ return -1;
+ }
+
+ if (strcmp(type, "unix") == 0) {
+ /* unix socket */
+ struct sockaddr_un sa;
+ memset(&sa, 0, sizeof(sa));
+ if (strlen(servname) >= sizeof(sa.sun_path)) {
+ h2o_configurator_errprintf(cmd, node, "path:%s is too long as a unix socket name", servname);
+ return -1;
+ }
+ sa.sun_family = AF_UNIX;
+ strcpy(sa.sun_path, servname);
+ h2o_fastcgi_register_by_address(ctx->pathconf, (void *)&sa, sizeof(sa), self->vars);
+ } else if (strcmp(type, "tcp") == 0) {
+ /* tcp socket */
+ uint16_t port;
+ if (sscanf(servname, "%" SCNu16, &port) != 1) {
+ h2o_configurator_errprintf(cmd, node, "invalid port number:%s", servname);
+ return -1;
+ }
+ h2o_fastcgi_register_by_hostport(ctx->pathconf, hostname, port, self->vars);
+ } else {
+ h2o_configurator_errprintf(cmd, node, "unknown listen type: %s", type);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int create_spawnproc(h2o_configurator_command_t *cmd, yoml_t *node, const char *dirname, char *const *argv,
+ struct sockaddr_un *sa, struct passwd *pw)
+{
+ int ret, listen_fd = -1, pipe_fds[2] = {-1, -1};
+
+ /* build socket path */
+ sa->sun_family = AF_UNIX;
+ ret = snprintf(sa->sun_path, sizeof(sa->sun_path), "%s/_", dirname);
+ if (ret < 0 || ret >= sizeof(sa->sun_path)) {
+ h2o_configurator_errprintf(cmd, node, "unix socket path too long: %s", dirname);
+ goto Error;
+ }
+
+ /* create socket */
+ if ((listen_fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
+ h2o_configurator_errprintf(cmd, node, "socket(2) failed: %s", strerror(errno));
+ goto Error;
+ }
+ if (bind(listen_fd, (void *)sa, sizeof(*sa)) != 0) {
+ h2o_configurator_errprintf(cmd, node, "bind(2) failed: %s", strerror(errno));
+ goto Error;
+ }
+ if (listen(listen_fd, H2O_SOMAXCONN) != 0) {
+ h2o_configurator_errprintf(cmd, node, "listen(2) failed: %s", strerror(errno));
+ goto Error;
+ }
+ /* change ownership of socket */
+ if (pw != NULL && chown(sa->sun_path, pw->pw_uid, pw->pw_gid) != 0) {
+ h2o_configurator_errprintf(cmd, node, "chown(2) failed to change ownership of socket:%s:%s", sa->sun_path, strerror(errno));
+ goto Error;
+ }
+
+ /* create pipe which is used to notify the termination of the server */
+ if (pipe(pipe_fds) != 0) {
+ h2o_configurator_errprintf(cmd, node, "pipe(2) failed: %s", strerror(errno));
+ pipe_fds[0] = -1;
+ pipe_fds[1] = -1;
+ goto Error;
+ }
+ if (fcntl(pipe_fds[1], F_SETFD, FD_CLOEXEC) < 0)
+ goto Error;
+
+ /* spawn */
+ int mapped_fds[] = {listen_fd, 0, /* listen_fd to 0 */
+ pipe_fds[0], 5, /* pipe_fds[0] to 5 */
+ -1};
+ pid_t pid = h2o_spawnp(argv[0], argv, mapped_fds, 0);
+ if (pid == -1) {
+ fprintf(stderr, "[lib/handler/fastcgi.c] failed to launch helper program %s:%s\n", argv[0], strerror(errno));
+ goto Error;
+ }
+
+ close(listen_fd);
+ listen_fd = -1;
+ close(pipe_fds[0]);
+ pipe_fds[0] = -1;
+
+ return pipe_fds[1];
+
+Error:
+ if (pipe_fds[0] != -1)
+ close(pipe_fds[0]);
+ if (pipe_fds[1])
+ close(pipe_fds[1]);
+ if (listen_fd != -1)
+ close(listen_fd);
+ unlink(sa->sun_path);
+ return -1;
+}
+
+static void spawnproc_on_dispose(h2o_fastcgi_handler_t *handler, void *data)
+{
+ int pipe_fd = (int)((char *)data - (char *)NULL);
+ close(pipe_fd);
+}
+
+static int on_config_spawn(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
+{
+ struct fastcgi_configurator_t *self = (void *)cmd->configurator;
+ char *spawn_user = NULL, *spawn_cmd;
+ char *kill_on_close_cmd_path = NULL, *setuidgid_cmd_path = NULL;
+ char dirname[] = "/tmp/h2o.fcgisock.XXXXXX";
+ char *argv[10];
+ int spawner_fd;
+ struct sockaddr_un sa;
+ h2o_fastcgi_config_vars_t config_vars;
+ int ret = -1;
+ struct passwd h2o_user_pwbuf, *h2o_user_pw;
+ char h2o_user_buf[65536];
+
+ memset(&sa, 0, sizeof(sa));
+
+ switch (node->type) {
+ case YOML_TYPE_SCALAR:
+ spawn_user = ctx->globalconf->user;
+ spawn_cmd = node->data.scalar;
+ break;
+ case YOML_TYPE_MAPPING: {
+ yoml_t *t;
+ if ((t = yoml_get(node, "command")) == NULL) {
+ h2o_configurator_errprintf(cmd, node, "mandatory attribute `command` does not exist");
+ return -1;
+ }
+ if (t->type != YOML_TYPE_SCALAR) {
+ h2o_configurator_errprintf(cmd, node, "attribute `command` must be scalar");
+ return -1;
+ }
+ spawn_cmd = t->data.scalar;
+ spawn_user = ctx->globalconf->user;
+ if ((t = yoml_get(node, "user")) != NULL) {
+ if (t->type != YOML_TYPE_SCALAR) {
+ h2o_configurator_errprintf(cmd, node, "attribute `user` must be scalar");
+ return -1;
+ }
+ spawn_user = t->data.scalar;
+ }
+ } break;
+ default:
+ h2o_configurator_errprintf(cmd, node, "argument must be scalar or mapping");
+ return -1;
+ }
+
+ /* obtain uid & gid of the client that connects to the FastCGI daemon (i.e. H2O after dropping privileges) */
+ if (ctx->globalconf->user != NULL) {
+ /* change ownership of temporary directory */
+ if (getpwnam_r(ctx->globalconf->user, &h2o_user_pwbuf, h2o_user_buf, sizeof(h2o_user_buf), &h2o_user_pw) != 0 ||
+ h2o_user_pw == NULL) {
+ h2o_configurator_errprintf(cmd, node, "getpwnam_r(3) failed to obtain uid of user:%s", ctx->globalconf->user);
+ goto Exit;
+ }
+ } else {
+ h2o_user_pw = NULL;
+ }
+
+ { /* build args */
+ size_t i = 0;
+ argv[i++] = kill_on_close_cmd_path = h2o_configurator_get_cmd_path("share/h2o/kill-on-close");
+ argv[i++] = "--rm";
+ argv[i++] = dirname;
+ argv[i++] = "--";
+ if (spawn_user != NULL) {
+ argv[i++] = setuidgid_cmd_path = h2o_configurator_get_cmd_path("share/h2o/setuidgid");
+ argv[i++] = spawn_user;
+ }
+ argv[i++] = "/bin/sh";
+ argv[i++] = "-c";
+ argv[i++] = spawn_cmd;
+ argv[i++] = NULL;
+ assert(i <= sizeof(argv) / sizeof(argv[0]));
+ }
+
+ if (ctx->dry_run) {
+ dirname[0] = '\0';
+ spawner_fd = -1;
+ sa.sun_family = AF_UNIX;
+ strcpy(sa.sun_path, "/dry-run.nonexistent");
+ } else {
+ /* create temporary directory */
+ if (mkdtemp(dirname) == NULL) {
+ h2o_configurator_errprintf(cmd, node, "mkdtemp(3) failed to create temporary directory:%s:%s", dirname,
+ strerror(errno));
+ dirname[0] = '\0';
+ goto Exit;
+ }
+ /* change ownership of temporary directory */
+ if (h2o_user_pw != NULL && chown(dirname, h2o_user_pw->pw_uid, h2o_user_pw->pw_gid) != 0) {
+ h2o_configurator_errprintf(cmd, node, "chown(2) failed to change ownership of temporary directory:%s:%s", dirname,
+ strerror(errno));
+ goto Exit;
+ }
+ /* launch spawnfcgi command */
+ if ((spawner_fd = create_spawnproc(cmd, node, dirname, argv, &sa, h2o_user_pw)) == -1) {
+ goto Exit;
+ }
+ }
+
+ config_vars = *self->vars;
+ config_vars.callbacks.dispose = spawnproc_on_dispose;
+ config_vars.callbacks.data = (char *)NULL + spawner_fd;
+ h2o_fastcgi_register_by_address(ctx->pathconf, (void *)&sa, sizeof(sa), &config_vars);
+
+ ret = 0;
+Exit:
+ if (dirname[0] != '\0')
+ unlink(dirname);
+ free(kill_on_close_cmd_path);
+ free(setuidgid_cmd_path);
+ return ret;
+}
+
+static int on_config_enter(h2o_configurator_t *_self, h2o_configurator_context_t *ctx, yoml_t *node)
+{
+ struct fastcgi_configurator_t *self = (void *)_self;
+
+ memcpy(self->vars + 1, self->vars, sizeof(*self->vars));
+ ++self->vars;
+ return 0;
+}
+
+static int on_config_exit(h2o_configurator_t *_self, h2o_configurator_context_t *ctx, yoml_t *node)
+{
+ struct fastcgi_configurator_t *self = (void *)_self;
+
+ --self->vars;
+ return 0;
+}
+
+void h2o_fastcgi_register_configurator(h2o_globalconf_t *conf)
+{
+ struct fastcgi_configurator_t *c = (void *)h2o_configurator_create(conf, sizeof(*c));
+
+ /* set default vars */
+ c->vars = c->_vars_stack;
+ c->vars->io_timeout = H2O_DEFAULT_FASTCGI_IO_TIMEOUT;
+ c->vars->keepalive_timeout = 0;
+
+ /* setup handlers */
+ c->super.enter = on_config_enter;
+ c->super.exit = on_config_exit;
+
+ h2o_configurator_define_command(&c->super, "fastcgi.connect",
+ H2O_CONFIGURATOR_FLAG_PATH | H2O_CONFIGURATOR_FLAG_EXTENSION | H2O_CONFIGURATOR_FLAG_DEFERRED,
+ on_config_connect);
+ h2o_configurator_define_command(&c->super, "fastcgi.spawn",
+ H2O_CONFIGURATOR_FLAG_PATH | H2O_CONFIGURATOR_FLAG_EXTENSION | H2O_CONFIGURATOR_FLAG_DEFERRED,
+ on_config_spawn);
+ h2o_configurator_define_command(&c->super, "fastcgi.timeout.io",
+ H2O_CONFIGURATOR_FLAG_ALL_LEVELS | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR, on_config_timeout_io);
+ h2o_configurator_define_command(&c->super, "fastcgi.timeout.keepalive",
+ H2O_CONFIGURATOR_FLAG_ALL_LEVELS | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
+ on_config_timeout_keepalive);
+ h2o_configurator_define_command(&c->super, "fastcgi.document_root",
+ H2O_CONFIGURATOR_FLAG_ALL_LEVELS | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
+ on_config_document_root);
+ h2o_configurator_define_command(&c->super, "fastcgi.send-delegated-uri",
+ H2O_CONFIGURATOR_FLAG_ALL_LEVELS | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
+ on_config_send_delegated_uri);
+}
diff --git a/debian/vendor-h2o/lib/handler/configurator/file.c b/debian/vendor-h2o/lib/handler/configurator/file.c
new file mode 100644
index 0000000..c1c779c
--- /dev/null
+++ b/debian/vendor-h2o/lib/handler/configurator/file.c
@@ -0,0 +1,197 @@
+/*
+ * Copyright (c) 2014 DeNA Co., Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+#include "h2o.h"
+#include "h2o/configurator.h"
+
+struct st_h2o_file_config_vars_t {
+ const char **index_files;
+ int flags;
+};
+
+struct st_h2o_file_configurator_t {
+ h2o_configurator_t super;
+ struct st_h2o_file_config_vars_t *vars;
+ struct st_h2o_file_config_vars_t _vars_stack[H2O_CONFIGURATOR_NUM_LEVELS + 1];
+};
+
+static int on_config_dir(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
+{
+ struct st_h2o_file_configurator_t *self = (void *)cmd->configurator;
+
+ h2o_file_register(ctx->pathconf, node->data.scalar, self->vars->index_files, *ctx->mimemap, self->vars->flags);
+ return 0;
+}
+
+static int on_config_file(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
+{
+ struct st_h2o_file_configurator_t *self = (void *)cmd->configurator;
+ h2o_mimemap_type_t *mime_type =
+ h2o_mimemap_get_type_by_extension(*ctx->mimemap, h2o_get_filext(node->data.scalar, strlen(node->data.scalar)));
+ h2o_file_register_file(ctx->pathconf, node->data.scalar, mime_type, self->vars->flags);
+ return 0;
+}
+
+static int on_config_index(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
+{
+ struct st_h2o_file_configurator_t *self = (void *)cmd->configurator;
+ size_t i;
+
+ free(self->vars->index_files);
+ self->vars->index_files = h2o_mem_alloc(sizeof(self->vars->index_files[0]) * (node->data.sequence.size + 1));
+ for (i = 0; i != node->data.sequence.size; ++i) {
+ yoml_t *element = node->data.sequence.elements[i];
+ if (element->type != YOML_TYPE_SCALAR) {
+ h2o_configurator_errprintf(cmd, element, "argument must be a sequence of scalars");
+ return -1;
+ }
+ self->vars->index_files[i] = element->data.scalar;
+ }
+ self->vars->index_files[i] = NULL;
+
+ return 0;
+}
+
+static int on_config_etag(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
+{
+ struct st_h2o_file_configurator_t *self = (void *)cmd->configurator;
+
+ switch (h2o_configurator_get_one_of(cmd, node, "OFF,ON")) {
+ case 0: /* off */
+ self->vars->flags |= H2O_FILE_FLAG_NO_ETAG;
+ break;
+ case 1: /* on */
+ self->vars->flags &= ~H2O_FILE_FLAG_NO_ETAG;
+ break;
+ default: /* error */
+ return -1;
+ }
+
+ return 0;
+}
+
+static int on_config_send_compressed(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
+{
+ struct st_h2o_file_configurator_t *self = (void *)cmd->configurator;
+
+ switch (h2o_configurator_get_one_of(cmd, node, "OFF,ON,gunzip")) {
+ case 0: /* off */
+ self->vars->flags &= ~H2O_FILE_FLAG_SEND_COMPRESSED;
+ break;
+ case 1: /* on */
+ self->vars->flags |= H2O_FILE_FLAG_SEND_COMPRESSED;
+ break;
+ case 2: /* gunzip */
+ self->vars->flags |= (H2O_FILE_FLAG_SEND_COMPRESSED | H2O_FILE_FLAG_GUNZIP);
+ break;
+ default: /* error */
+ return -1;
+ }
+
+ return 0;
+}
+
+static int on_config_dir_listing(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
+{
+ struct st_h2o_file_configurator_t *self = (void *)cmd->configurator;
+
+ switch (h2o_configurator_get_one_of(cmd, node, "OFF,ON")) {
+ case 0: /* off */
+ self->vars->flags &= ~H2O_FILE_FLAG_DIR_LISTING;
+ break;
+ case 1: /* on */
+ self->vars->flags |= H2O_FILE_FLAG_DIR_LISTING;
+ break;
+ default: /* error */
+ return -1;
+ }
+
+ return 0;
+}
+
+static const char **dup_strlist(const char **s)
+{
+ size_t i;
+ const char **ret;
+
+ for (i = 0; s[i] != NULL; ++i)
+ ;
+ ret = h2o_mem_alloc(sizeof(*ret) * (i + 1));
+ for (i = 0; s[i] != NULL; ++i)
+ ret[i] = s[i];
+ ret[i] = NULL;
+
+ return ret;
+}
+
+static int on_config_enter(h2o_configurator_t *_self, h2o_configurator_context_t *ctx, yoml_t *node)
+{
+ struct st_h2o_file_configurator_t *self = (void *)_self;
+ ++self->vars;
+ self->vars[0].index_files = dup_strlist(self->vars[-1].index_files);
+ self->vars[0].flags = self->vars[-1].flags;
+ return 0;
+}
+
+static int on_config_exit(h2o_configurator_t *_self, h2o_configurator_context_t *ctx, yoml_t *node)
+{
+ struct st_h2o_file_configurator_t *self = (void *)_self;
+ free(self->vars->index_files);
+ --self->vars;
+ return 0;
+}
+
+void h2o_file_register_configurator(h2o_globalconf_t *globalconf)
+{
+ struct st_h2o_file_configurator_t *self = (void *)h2o_configurator_create(globalconf, sizeof(*self));
+
+ self->super.enter = on_config_enter;
+ self->super.exit = on_config_exit;
+ self->vars = self->_vars_stack;
+ self->vars->index_files = h2o_file_default_index_files;
+
+ h2o_configurator_define_command(&self->super, "file.dir", H2O_CONFIGURATOR_FLAG_PATH | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR |
+ H2O_CONFIGURATOR_FLAG_DEFERRED,
+ on_config_dir);
+ h2o_configurator_define_command(&self->super, "file.file", H2O_CONFIGURATOR_FLAG_PATH | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR |
+ H2O_CONFIGURATOR_FLAG_DEFERRED,
+ on_config_file);
+ h2o_configurator_define_command(&self->super, "file.index",
+ (H2O_CONFIGURATOR_FLAG_ALL_LEVELS & ~H2O_CONFIGURATOR_FLAG_EXTENSION) |
+ H2O_CONFIGURATOR_FLAG_EXPECT_SEQUENCE,
+ on_config_index);
+ h2o_configurator_define_command(&self->super, "file.etag",
+ (H2O_CONFIGURATOR_FLAG_ALL_LEVELS & ~H2O_CONFIGURATOR_FLAG_EXTENSION) |
+ H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
+ on_config_etag);
+ h2o_configurator_define_command(&self->super, "file.send-compressed",
+ (H2O_CONFIGURATOR_FLAG_ALL_LEVELS & ~H2O_CONFIGURATOR_FLAG_EXTENSION) |
+ H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
+ on_config_send_compressed);
+ h2o_configurator_define_command(&self->super, "file.send-gzip",
+ (H2O_CONFIGURATOR_FLAG_ALL_LEVELS & ~H2O_CONFIGURATOR_FLAG_EXTENSION) |
+ H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
+ on_config_send_compressed);
+ h2o_configurator_define_command(&self->super, "file.dirlisting",
+ (H2O_CONFIGURATOR_FLAG_ALL_LEVELS & ~H2O_CONFIGURATOR_FLAG_EXTENSION) |
+ H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
+ on_config_dir_listing);
+}
diff --git a/debian/vendor-h2o/lib/handler/configurator/headers.c b/debian/vendor-h2o/lib/handler/configurator/headers.c
new file mode 100644
index 0000000..68536c0
--- /dev/null
+++ b/debian/vendor-h2o/lib/handler/configurator/headers.c
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2015 DeNA Co., Ltd., Kazuho Oku
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+#include <string.h>
+#include "h2o.h"
+#include "h2o/configurator.h"
+
+struct headers_configurator_t {
+ h2o_configurator_t super;
+ h2o_headers_command_t **cmds, *_cmd_stack[H2O_CONFIGURATOR_NUM_LEVELS + 1];
+};
+
+static int on_config_enter(h2o_configurator_t *_self, h2o_configurator_context_t *ctx, yoml_t *node)
+{
+ struct headers_configurator_t *self = (void *)_self;
+
+ self->cmds[1] = self->cmds[0];
+ if (self->cmds[1] != NULL)
+ h2o_mem_addref_shared(self->cmds[1]);
+
+ ++self->cmds;
+ return 0;
+}
+
+static int on_config_exit(h2o_configurator_t *_self, h2o_configurator_context_t *ctx, yoml_t *node)
+{
+ struct headers_configurator_t *self = (void *)_self;
+
+ if (ctx->pathconf != NULL && *self->cmds != NULL) {
+ if (*self->cmds != NULL)
+ h2o_mem_addref_shared(*self->cmds);
+ h2o_headers_register(ctx->pathconf, *self->cmds);
+ }
+
+ if (*self->cmds != NULL)
+ h2o_mem_release_shared(*self->cmds);
+ --self->cmds;
+ return 0;
+}
+
+static h2o_headers_command_t **get_headers_commands(h2o_configurator_t *_self)
+{
+ struct headers_configurator_t *self = (void *)_self;
+ return self->cmds;
+}
+
+void h2o_headers_register_configurator(h2o_globalconf_t *conf)
+{
+ struct headers_configurator_t *c = (void *)h2o_configurator_create(conf, sizeof(*c));
+
+ c->super.enter = on_config_enter;
+ c->super.exit = on_config_exit;
+
+ h2o_configurator_define_headers_commands(conf, &c->super, "header", get_headers_commands);
+ c->cmds = c->_cmd_stack;
+}
diff --git a/debian/vendor-h2o/lib/handler/configurator/headers_util.c b/debian/vendor-h2o/lib/handler/configurator/headers_util.c
new file mode 100644
index 0000000..c05b9b7
--- /dev/null
+++ b/debian/vendor-h2o/lib/handler/configurator/headers_util.c
@@ -0,0 +1,143 @@
+#include "h2o.h"
+#include "h2o/configurator.h"
+
+struct headers_util_configurator_t {
+ h2o_configurator_t super;
+ h2o_configurator_t *child;
+ h2o_configurator_get_headers_commands_cb get_commands;
+};
+
+static int extract_name(const char *src, size_t len, h2o_iovec_t **_name)
+{
+ h2o_iovec_t name;
+ const h2o_token_t *name_token;
+
+ name = h2o_str_stripws(src, len);
+ if (name.len == 0)
+ return -1;
+
+ name = h2o_strdup(NULL, name.base, name.len);
+ h2o_strtolower(name.base, name.len);
+
+ if ((name_token = h2o_lookup_token(name.base, name.len)) != NULL) {
+ *_name = (h2o_iovec_t *)&name_token->buf;
+ free(name.base);
+ } else {
+ *_name = h2o_mem_alloc(sizeof(**_name));
+ **_name = name;
+ }
+
+ return 0;
+}
+
+static int extract_name_value(const char *src, h2o_iovec_t **name, h2o_iovec_t *value)
+{
+ const char *colon = strchr(src, ':');
+
+ if (colon == NULL)
+ return -1;
+
+ if (extract_name(src, colon - src, name) != 0)
+ return -1;
+ *value = h2o_str_stripws(colon + 1, strlen(colon + 1));
+ *value = h2o_strdup(NULL, value->base, value->len);
+
+ return 0;
+}
+
+static int add_cmd(h2o_configurator_command_t *cmd, yoml_t *node, int cmd_id, h2o_iovec_t *name, h2o_iovec_t value,
+ h2o_headers_command_t **cmds)
+{
+ if (h2o_iovec_is_token(name)) {
+ const h2o_token_t *token = (void *)name;
+ if (h2o_headers_is_prohibited_name(token)) {
+ h2o_configurator_errprintf(cmd, node, "the named header cannot be rewritten");
+ return -1;
+ }
+ }
+
+ h2o_headers_append_command(cmds, cmd_id, name, value);
+ return 0;
+}
+
+static int on_config_header_2arg(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, int cmd_id, yoml_t *node,
+ h2o_headers_command_t **headers_cmds)
+{
+ h2o_iovec_t *name, value;
+
+ if (extract_name_value(node->data.scalar, &name, &value) != 0) {
+ h2o_configurator_errprintf(cmd, node, "failed to parse the value; should be in form of `name: value`");
+ return -1;
+ }
+ if (add_cmd(cmd, node, cmd_id, name, value, headers_cmds) != 0) {
+ if (!h2o_iovec_is_token(name))
+ free(name->base);
+ free(value.base);
+ return -1;
+ }
+ return 0;
+}
+
+static int on_config_header_unset(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
+{
+ h2o_iovec_t *name;
+ struct headers_util_configurator_t *self = (void *)cmd->configurator;
+
+ if (extract_name(node->data.scalar, strlen(node->data.scalar), &name) != 0) {
+ h2o_configurator_errprintf(cmd, node, "invalid header name");
+ return -1;
+ }
+ if (add_cmd(cmd, node, H2O_HEADERS_CMD_UNSET, name, (h2o_iovec_t){NULL}, self->get_commands(self->child)) != 0) {
+ if (!h2o_iovec_is_token(name))
+ free(name->base);
+ return -1;
+ }
+ return 0;
+}
+
+#define DEFINE_2ARG(fn, cmd_id) \
+ static int fn(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node) \
+ { \
+ struct headers_util_configurator_t *self = (void *)cmd->configurator; \
+ return on_config_header_2arg(cmd, ctx, cmd_id, node, self->get_commands(self->child)); \
+ }
+
+DEFINE_2ARG(on_config_header_add, H2O_HEADERS_CMD_ADD)
+DEFINE_2ARG(on_config_header_append, H2O_HEADERS_CMD_APPEND)
+DEFINE_2ARG(on_config_header_merge, H2O_HEADERS_CMD_MERGE)
+DEFINE_2ARG(on_config_header_set, H2O_HEADERS_CMD_SET)
+DEFINE_2ARG(on_config_header_setifempty, H2O_HEADERS_CMD_SETIFEMPTY)
+
+#undef DEFINE_2ARG
+
+void h2o_configurator_define_headers_commands(h2o_globalconf_t *global_conf, h2o_configurator_t *conf, const char *prefix,
+ h2o_configurator_get_headers_commands_cb get_commands)
+{
+ struct headers_util_configurator_t *c = (void *)h2o_configurator_create(global_conf, sizeof(*c));
+ c->child = conf;
+ c->get_commands = get_commands;
+ size_t prefix_len = strlen(prefix);
+
+#define DEFINE_CMD_NAME(name, suffix) \
+ char *name = h2o_mem_alloc(prefix_len + sizeof(suffix)); \
+ memcpy(name, prefix, prefix_len); \
+ memcpy(name + prefix_len, suffix, sizeof(suffix))
+
+ DEFINE_CMD_NAME(add_directive, ".add");
+ DEFINE_CMD_NAME(append_directive, ".append");
+ DEFINE_CMD_NAME(merge_directive, ".merge");
+ DEFINE_CMD_NAME(set_directive, ".set");
+ DEFINE_CMD_NAME(setifempty_directive, ".setifempty");
+ DEFINE_CMD_NAME(unset_directive, ".unset");
+#undef DEFINE_CMD_NAME
+
+#define DEFINE_CMD(name, cb) \
+ h2o_configurator_define_command(&c->super, name, H2O_CONFIGURATOR_FLAG_ALL_LEVELS | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR, cb)
+ DEFINE_CMD(add_directive, on_config_header_add);
+ DEFINE_CMD(append_directive, on_config_header_append);
+ DEFINE_CMD(merge_directive, on_config_header_merge);
+ DEFINE_CMD(set_directive, on_config_header_set);
+ DEFINE_CMD(setifempty_directive, on_config_header_setifempty);
+ DEFINE_CMD(unset_directive, on_config_header_unset);
+#undef DEFINE_CMD
+}
diff --git a/debian/vendor-h2o/lib/handler/configurator/http2_debug_state.c b/debian/vendor-h2o/lib/handler/configurator/http2_debug_state.c
new file mode 100644
index 0000000..419da9d
--- /dev/null
+++ b/debian/vendor-h2o/lib/handler/configurator/http2_debug_state.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2016 DeNA Co., Ltd., Ichito Nagata
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+#include "h2o.h"
+#include "h2o/configurator.h"
+
+static int on_config_debug_state(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
+{
+ switch (h2o_configurator_get_one_of(cmd, node, "minimum,hpack")) {
+ case 0: /* minimum */
+ h2o_http2_debug_state_register(ctx->hostconf, 0);
+ return 0;
+ case 1: /* with hpack state*/
+ h2o_http2_debug_state_register(ctx->hostconf, 1);
+ return 0;
+ default: /* error */
+ return -1;
+ }
+}
+
+void h2o_http2_debug_state_register_configurator(h2o_globalconf_t *conf)
+{
+ struct st_h2o_configurator_t *c = (void *)h2o_configurator_create(conf, sizeof(*c));
+
+ h2o_configurator_define_command(c, "http2-debug-state", H2O_CONFIGURATOR_FLAG_HOST | H2O_CONFIGURATOR_FLAG_DEFERRED |
+ H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
+ on_config_debug_state);
+}
diff --git a/debian/vendor-h2o/lib/handler/configurator/mruby.c b/debian/vendor-h2o/lib/handler/configurator/mruby.c
new file mode 100644
index 0000000..1cef8f4
--- /dev/null
+++ b/debian/vendor-h2o/lib/handler/configurator/mruby.c
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2015 DeNA Co., Ltd., Kazuho Oku, Ryosuke Matsumoto
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+#include <errno.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "h2o.h"
+#include "h2o/configurator.h"
+#include "h2o/mruby_.h"
+
+struct mruby_configurator_t {
+ h2o_configurator_t super;
+ h2o_mruby_config_vars_t *vars;
+ h2o_mruby_config_vars_t _vars_stack[H2O_CONFIGURATOR_NUM_LEVELS + 1];
+ mrb_state *mrb; /* will be lazily initialized */
+};
+
+static int compile_test(mrb_state *mrb, h2o_mruby_config_vars_t *config, char *errbuf)
+{
+ mrb_value result = h2o_mruby_compile_code(mrb, config, errbuf);
+ int ok = !mrb_nil_p(result);
+ return ok;
+}
+
+static mrb_state *get_mrb(struct mruby_configurator_t *self)
+{
+ if (self->mrb == NULL) {
+ self->mrb = mrb_open();
+ if (self->mrb == NULL) {
+ fprintf(stderr, "%s: no memory\n", H2O_MRUBY_MODULE_NAME);
+ abort();
+ }
+ h2o_mruby_setup_globals(self->mrb);
+ }
+ return self->mrb;
+}
+
+static int on_config_mruby_handler(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
+{
+ struct mruby_configurator_t *self = (void *)cmd->configurator;
+
+ /* set source */
+ self->vars->source = h2o_strdup(NULL, node->data.scalar, SIZE_MAX);
+ self->vars->path = node->filename;
+ self->vars->lineno = (int)node->line + 1;
+
+ /* check if there is any error in source */
+ char errbuf[1024];
+ if (!compile_test(get_mrb(self), self->vars, errbuf)) {
+ h2o_configurator_errprintf(cmd, node, "ruby compile error:%s", errbuf);
+ return -1;
+ }
+
+ /* register */
+ h2o_mruby_register(ctx->pathconf, self->vars);
+
+ return 0;
+}
+
+static int on_config_mruby_handler_file(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
+{
+ struct mruby_configurator_t *self = (void *)cmd->configurator;
+ FILE *fp = NULL;
+ h2o_iovec_t buf = {NULL};
+ int ret = -1;
+
+ /* open and read file */
+ if ((fp = fopen(node->data.scalar, "rt")) == NULL) {
+ h2o_configurator_errprintf(cmd, node, "failed to open file: %s:%s", node->data.scalar, strerror(errno));
+ goto Exit;
+ }
+ while (!feof(fp)) {
+ buf.base = h2o_mem_realloc(buf.base, buf.len + 65536);
+ buf.len += fread(buf.base + buf.len, 1, 65536, fp);
+ if (ferror(fp)) {
+ h2o_configurator_errprintf(cmd, node, "I/O error occurred while reading file:%s:%s", node->data.scalar,
+ strerror(errno));
+ goto Exit;
+ }
+ }
+
+ /* set source */
+ self->vars->source = buf;
+ buf.base = NULL;
+ self->vars->path = node->data.scalar; /* the value is retained until the end of the configuration phase */
+ self->vars->lineno = 0;
+
+ /* check if there is any error in source */
+ char errbuf[1024];
+ if (!compile_test(get_mrb(self), self->vars, errbuf)) {
+ h2o_configurator_errprintf(cmd, node, "failed to compile file:%s:%s", node->data.scalar, errbuf);
+ goto Exit;
+ }
+
+ /* register */
+ h2o_mruby_register(ctx->pathconf, self->vars);
+
+ ret = 0;
+
+Exit:
+ if (fp != NULL)
+ fclose(fp);
+ if (buf.base != NULL)
+ free(buf.base);
+ return ret;
+}
+
+static int on_config_mruby_handler_path(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
+{
+ h2o_configurator_errprintf(cmd, node, "the command has been removed; see https://github.com/h2o/h2o/pull/467");
+ return -1;
+}
+
+static int on_config_enter(h2o_configurator_t *_self, h2o_configurator_context_t *ctx, yoml_t *node)
+{
+ struct mruby_configurator_t *self = (void *)_self;
+
+ memcpy(self->vars + 1, self->vars, sizeof(*self->vars));
+ ++self->vars;
+ return 0;
+}
+
+static int on_config_exit(h2o_configurator_t *_self, h2o_configurator_context_t *ctx, yoml_t *node)
+{
+ struct mruby_configurator_t *self = (void *)_self;
+
+ /* free if the to-be-exitted frame level contains a different source */
+ if (self->vars[-1].source.base != self->vars[0].source.base)
+ free(self->vars->source.base);
+
+ --self->vars;
+
+ /* release mrb only when global configuration exited */
+ if (self->mrb != NULL && ctx->parent == NULL) {
+ mrb_close(self->mrb);
+ self->mrb = NULL;
+ }
+
+ return 0;
+}
+
+void h2o_mruby_register_configurator(h2o_globalconf_t *conf)
+{
+ struct mruby_configurator_t *c = (void *)h2o_configurator_create(conf, sizeof(*c));
+
+ c->vars = c->_vars_stack;
+ c->super.enter = on_config_enter;
+ c->super.exit = on_config_exit;
+
+ h2o_configurator_define_command(&c->super, "mruby.handler", H2O_CONFIGURATOR_FLAG_PATH | H2O_CONFIGURATOR_FLAG_DEFERRED |
+ H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
+ on_config_mruby_handler);
+ h2o_configurator_define_command(&c->super, "mruby.handler-file", H2O_CONFIGURATOR_FLAG_PATH | H2O_CONFIGURATOR_FLAG_DEFERRED |
+ H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
+ on_config_mruby_handler_file);
+ h2o_configurator_define_command(&c->super, "mruby.handler_path", H2O_CONFIGURATOR_FLAG_PATH | H2O_CONFIGURATOR_FLAG_DEFERRED,
+ on_config_mruby_handler_path);
+}
diff --git a/debian/vendor-h2o/lib/handler/configurator/proxy.c b/debian/vendor-h2o/lib/handler/configurator/proxy.c
new file mode 100644
index 0000000..cfc9cbf
--- /dev/null
+++ b/debian/vendor-h2o/lib/handler/configurator/proxy.c
@@ -0,0 +1,392 @@
+/*
+ * Copyright (c) 2014 DeNA Co., Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+#include <inttypes.h>
+#include <errno.h>
+#include <stdio.h>
+#include <openssl/crypto.h>
+#include <openssl/err.h>
+#include <openssl/ssl.h>
+#include "h2o.h"
+#include "h2o/configurator.h"
+
+struct proxy_configurator_t {
+ h2o_configurator_t super;
+ h2o_proxy_config_vars_t *vars;
+ h2o_proxy_config_vars_t _vars_stack[H2O_CONFIGURATOR_NUM_LEVELS + 1];
+};
+
+static int on_config_timeout_io(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
+{
+ struct proxy_configurator_t *self = (void *)cmd->configurator;
+ return h2o_configurator_scanf(cmd, node, "%" SCNu64, &self->vars->io_timeout);
+}
+
+static int on_config_timeout_keepalive(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
+{
+ struct proxy_configurator_t *self = (void *)cmd->configurator;
+ return h2o_configurator_scanf(cmd, node, "%" SCNu64, &self->vars->keepalive_timeout);
+}
+
+static int on_config_preserve_host(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
+{
+ struct proxy_configurator_t *self = (void *)cmd->configurator;
+ ssize_t ret = h2o_configurator_get_one_of(cmd, node, "OFF,ON");
+ if (ret == -1)
+ return -1;
+ self->vars->preserve_host = (int)ret;
+ return 0;
+}
+
+static int on_config_proxy_protocol(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
+{
+ struct proxy_configurator_t *self = (void *)cmd->configurator;
+ ssize_t ret = h2o_configurator_get_one_of(cmd, node, "OFF,ON");
+ if (ret == -1)
+ return -1;
+ self->vars->use_proxy_protocol = (int)ret;
+ return 0;
+}
+
+static int on_config_websocket_timeout(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
+{
+ struct proxy_configurator_t *self = (void *)cmd->configurator;
+ return h2o_configurator_scanf(cmd, node, "%" SCNu64, &self->vars->websocket.timeout);
+}
+
+static int on_config_websocket(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
+{
+ struct proxy_configurator_t *self = (void *)cmd->configurator;
+ ssize_t ret = h2o_configurator_get_one_of(cmd, node, "OFF,ON");
+ if (ret == -1)
+ return -1;
+ self->vars->websocket.enabled = (int)ret;
+ return 0;
+}
+
+static SSL_CTX *create_ssl_ctx(void)
+{
+ SSL_CTX *ctx = SSL_CTX_new(SSLv23_client_method());
+ SSL_CTX_set_options(ctx, SSL_CTX_get_options(ctx) | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
+ return ctx;
+}
+
+static h2o_cache_t *create_ssl_session_cache(size_t capacity, uint64_t duration)
+{
+ return h2o_cache_create(H2O_CACHE_FLAG_MULTITHREADED, capacity, duration, h2o_socket_ssl_destroy_session_cache_entry);
+}
+
+static void update_ssl_ctx(SSL_CTX **ctx, X509_STORE *cert_store, int verify_mode, h2o_cache_t **session_cache)
+{
+ assert(*ctx != NULL);
+
+ /* inherit the properties that weren't specified */
+ if (cert_store == NULL)
+ cert_store = SSL_CTX_get_cert_store(*ctx);
+ X509_STORE_up_ref(cert_store);
+ if (verify_mode == -1)
+ verify_mode = SSL_CTX_get_verify_mode(*ctx);
+ h2o_cache_t *new_session_cache;
+ if (session_cache == NULL) {
+ h2o_cache_t *current = h2o_socket_ssl_get_session_cache(*ctx);
+ new_session_cache =
+ current == NULL ? NULL : create_ssl_session_cache(h2o_cache_get_capacity(current), h2o_cache_get_duration(current));
+ } else {
+ new_session_cache = *session_cache;
+ }
+
+ /* free the existing context */
+ if (*ctx != NULL)
+ SSL_CTX_free(*ctx);
+
+ /* create new ctx */
+ *ctx = create_ssl_ctx();
+ SSL_CTX_set_cert_store(*ctx, cert_store);
+ SSL_CTX_set_verify(*ctx, verify_mode, NULL);
+ if (new_session_cache != NULL)
+ h2o_socket_ssl_set_session_cache(*ctx, new_session_cache);
+}
+
+static int on_config_ssl_verify_peer(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
+{
+ struct proxy_configurator_t *self = (void *)cmd->configurator;
+ ssize_t ret = h2o_configurator_get_one_of(cmd, node, "OFF,ON");
+ if (ret == -1)
+ return -1;
+
+ update_ssl_ctx(&self->vars->ssl_ctx, NULL, ret != 0 ? SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT : SSL_VERIFY_NONE,
+ NULL);
+
+ return 0;
+}
+
+static int on_config_ssl_cafile(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
+{
+ struct proxy_configurator_t *self = (void *)cmd->configurator;
+ X509_STORE *store = X509_STORE_new();
+ int ret = -1;
+
+ if (X509_STORE_load_locations(store, node->data.scalar, NULL) == 1) {
+ update_ssl_ctx(&self->vars->ssl_ctx, store, -1, NULL);
+ ret = 0;
+ } else {
+ h2o_configurator_errprintf(cmd, node, "failed to load certificates file:%s", node->data.scalar);
+ ERR_print_errors_fp(stderr);
+ }
+
+ X509_STORE_free(store);
+ return ret;
+}
+
+static int on_config_ssl_session_cache(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
+{
+ struct proxy_configurator_t *self = (void *)cmd->configurator;
+ size_t capacity = 0;
+ uint64_t duration = 0;
+ h2o_cache_t *current_cache = h2o_socket_ssl_get_session_cache(self->vars->ssl_ctx);
+
+ switch (node->type) {
+ case YOML_TYPE_SCALAR:
+ if (strcasecmp(node->data.scalar, "OFF") == 0) {
+ if (current_cache != NULL) {
+ /* set the cache NULL */
+ h2o_cache_t *empty_cache = NULL;
+ update_ssl_ctx(&self->vars->ssl_ctx, NULL, -1, &empty_cache);
+ }
+ return 0;
+ } else if (strcasecmp(node->data.scalar, "ON") == 0) {
+ /* use default values */
+ capacity = H2O_DEFAULT_PROXY_SSL_SESSION_CACHE_CAPACITY;
+ duration = H2O_DEFAULT_PROXY_SSL_SESSION_CACHE_DURATION;
+ } else {
+ h2o_configurator_errprintf(cmd, node, "scalar argument must be either of: `OFF`, `ON`");
+ return -1;
+ }
+ break;
+ case YOML_TYPE_MAPPING: {
+ size_t i;
+ for (i = 0; i != node->data.mapping.size; ++i) {
+ yoml_t *key = node->data.mapping.elements[i].key;
+ yoml_t *value = node->data.mapping.elements[i].value;
+ if (key->type != YOML_TYPE_SCALAR) {
+ h2o_configurator_errprintf(cmd, key, "key must be a scalar");
+ return -1;
+ }
+ if (strcasecmp(key->data.scalar, "capacity") == 0) {
+ if (h2o_configurator_scanf(cmd, value, "%zu", &capacity) != 0)
+ return -1;
+ if (capacity == 0) {
+ h2o_configurator_errprintf(cmd, key, "capacity must be greater than zero");
+ return -1;
+ }
+ } else if (strcasecmp(key->data.scalar, "lifetime") == 0) {
+ unsigned lifetime = 0;
+ if (h2o_configurator_scanf(cmd, value, "%u", &lifetime) != 0)
+ return -1;
+ if (lifetime == 0) {
+ h2o_configurator_errprintf(cmd, key, "lifetime must be greater than zero");
+ return -1;
+ }
+ duration = (uint64_t)lifetime * 1000;
+ } else {
+ h2o_configurator_errprintf(cmd, key, "key must be either of: `capacity`, `lifetime`");
+ return -1;
+ }
+ }
+ if (capacity == 0 || duration == 0) {
+ h2o_configurator_errprintf(cmd, node, "`capacity` and `lifetime` are required");
+ return -1;
+ }
+ } break;
+ default:
+ h2o_configurator_errprintf(cmd, node, "node must be a scalar or a mapping");
+ return -1;
+ }
+
+ if (current_cache != NULL) {
+ size_t current_capacity = h2o_cache_get_capacity(current_cache);
+ uint64_t current_duration = h2o_cache_get_duration(current_cache);
+ if (capacity == current_capacity && duration == current_duration) {
+ /* parameters aren't changed, so reuse it */
+ return 0;
+ }
+ }
+
+ h2o_cache_t *new_cache = create_ssl_session_cache(capacity, duration);
+ update_ssl_ctx(&self->vars->ssl_ctx, NULL, -1, &new_cache);
+ return 0;
+}
+
+static int on_config_reverse_url(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
+{
+ struct proxy_configurator_t *self = (void *)cmd->configurator;
+ h2o_url_t parsed;
+
+ if (h2o_url_parse(node->data.scalar, SIZE_MAX, &parsed) != 0) {
+ h2o_configurator_errprintf(cmd, node, "failed to parse URL: %s\n", node->data.scalar);
+ return -1;
+ }
+ if (self->vars->keepalive_timeout != 0 && self->vars->use_proxy_protocol) {
+ h2o_configurator_errprintf(cmd, node, "please either set `proxy.use-proxy-protocol` to `OFF` or disable keep-alive by "
+ "setting `proxy.timeout.keepalive` to zero; the features are mutually exclusive");
+ return -1;
+ }
+
+ if (self->vars->headers_cmds != NULL)
+ h2o_mem_addref_shared(self->vars->headers_cmds);
+
+ /* register */
+ h2o_proxy_register_reverse_proxy(ctx->pathconf, &parsed, self->vars);
+
+ return 0;
+}
+
+static int on_config_emit_x_forwarded_headers(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
+{
+ ssize_t ret = h2o_configurator_get_one_of(cmd, node, "OFF,ON");
+ if (ret == -1)
+ return -1;
+ ctx->globalconf->proxy.emit_x_forwarded_headers = (int)ret;
+ return 0;
+}
+
+static int on_config_emit_via_header(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
+{
+ ssize_t ret = h2o_configurator_get_one_of(cmd, node, "OFF,ON");
+ if (ret == -1)
+ return -1;
+ ctx->globalconf->proxy.emit_via_header = (int)ret;
+ return 0;
+}
+
+static int on_config_preserve_x_forwarded_proto(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
+{
+ ssize_t ret = h2o_configurator_get_one_of(cmd, node, "OFF,ON");
+ if (ret == -1)
+ return -1;
+ ctx->globalconf->proxy.preserve_x_forwarded_proto = (int)ret;
+ return 0;
+}
+
+static int on_config_enter(h2o_configurator_t *_self, h2o_configurator_context_t *ctx, yoml_t *node)
+{
+ struct proxy_configurator_t *self = (void *)_self;
+
+ memcpy(self->vars + 1, self->vars, sizeof(*self->vars));
+ if (self->vars[1].headers_cmds != NULL)
+ h2o_mem_addref_shared(self->vars[1].headers_cmds);
+ ++self->vars;
+
+ if (ctx->pathconf == NULL && ctx->hostconf == NULL) {
+ /* is global conf, setup the default SSL context */
+ self->vars->ssl_ctx = create_ssl_ctx();
+ char *ca_bundle = h2o_configurator_get_cmd_path("share/h2o/ca-bundle.crt");
+ if (SSL_CTX_load_verify_locations(self->vars->ssl_ctx, ca_bundle, NULL) != 1)
+ fprintf(stderr, "Warning: failed to load the default certificates file at %s. Proxying to HTTPS servers may fail.\n",
+ ca_bundle);
+ free(ca_bundle);
+ SSL_CTX_set_verify(self->vars->ssl_ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);
+ h2o_cache_t *ssl_session_cache =
+ create_ssl_session_cache(H2O_DEFAULT_PROXY_SSL_SESSION_CACHE_CAPACITY, H2O_DEFAULT_PROXY_SSL_SESSION_CACHE_DURATION);
+ h2o_socket_ssl_set_session_cache(self->vars->ssl_ctx, ssl_session_cache);
+ } else {
+ SSL_CTX_up_ref(self->vars->ssl_ctx);
+ }
+
+ return 0;
+}
+
+static int on_config_exit(h2o_configurator_t *_self, h2o_configurator_context_t *ctx, yoml_t *node)
+{
+ struct proxy_configurator_t *self = (void *)_self;
+
+ if (ctx->pathconf == NULL && ctx->hostconf == NULL) {
+ /* is global conf */
+ ctx->globalconf->proxy.io_timeout = self->vars->io_timeout;
+ ctx->globalconf->proxy.ssl_ctx = self->vars->ssl_ctx;
+ } else {
+ SSL_CTX_free(self->vars->ssl_ctx);
+ }
+
+ if (self->vars->headers_cmds != NULL)
+ h2o_mem_release_shared(self->vars->headers_cmds);
+
+ --self->vars;
+ return 0;
+}
+
+static h2o_headers_command_t **get_headers_commands(h2o_configurator_t *_self)
+{
+ struct proxy_configurator_t *self = (void *)_self;
+ return &self->vars->headers_cmds;
+}
+
+void h2o_proxy_register_configurator(h2o_globalconf_t *conf)
+{
+ struct proxy_configurator_t *c = (void *)h2o_configurator_create(conf, sizeof(*c));
+
+ /* set default vars */
+ c->vars = c->_vars_stack;
+ c->vars->io_timeout = H2O_DEFAULT_PROXY_IO_TIMEOUT;
+ c->vars->keepalive_timeout = 2000;
+ c->vars->websocket.enabled = 0; /* have websocket proxying disabled by default; until it becomes non-experimental */
+ c->vars->websocket.timeout = H2O_DEFAULT_PROXY_WEBSOCKET_TIMEOUT;
+
+ /* setup handlers */
+ c->super.enter = on_config_enter;
+ c->super.exit = on_config_exit;
+ h2o_configurator_define_command(
+ &c->super, "proxy.reverse.url",
+ H2O_CONFIGURATOR_FLAG_PATH | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR | H2O_CONFIGURATOR_FLAG_DEFERRED, on_config_reverse_url);
+ h2o_configurator_define_command(&c->super, "proxy.preserve-host",
+ H2O_CONFIGURATOR_FLAG_ALL_LEVELS | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
+ on_config_preserve_host);
+ h2o_configurator_define_command(&c->super, "proxy.proxy-protocol",
+ H2O_CONFIGURATOR_FLAG_ALL_LEVELS | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
+ on_config_proxy_protocol);
+ h2o_configurator_define_command(&c->super, "proxy.timeout.io",
+ H2O_CONFIGURATOR_FLAG_ALL_LEVELS | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR, on_config_timeout_io);
+ h2o_configurator_define_command(&c->super, "proxy.timeout.keepalive",
+ H2O_CONFIGURATOR_FLAG_ALL_LEVELS | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
+ on_config_timeout_keepalive);
+ h2o_configurator_define_command(&c->super, "proxy.websocket",
+ H2O_CONFIGURATOR_FLAG_ALL_LEVELS | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR, on_config_websocket);
+ h2o_configurator_define_command(&c->super, "proxy.websocket.timeout",
+ H2O_CONFIGURATOR_FLAG_ALL_LEVELS | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
+ on_config_websocket_timeout);
+ h2o_configurator_define_command(&c->super, "proxy.ssl.verify-peer",
+ H2O_CONFIGURATOR_FLAG_ALL_LEVELS | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
+ on_config_ssl_verify_peer);
+ h2o_configurator_define_command(&c->super, "proxy.ssl.cafile",
+ H2O_CONFIGURATOR_FLAG_ALL_LEVELS | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR, on_config_ssl_cafile);
+ h2o_configurator_define_command(&c->super, "proxy.ssl.session-cache", H2O_CONFIGURATOR_FLAG_ALL_LEVELS,
+ on_config_ssl_session_cache);
+ h2o_configurator_define_command(&c->super, "proxy.preserve-x-forwarded-proto",
+ H2O_CONFIGURATOR_FLAG_GLOBAL | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
+ on_config_preserve_x_forwarded_proto);
+ h2o_configurator_define_command(&c->super, "proxy.emit-x-forwarded-headers",
+ H2O_CONFIGURATOR_FLAG_GLOBAL | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
+ on_config_emit_x_forwarded_headers);
+ h2o_configurator_define_command(&c->super, "proxy.emit-via-header",
+ H2O_CONFIGURATOR_FLAG_GLOBAL | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
+ on_config_emit_via_header);
+ h2o_configurator_define_headers_commands(conf, &c->super, "proxy.header", get_headers_commands);
+}
diff --git a/debian/vendor-h2o/lib/handler/configurator/redirect.c b/debian/vendor-h2o/lib/handler/configurator/redirect.c
new file mode 100644
index 0000000..4ebbb99
--- /dev/null
+++ b/debian/vendor-h2o/lib/handler/configurator/redirect.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2015 DeNA Co., Ltd., Kazuho Oku
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+#include "h2o.h"
+#include "h2o/configurator.h"
+
+static int on_config(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
+{
+ const char *dest;
+ int status = 302; /* default is temporary redirect */
+ int internal = 0; /* default is external redirect */
+ yoml_t *t;
+
+ switch (node->type) {
+ case YOML_TYPE_SCALAR:
+ dest = node->data.scalar;
+ break;
+ case YOML_TYPE_MAPPING:
+ if ((t = yoml_get(node, "url")) == NULL) {
+ h2o_configurator_errprintf(cmd, node, "mandatory property `url` is missing");
+ return -1;
+ }
+ if (t->type != YOML_TYPE_SCALAR) {
+ h2o_configurator_errprintf(cmd, t, "property `url` must be a string");
+ return -1;
+ }
+ dest = t->data.scalar;
+ if ((t = yoml_get(node, "status")) == NULL) {
+ h2o_configurator_errprintf(cmd, node, "mandatory property `status` is missing");
+ return -1;
+ }
+ if (h2o_configurator_scanf(cmd, t, "%d", &status) != 0)
+ return -1;
+ if (!(300 <= status && status <= 399)) {
+ h2o_configurator_errprintf(cmd, t, "value of property `status` should be within 300 to 399");
+ return -1;
+ }
+ if ((t = yoml_get(node, "internal")) != NULL) {
+ if ((internal = (int)h2o_configurator_get_one_of(cmd, t, "NO,YES")) == -1)
+ return -1;
+ }
+ break;
+ default:
+ h2o_configurator_errprintf(cmd, node, "value must be a string or a mapping");
+ return -1;
+ }
+
+ h2o_redirect_register(ctx->pathconf, internal, status, dest);
+
+ return 0;
+}
+
+void h2o_redirect_register_configurator(h2o_globalconf_t *conf)
+{
+ h2o_configurator_t *c = h2o_configurator_create(conf, sizeof(*c));
+
+ h2o_configurator_define_command(c, "redirect", H2O_CONFIGURATOR_FLAG_PATH | H2O_CONFIGURATOR_FLAG_DEFERRED, on_config);
+}
diff --git a/debian/vendor-h2o/lib/handler/configurator/reproxy.c b/debian/vendor-h2o/lib/handler/configurator/reproxy.c
new file mode 100644
index 0000000..21650e4
--- /dev/null
+++ b/debian/vendor-h2o/lib/handler/configurator/reproxy.c
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2015 Daisuke Maki, DeNA Co., Ltd., Kazuho Oku
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+#include <inttypes.h>
+#include "h2o.h"
+#include "h2o/configurator.h"
+
+struct config_t {
+ int enabled;
+};
+
+struct reproxy_configurator_t {
+ h2o_configurator_t super;
+ struct config_t *vars, _vars_stack[H2O_CONFIGURATOR_NUM_LEVELS + 1];
+};
+
+static int on_config_reproxy(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
+{
+ struct reproxy_configurator_t *self = (void *)cmd->configurator;
+
+ ssize_t ret = h2o_configurator_get_one_of(cmd, node, "OFF,ON");
+ if (ret == -1)
+ return -1;
+ self->vars->enabled = (int)ret;
+
+ return 0;
+}
+
+static int on_config_enter(h2o_configurator_t *_self, h2o_configurator_context_t *ctx, yoml_t *node)
+{
+ struct reproxy_configurator_t *self = (void *)_self;
+
+ self->vars[1] = self->vars[0];
+ ++self->vars;
+ return 0;
+}
+
+static int on_config_exit(h2o_configurator_t *_self, h2o_configurator_context_t *ctx, yoml_t *node)
+{
+ struct reproxy_configurator_t *self = (void *)_self;
+
+ if (ctx->pathconf != NULL && self->vars->enabled != 0)
+ h2o_reproxy_register(ctx->pathconf);
+
+ --self->vars;
+ return 0;
+}
+
+void h2o_reproxy_register_configurator(h2o_globalconf_t *conf)
+{
+ struct reproxy_configurator_t *c = (void *)h2o_configurator_create(conf, sizeof(*c));
+
+ /* set default vars */
+ c->vars = c->_vars_stack;
+
+ /* setup handlers */
+ c->super.enter = on_config_enter;
+ c->super.exit = on_config_exit;
+
+ /* reproxy: ON | OFF */
+ h2o_configurator_define_command(&c->super, "reproxy", H2O_CONFIGURATOR_FLAG_ALL_LEVELS | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
+ on_config_reproxy);
+}
diff --git a/debian/vendor-h2o/lib/handler/configurator/status.c b/debian/vendor-h2o/lib/handler/configurator/status.c
new file mode 100644
index 0000000..8645aa3
--- /dev/null
+++ b/debian/vendor-h2o/lib/handler/configurator/status.c
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2016 DeNA Co., Ltd., Kazuho Oku
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+#include "h2o.h"
+#include "h2o/configurator.h"
+
+static int on_config_status(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
+{
+ switch (h2o_configurator_get_one_of(cmd, node, "OFF,ON")) {
+ case 0: /* OFF */
+ return 0;
+ case 1: /* ON */
+ h2o_status_register(ctx->pathconf);
+ return 0;
+ default: /* error */
+ return -1;
+ }
+}
+
+struct st_status_configurator {
+ h2o_configurator_t super;
+ int stack;
+ int duration_stats;
+};
+
+static int on_config_duration_stats(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
+{
+ struct st_status_configurator *c = (void *)cmd->configurator;
+ ssize_t ret;
+ switch (ret = h2o_configurator_get_one_of(cmd, node, "OFF,ON")) {
+ case 0: /* OFF */
+ case 1: /* ON */
+ c->duration_stats = (int)ret;
+ return 0;
+ default: /* error */
+ return -1;
+ }
+}
+
+int on_enter_status(h2o_configurator_t *_conf, h2o_configurator_context_t *ctx, yoml_t *node)
+{
+ struct st_status_configurator *c = (void *)_conf;
+ c->stack++;
+ return 0;
+}
+
+int on_exit_status(h2o_configurator_t *_conf, h2o_configurator_context_t *ctx, yoml_t *node)
+{
+ struct st_status_configurator *c = (void *)_conf;
+ c->stack--;
+ if (!c->stack && c->duration_stats) {
+ h2o_duration_stats_register(ctx->globalconf);
+ }
+ return 0;
+}
+
+void h2o_status_register_configurator(h2o_globalconf_t *conf)
+{
+ struct st_status_configurator *c = (void *)h2o_configurator_create(conf, sizeof(*c));
+ c->super.enter = on_enter_status;
+ c->super.exit = on_exit_status;
+
+ h2o_configurator_define_command(&c->super, "status", H2O_CONFIGURATOR_FLAG_PATH | H2O_CONFIGURATOR_FLAG_DEFERRED |
+ H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
+ on_config_status);
+
+ h2o_configurator_define_command(&c->super, "duration-stats", H2O_CONFIGURATOR_FLAG_GLOBAL | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
+ on_config_duration_stats);
+}
diff --git a/debian/vendor-h2o/lib/handler/configurator/throttle_resp.c b/debian/vendor-h2o/lib/handler/configurator/throttle_resp.c
new file mode 100644
index 0000000..61431f7
--- /dev/null
+++ b/debian/vendor-h2o/lib/handler/configurator/throttle_resp.c
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2016 Justin Zhu
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+#include "h2o.h"
+#include "h2o/configurator.h"
+
+struct throttle_resp_config_vars_t {
+ int on;
+};
+
+struct throttle_resp_configurator_t {
+ h2o_configurator_t super;
+ struct throttle_resp_config_vars_t *vars, _vars_stack[H2O_CONFIGURATOR_NUM_LEVELS + 1];
+};
+
+static int on_config_throttle_resp(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
+{
+ struct throttle_resp_configurator_t *self = (void *)cmd->configurator;
+
+ if ((self->vars->on = (int)h2o_configurator_get_one_of(cmd, node, "OFF,ON")) == -1)
+ return -1;
+ return 0;
+}
+
+static int on_config_enter(h2o_configurator_t *configurator, h2o_configurator_context_t *ctx, yoml_t *node)
+{
+ struct throttle_resp_configurator_t *self = (void *)configurator;
+
+ ++self->vars;
+ self->vars[0] = self->vars[-1];
+ return 0;
+}
+
+static int on_config_exit(h2o_configurator_t *configurator, h2o_configurator_context_t *ctx, yoml_t *node)
+{
+ struct throttle_resp_configurator_t *self = (void *)configurator;
+
+ if (ctx->pathconf != NULL && self->vars->on)
+ h2o_throttle_resp_register(ctx->pathconf);
+
+ --self->vars;
+ return 0;
+}
+
+void h2o_throttle_resp_register_configurator(h2o_globalconf_t *conf)
+{
+ struct throttle_resp_configurator_t *c = (void *)h2o_configurator_create(conf, sizeof(*c));
+
+ c->super.enter = on_config_enter;
+ c->super.exit = on_config_exit;
+ h2o_configurator_define_command(&c->super, "throttle-response",
+ H2O_CONFIGURATOR_FLAG_ALL_LEVELS | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
+ on_config_throttle_resp);
+ c->vars = c->_vars_stack;
+}