Esempio n. 1
0
int main(int argc, char **argv)
{
    h2o_hostconf_t *hostconf;

    signal(SIGPIPE, SIG_IGN);

    h2o_config_init(&config);
    hostconf = h2o_config_register_host(&config, "default");
    register_handler(hostconf, "/post-test", post_test);
    register_handler(hostconf, "/chunked-test", chunked_test);
    h2o_file_register(h2o_config_register_path(hostconf, "/"), "examples/doc_root", NULL, NULL, 0);

#if 0 /* reproxy is not yet implemented */
    register_handler(hostconf, "/reproxy-test", reproxy_test);
    h2o_reproxy_register(hostconf);
#endif

#if H2O_USE_LIBUV
    uv_loop_t loop;
    uv_loop_init(&loop);
    h2o_context_init(&ctx, &loop, &config);
#else
    h2o_context_init(&ctx, h2o_evloop_create(), &config);
#endif

    /* disabled by default: uncomment the block below to use HTTPS instead of HTTP */
    /*
    if (setup_ssl("server.crt", "server.key") != 0)
        goto Error;
    */

    /* disabled by default: uncomment the line below to enable access logging */
    /* h2o_access_log_register(&config.default_host, "/dev/stdout", NULL); */

    if (create_listener() != 0) {
        fprintf(stderr, "failed to listen to 127.0.0.1:7890:%s\n", strerror(errno));
        goto Error;
    }

#if H2O_USE_LIBUV
    uv_run(ctx.loop, UV_RUN_DEFAULT);
#else
    while (h2o_evloop_run(ctx.loop) == 0)
        ;
#endif

Error:
    return 1;
}
void initialize_event_loop(bool is_main_thread,
                           global_data_t *global_data,
                           h2o_multithread_receiver_t *h2o_receiver,
                           event_loop_t *loop)
{
	h2o_socket_cb accept_cb = accept_connection;
	const config_t * const config = global_data->global_thread_data->config;

	memset(loop, 0, sizeof(*loop));
	h2o_context_init(&loop->h2o_ctx, h2o_evloop_create(), &global_data->h2o_config);
	loop->h2o_accept_ctx.ctx = &loop->h2o_ctx;
	loop->h2o_accept_ctx.hosts = global_data->h2o_config.hosts;

	if (global_data->ssl_ctx) {
		loop->h2o_accept_ctx.ssl_ctx = global_data->ssl_ctx;
		start_accept_polling(config, accept_connection, true, loop);
		// Assume that the majority of the connections use HTTPS,
		// so HTTP can take a few extra operations.
		accept_cb = accept_http_connection;
	}

	start_accept_polling(config, accept_cb, false, loop);
	h2o_multithread_register_receiver(loop->h2o_ctx.queue,
	                                  h2o_receiver,
	                                  process_messages);

	if (is_main_thread) {
		global_data->signals = h2o_evloop_socket_create(loop->h2o_ctx.loop,
		                                                global_data->signal_fd,
		                                                H2O_SOCKET_FLAG_DONT_READ);
		global_data->signals->data = loop;
		h2o_socket_read_start(global_data->signals, shutdown_server);
	}
}
Esempio n. 3
0
int main(int argc, char **argv)
{
    uv_loop_t *loop = uv_default_loop();
    uv_tcp_t listener;
    struct sockaddr_in sockaddr;
    h2o_handler_t ws_handler;
    int r;

    if ((r = uv_tcp_init(loop, &listener)) != 0) {
        fprintf(stderr, "uv_tcp_init:%s\n", uv_strerror(r));
        goto Error;
    }
    uv_ip4_addr("127.0.0.1", 7890, &sockaddr);
    if ((r = uv_tcp_bind(&listener, (struct sockaddr*)&sockaddr, sizeof(sockaddr))) != 0) {
        fprintf(stderr, "uv_tcp_bind:%s\n", uv_strerror(r));
        goto Error;
    }
    if ((r = uv_listen((uv_stream_t*)&listener, 128, on_connect)) != 0) {
        fprintf(stderr, "uv_listen:%s\n", uv_strerror(r));
        goto Error;
    }

    h2o_config_init(&config);
    memset(&ws_handler, 0, sizeof(ws_handler));
    ws_handler.on_req = on_req;
    h2o_linklist_insert(&config.default_host.handlers, &ws_handler._link);
    h2o_context_init(&ctx, loop, &config);
    //ssl_ctx = h2o_ssl_new_server_context("server.crt", "server.key", NULL);

    return uv_run(loop, UV_RUN_DEFAULT);

Error:
    return 1;
}
Esempio n. 4
0
int main(int argc, char **argv)
{
    h2o_hostconf_t *hostconf;
    h2o_pathconf_t *pathconf;

    h2o_config_init(&config);
    hostconf = h2o_config_register_host(&config, h2o_iovec_init(H2O_STRLIT("default")), 65535);
    pathconf = h2o_config_register_path(hostconf, "/", 0);
    h2o_create_handler(pathconf, sizeof(h2o_handler_t))->on_req = on_req;

#if H2O_USE_LIBUV
    uv_loop_t loop;
    uv_loop_init(&loop);
    h2o_context_init(&ctx, &loop, &config);
#else
    h2o_context_init(&ctx, h2o_evloop_create(), &config);
#endif

    /* disabled by default: uncomment the block below to use HTTPS instead of HTTP */
    /*
    if (setup_ssl("server.crt", "server.key") != 0)
        goto Error;
    */

    accept_ctx.ctx = &ctx;
    accept_ctx.hosts = config.hosts;

    if (create_listener() != 0) {
        fprintf(stderr, "failed to listen to 127.0.0.1:7890:%s\n", strerror(errno));
        goto Error;
    }

#if H2O_USE_LIBUV
    uv_run(ctx.loop, UV_RUN_DEFAULT);
#else
    while (h2o_evloop_run(ctx.loop, INT32_MAX) == 0)
        ;
#endif

Error:
    return 1;
}
Esempio n. 5
0
int main(int argc, char **argv)
{
    static struct option longopts[] = {
        { "conf", required_argument, NULL, 'c' },
        { "help", no_argument, NULL, 'h' },
        { NULL, 0, NULL, 0 }
    };
    static struct port_configurator_t port_configurator = {
        { NULL, "port", NULL, on_config_port, on_config_port_complete },
        0
    };


    const char *conf_fn = "h2o.conf";
    int opt_ch;
    yoml_t *config;
    h2o_context_t ctx;

    /* parse options */
    while ((opt_ch = getopt_long(argc, argv, "c:h:", longopts, NULL)) != -1) {
        switch (opt_ch) {
        case 'c':
            conf_fn = optarg;
            break;
        case 'h':
            usage();
            exit(0);
            break;
        default:
            assert(0);
            break;
        }
    }
    argc -= optind;
    argv += optind;

    /* load configuration */
    if ((config = load_config(conf_fn)) == NULL)
        exit(EX_CONFIG);

    /* setup h2o context */
    h2o_context_init(&ctx, h2o_evloop_create());
    h2o_register_configurator(&ctx, &port_configurator.super);

    /* apply the configuration */
    if (h2o_context_configure(&ctx, conf_fn, config) != 0)
        exit(EX_CONFIG);

    while (h2o_evloop_run(ctx.loop) == 0)
        ;

    return 0;
}
Esempio n. 6
0
void test_issues293()
{
    h2o_globalconf_t globalconf;

    h2o_config_init(&globalconf);

    /* register two hosts, using 80 and 443 */
    register_authority(&globalconf, h2o_iovec_init(H2O_STRLIT("default")), 65535);
    register_authority(&globalconf, h2o_iovec_init(H2O_STRLIT("host1")), 80);
    register_authority(&globalconf, h2o_iovec_init(H2O_STRLIT("host1")), 443);
    register_authority(&globalconf, h2o_iovec_init(H2O_STRLIT("host2")), 80);
    register_authority(&globalconf, h2o_iovec_init(H2O_STRLIT("host2")), 443);
    register_authority(&globalconf, h2o_iovec_init(H2O_STRLIT("host3")), 65535);

    h2o_context_init(&ctx, test_loop, &globalconf);

    /* run the tests */
    check(&H2O_URL_SCHEME_HTTP, "host1", "host1:80");
    check(&H2O_URL_SCHEME_HTTPS, "host1", "host1:443");
    check(&H2O_URL_SCHEME_HTTP, "host2", "host2:80");
    check(&H2O_URL_SCHEME_HTTPS, "host2", "host2:443");

    /* supplied port number in the Host header must be preferred */
    check(&H2O_URL_SCHEME_HTTP, "host1:80", "host1:80");
    check(&H2O_URL_SCHEME_HTTP, "host1:443", "host1:443");
    check(&H2O_URL_SCHEME_HTTPS, "host1:80", "host1:80");
    check(&H2O_URL_SCHEME_HTTPS, "host1:443", "host1:443");
    check(&H2O_URL_SCHEME_HTTP, "host2:80", "host2:80");
    check(&H2O_URL_SCHEME_HTTP, "host2:443", "host2:443");
    check(&H2O_URL_SCHEME_HTTPS, "host2:80", "host2:80");
    check(&H2O_URL_SCHEME_HTTPS, "host2:443", "host2:443");

    /* host-level conf without default port */
    check(&H2O_URL_SCHEME_HTTP, "host3", "host3:65535");
    check(&H2O_URL_SCHEME_HTTPS, "host3", "host3:65535");
    check(&H2O_URL_SCHEME_HTTP, "host3", "host3:65535");
    check(&H2O_URL_SCHEME_HTTPS, "host3", "host3:65535");
    check(&H2O_URL_SCHEME_HTTP, "host3:80", "host3:65535");
    check(&H2O_URL_SCHEME_HTTPS, "host3:80", "default:65535");
    check(&H2O_URL_SCHEME_HTTP, "host3:443", "default:65535");
    check(&H2O_URL_SCHEME_HTTPS, "host3:443", "host3:65535");

    /* upper-case */
    check(&H2O_URL_SCHEME_HTTP, "HoST1", "host1:80");
    check(&H2O_URL_SCHEME_HTTP, "HoST1:80", "host1:80");
    check(&H2O_URL_SCHEME_HTTPS, "HoST1", "host1:443");
    check(&H2O_URL_SCHEME_HTTPS, "HoST1:443", "host1:443");

    h2o_context_dispose(&ctx);
    h2o_config_dispose(&globalconf);
}
Esempio n. 7
0
File: simple.c Progetto: Gwill/h2o
int main(int argc, char **argv)
{
    signal(SIGPIPE, SIG_IGN);

    h2o_config_init(&config);
    register_handler(&config.default_host, post_test);
    register_handler(&config.default_host, chunked_test);
    register_handler(&config.default_host, reproxy_test);
    h2o_register_file_handler(&config.default_host, "/", "htdocs", "index.html");
    h2o_define_mimetype(&config.default_host.mimemap, "html", "text/html");
    h2o_register_reproxy_filter(&config.default_host);

#if H2O_USE_LIBUV
    uv_loop_t loop;
    uv_loop_init(&loop);
    h2o_context_init(&ctx, &loop, &config);
#else
    h2o_context_init(&ctx, h2o_evloop_create(), &config);
#endif

    //ssl_ctx = h2o_ssl_new_server_context("server.crt", "server.key", h2o_http2_tls_identifiers);
    //h2o_register_access_logger(&ctx, "/dev/stdout");

    if (create_listener() != 0) {
        fprintf(stderr, "failed to listen to 127.0.0.1:7890:%s\n", strerror(errno));
        goto Error;
    }

#if H2O_USE_LIBUV
    uv_run(ctx.loop, UV_RUN_DEFAULT);
#else
    while (h2o_evloop_run(ctx.loop) == 0)
        ;
#endif

Error:
    return 1;
}
Esempio n. 8
0
File: main.c Progetto: Gwill/h2o
static void *run_loop(void *_config)
{
    h2o_global_configuration_t *config = _config;
    h2o_evloop_t *loop;
    h2o_context_t ctx;

    loop = h2o_evloop_create();
    h2o_context_init(&ctx, loop, config);

    while (1)
        h2o_evloop_run(loop);

    return NULL;
}
Esempio n. 9
0
void initialize_event_loop(bool is_main_thread,
                           global_data_t *global_data,
                           event_loop_t *loop)
{
	memset(loop, 0, sizeof(*loop));
	h2o_context_init(&loop->h2o_ctx, h2o_evloop_create(), &global_data->h2o_config);
	loop->h2o_accept_ctx.ctx = &loop->h2o_ctx;
	loop->h2o_accept_ctx.hosts = global_data->h2o_config.hosts;
	loop->h2o_accept_ctx.ssl_ctx = global_data->ssl_ctx;

	int listener_sd;

	if (is_main_thread)
		listener_sd = global_data->listener_sd;
	else {
		int flags;

		CHECK_ERRNO_RETURN(listener_sd, dup, global_data->listener_sd);
		CHECK_ERRNO_RETURN(flags, fcntl, listener_sd, F_GETFD);
		CHECK_ERRNO(fcntl, listener_sd, F_SETFD, flags | FD_CLOEXEC);
	}

	// Let all the threads race to call accept() on the socket; since the latter is
	// non-blocking, that will effectively act as load balancing.
	loop->h2o_socket = h2o_evloop_socket_create(loop->h2o_ctx.loop,
	                                            listener_sd,
	                                            H2O_SOCKET_FLAG_DONT_READ);
	loop->h2o_socket->data = loop;
	h2o_socket_read_start(loop->h2o_socket, accept_connection);
	h2o_multithread_register_receiver(loop->h2o_ctx.queue,
	                                  &loop->h2o_receiver,
	                                  process_messages);
	// libh2o's event loop does not support write polling unless it
	// controls sending the data as well, so do read polling on the
	// epoll file descriptor as a work-around.
	CHECK_ERRNO_RETURN(loop->epoll_fd, epoll_create1, EPOLL_CLOEXEC);
	loop->epoll_socket = h2o_evloop_socket_create(loop->h2o_ctx.loop,
	                                              loop->epoll_fd,
	                                              H2O_SOCKET_FLAG_DONT_READ);
	loop->epoll_socket->data = loop;
	h2o_socket_read_start(loop->epoll_socket, do_epoll_wait);

	if (is_main_thread) {
		global_data->signals = h2o_evloop_socket_create(loop->h2o_ctx.loop,
		                                                global_data->signal_fd,
		                                                H2O_SOCKET_FLAG_DONT_READ);
		global_data->signals->data = loop;
		h2o_socket_read_start(global_data->signals, shutdown_server);
	}
}
Esempio n. 10
0
void test_lib__handler__redirect_c()
{
    h2o_globalconf_t globalconf;
    h2o_hostconf_t *hostconf;
    h2o_pathconf_t *pathconf;

    h2o_config_init(&globalconf);
    hostconf = h2o_config_register_host(&globalconf, h2o_iovec_init(H2O_STRLIT("default")), 65535);
    pathconf = h2o_config_register_path(hostconf, "/", 0);
    h2o_redirect_register(pathconf, 0, 301, "https://example.com/bar/");

    h2o_context_init(&ctx, test_loop, &globalconf);

    {
        h2o_loopback_conn_t *conn = h2o_loopback_create(&ctx, ctx.globalconf->hosts);
        conn->req.input.method = h2o_iovec_init(H2O_STRLIT("GET"));
        conn->req.input.path = h2o_iovec_init(H2O_STRLIT("/"));
        h2o_loopback_run_loop(conn);
        ok(conn->req.res.status == 301);
        ok(check_header(&conn->req.res, H2O_TOKEN_LOCATION, "https://example.com/bar/"));
        ok(conn->body->size != 0);
        h2o_loopback_destroy(conn);
    }
    {
        h2o_loopback_conn_t *conn = h2o_loopback_create(&ctx, ctx.globalconf->hosts);
        conn->req.input.method = h2o_iovec_init(H2O_STRLIT("GET"));
        conn->req.input.path = h2o_iovec_init(H2O_STRLIT("/abc"));
        h2o_loopback_run_loop(conn);
        ok(conn->req.res.status == 301);
        ok(check_header(&conn->req.res, H2O_TOKEN_LOCATION, "https://example.com/bar/abc"));
        ok(conn->body->size != 0);
        h2o_loopback_destroy(conn);
    }
    {
        h2o_loopback_conn_t *conn = h2o_loopback_create(&ctx, ctx.globalconf->hosts);
        conn->req.input.method = h2o_iovec_init(H2O_STRLIT("HEAD"));
        conn->req.input.path = h2o_iovec_init(H2O_STRLIT("/"));
        h2o_loopback_run_loop(conn);
        ok(conn->req.res.status == 301);
        ok(check_header(&conn->req.res, H2O_TOKEN_LOCATION, "https://example.com/bar/"));
        ok(conn->body->size == 0);
        h2o_loopback_destroy(conn);
    }

    h2o_context_dispose(&ctx);
    h2o_config_dispose(&globalconf);
}
Esempio n. 11
0
void test_lib__handler__fastcgi_c()
{
    h2o_globalconf_t globalconf;
    h2o_hostconf_t *hostconf;
    h2o_pathconf_t *pathconf;

    h2o_config_init(&globalconf);
    globalconf.server_name = h2o_iovec_init(H2O_STRLIT("h2o/1.2.1-alpha1"));
    hostconf = h2o_config_register_host(&globalconf, h2o_iovec_init(H2O_STRLIT("default")), 65535);
    pathconf = h2o_config_register_path(hostconf, "/");

    h2o_context_init(&ctx, test_loop, &globalconf);

    subtest("build-request", test_build_request);

    h2o_context_dispose(&ctx);
    h2o_config_dispose(&globalconf);
}
Esempio n. 12
0
File: main.c Progetto: Debug-Orz/h2o
static void *run_loop(void *_conf)
{
    struct config_t *conf = _conf;
    h2o_evloop_t *loop;
    h2o_context_t ctx;
    struct listener_ctx_t *listeners = alloca(sizeof(*listeners) * conf->num_listeners);
    size_t i;

    /* setup loop and context */
    loop = h2o_evloop_create();
    h2o_context_init(&ctx, loop, &conf->global_config);

    /* setup listeners */
    for (i = 0; i != conf->num_listeners; ++i) {
        listeners[i].ctx = &ctx;
        listeners[i].ssl_ctx = conf->listeners[i]->ssl_ctx;
        listeners[i].sock = h2o_evloop_socket_create(
            ctx.loop, conf->listeners[i]->fd,
            (struct sockaddr*)&conf->listeners[i]->addr, conf->listeners[i]->addrlen,
            H2O_SOCKET_FLAG_IS_ACCEPT);
        listeners[i].sock->data = listeners + i;
    }

    /* the main loop */
    while (1) {
        /* start / stop trying to accept new connections */
        if (conf->state.num_connections < conf->max_connections) {
            for (i = 0; i != conf->num_listeners; ++i) {
                if (! h2o_socket_is_reading(listeners[i].sock))
                    h2o_socket_read_start(listeners[i].sock, on_accept);
            }
        } else {
            for (i = 0; i != conf->num_listeners; ++i) {
                if (h2o_socket_is_reading(listeners[i].sock))
                    h2o_socket_read_stop(listeners[i].sock);
            }
        }
        /* run the loop once */
        h2o_evloop_run(loop);
    }

    return NULL;
}
Esempio n. 13
0
int main(int argc, char **argv)
{
    uv_loop_t *loop = uv_default_loop();
    uv_tcp_t listener;
    struct sockaddr_in sockaddr;
    h2o_hostconf_t *hostconf;
    h2o_pathconf_t *pathconf;
    int r;

    if ((r = uv_tcp_init(loop, &listener)) != 0) {
        fprintf(stderr, "uv_tcp_init:%s\n", uv_strerror(r));
        goto Error;
    }
    uv_ip4_addr("127.0.0.1", 7890, &sockaddr);
    if ((r = uv_tcp_bind(&listener, (struct sockaddr *)&sockaddr, sizeof(sockaddr))) != 0) {
        fprintf(stderr, "uv_tcp_bind:%s\n", uv_strerror(r));
        goto Error;
    }
    if ((r = uv_listen((uv_stream_t *)&listener, 128, on_connect)) != 0) {
        fprintf(stderr, "uv_listen:%s\n", uv_strerror(r));
        goto Error;
    }

    h2o_config_init(&config);
    hostconf = h2o_config_register_host(&config, "default");
    pathconf = h2o_config_register_path(hostconf, "/");
    h2o_create_handler(pathconf, sizeof(h2o_handler_t))->on_req = on_req;

    h2o_context_init(&ctx, loop, &config);

    /* disabled by default: uncomment the block below to use HTTPS instead of HTTP */
    /*
    if (setup_ssl("server.crt", "server.key") != 0)
        goto Error;
    */

    return uv_run(loop, UV_RUN_DEFAULT);

Error:
    return 1;
}
Esempio n. 14
0
File: file.c Progetto: lhjay1/h2o
void test_lib__file_c()
{
    h2o_globalconf_t globalconf;
    h2o_hostconf_t *hostconf;
    h2o_context_t ctx;

    h2o_config_init(&globalconf);
    hostconf = h2o_config_register_host(&globalconf, "default");
    h2o_file_register(hostconf, "/", "t/00unit/file", NULL, NULL);

    h2o_context_init(&ctx, test_loop, &globalconf);

    {
        h2o_loopback_conn_t *conn = h2o_loopback_create(&ctx);
        conn->req.method = h2o_buf_init(H2O_STRLIT("GET"));
        conn->req.path = h2o_buf_init(H2O_STRLIT("/"));
        h2o_loopback_run_loop(conn);
        ok(conn->req.res.status == 200);
        ok(check_header(&conn->req.res, H2O_TOKEN_CONTENT_TYPE, "text/html"));
        ok(h2o_memis(conn->body->bytes, conn->body->size, H2O_STRLIT("hello html\n")));
        h2o_loopback_destroy(conn);
    }
    {
        h2o_loopback_conn_t *conn = h2o_loopback_create(&ctx);
        conn->req.method = h2o_buf_init(H2O_STRLIT("GET"));
        conn->req.path = h2o_buf_init(H2O_STRLIT("/index.html"));
        h2o_loopback_run_loop(conn);
        ok(conn->req.res.status == 200);
        ok(check_header(&conn->req.res, H2O_TOKEN_CONTENT_TYPE, "text/html"));
        ok(h2o_memis(conn->body->bytes, conn->body->size, H2O_STRLIT("hello html\n")));
        h2o_loopback_destroy(conn);
    }
    {
        h2o_loopback_conn_t *conn = h2o_loopback_create(&ctx);
        conn->req.method = h2o_buf_init(H2O_STRLIT("GET"));
        conn->req.path = h2o_buf_init(H2O_STRLIT("/1000.txt"));
        h2o_loopback_run_loop(conn);
        ok(conn->req.res.status == 200);
        ok(check_header(&conn->req.res, H2O_TOKEN_CONTENT_TYPE, "text/plain"));
        ok(conn->body->size == 1000);
        ok(strcmp(sha1sum(conn->body->bytes, conn->body->size), "dfd3ae1f5c475555fad62efe42e07309fa45f2ed") == 0);
        h2o_loopback_destroy(conn);
    }
    {
        h2o_loopback_conn_t *conn = h2o_loopback_create(&ctx);
        conn->req.method = h2o_buf_init(H2O_STRLIT("GET"));
        conn->req.path = h2o_buf_init(H2O_STRLIT("/1000000.txt"));
        h2o_loopback_run_loop(conn);
        ok(conn->req.res.status == 200);
        ok(check_header(&conn->req.res, H2O_TOKEN_CONTENT_TYPE, "text/plain"));
        ok(conn->body->size == 1000000);
        ok(strcmp(sha1sum(conn->body->bytes, conn->body->size), "00c8ab71d0914dce6a1ec2eaa0fda0df7044b2a2") == 0);
        h2o_loopback_destroy(conn);
    }
    {
        h2o_loopback_conn_t *conn = h2o_loopback_create(&ctx);
        conn->req.method = h2o_buf_init(H2O_STRLIT("GET"));
        conn->req.path = h2o_buf_init(H2O_STRLIT("/index_txt/"));
        h2o_loopback_run_loop(conn);
        ok(conn->req.res.status == 200);
        ok(check_header(&conn->req.res, H2O_TOKEN_CONTENT_TYPE, "text/plain"));
        ok(h2o_memis(conn->body->bytes, conn->body->size, H2O_STRLIT("hello text\n")));
        h2o_loopback_destroy(conn);
    }
    {
        h2o_loopback_conn_t *conn = h2o_loopback_create(&ctx);
        conn->req.method = h2o_buf_init(H2O_STRLIT("GET"));
        conn->req.path = h2o_buf_init(H2O_STRLIT("/index_txt"));
        h2o_loopback_run_loop(conn);
        ok(conn->req.res.status == 301);
        ok(check_header(&conn->req.res, H2O_TOKEN_LOCATION, "http://default/index_txt/"));
        h2o_loopback_destroy(conn);
    }
    {
        h2o_loopback_conn_t *conn = h2o_loopback_create(&ctx);
        conn->req.method = h2o_buf_init(H2O_STRLIT("GET"));
        conn->req.path = h2o_buf_init(H2O_STRLIT("/index_txt_as_dir/"));
        h2o_loopback_run_loop(conn);
        ok(conn->req.res.status == 301);
        ok(check_header(&conn->req.res, H2O_TOKEN_LOCATION, "http://default/index_txt_as_dir/index.txt/"));
        h2o_loopback_destroy(conn);
    }

    h2o_context_dispose(&ctx);
    h2o_config_dispose(&globalconf);
}