Example #1
0
static mrb_value h2o_mrb_req_reprocess_request(mrb_state *mrb, mrb_value self)
{
    h2o_mruby_internal_context_t *mruby_ctx = (h2o_mruby_internal_context_t *)mrb->ud;
    char *s;
    mrb_int len;
    h2o_url_t parsed, base, resolved;

    if (mruby_ctx->state != H2O_MRUBY_STATE_UNDETERMINED)
        mrb_raise(mrb, E_RUNTIME_ERROR, "response already sent");

    mrb_get_args(mrb, "s", &s, &len);

    /* resolve the input URL:
     * * uses `hostconf->authority.hostport` as part of base to prevent relative-path internal redirect generating a TCP connection
     * * h2o_url_resolve always copies the memory (so the values will be preserved after mruby GC)
     */
    if (h2o_url_parse_relative(s, (size_t)len, &parsed) != 0)
        mrb_raise(mrb, E_ARGUMENT_ERROR, "failed to parse URL");
    h2o_req_t *req = mruby_ctx->req;
    if (h2o_url_init(&base, req->scheme, req->hostconf->authority.hostport, req->pathconf->path) != 0)
        mrb_raise(mrb, E_RUNTIME_ERROR, "failed to parse current authority");
    h2o_url_resolve(&req->pool, &base, &parsed, &resolved);

    /* request reprocess */
    h2o_reprocess_request_deferred(req, req->method, resolved.scheme, resolved.authority, resolved.path, NULL, 0);
    mruby_ctx->state = H2O_MRUBY_STATE_RESPONSE_SENT;

    return mrb_nil_value();
}
Example #2
0
static void push_one_path(h2o_mem_pool_t *pool, h2o_iovec_vector_t *paths_to_push, h2o_iovec_t *url,
                          h2o_iovec_t base_path, const h2o_url_scheme_t *input_scheme, h2o_iovec_t input_authority,
                          const h2o_url_scheme_t *base_scheme, h2o_iovec_t *base_authority)
{
    h2o_url_t parsed, resolved;

    /* check the authority, and extract absolute path */
    if (h2o_url_parse_relative(url->base, url->len, &parsed) != 0)
        return;

    /* fast-path for abspath form */
    if (base_scheme == NULL && parsed.scheme == NULL && parsed.authority.base == NULL && url->len != 0 && url->base[0] == '/') {
        h2o_vector_reserve(pool, paths_to_push, paths_to_push->size + 1);
        paths_to_push->entries[paths_to_push->size++] = h2o_strdup(pool, url->base, url->len);
        return;
    }

    /* check scheme and authority if given URL contains either of the two, or if base is specified */
    h2o_url_t base = {input_scheme, input_authority, {}, base_path, 65535};
    if (base_scheme != NULL) {
        base.scheme = base_scheme;
        base.authority = *base_authority;
    }
    h2o_url_resolve(pool, &base, &parsed, &resolved);
    if (input_scheme != resolved.scheme)
        return;
    if (!h2o_lcstris(input_authority.base, input_authority.len, resolved.authority.base, resolved.authority.len))
        return;

    h2o_vector_reserve(pool, paths_to_push, paths_to_push->size + 1);
    paths_to_push->entries[paths_to_push->size++] = resolved.path;
}
Example #3
0
File: util.c Project: nwcs/h2o
h2o_iovec_t h2o_extract_push_path_from_link_header(h2o_mem_pool_t *pool, const char *value, size_t value_len,
                                                   const h2o_url_scheme_t *base_scheme, h2o_iovec_t *base_authority,
                                                   h2o_iovec_t *base_path)
{
    h2o_iovec_t url;
    h2o_url_t parsed, resolved;

    { /* extract URL value from: Link: </pushed.css>; rel=preload */
        h2o_iovec_t iter = h2o_iovec_init(value, value_len), token_value;
        const char *token;
        size_t token_len;
        /* first element should be <URL> */
        if ((token = h2o_next_token(&iter, ';', &token_len, NULL)) == NULL)
            goto None;
        if (!(token_len >= 2 && token[0] == '<' && token[token_len - 1] == '>'))
            goto None;
        url = h2o_iovec_init(token + 1, token_len - 2);
        /* find rel=preload */
        while ((token = h2o_next_token(&iter, ';', &token_len, &token_value)) != NULL) {
            if (h2o_lcstris(token, token_len, H2O_STRLIT("rel")) &&
                h2o_lcstris(token_value.base, token_value.len, H2O_STRLIT("preload")))
                break;
        }
        if (token == NULL)
            goto None;
    }

    /* check the authority, and extract absolute path */
    if (h2o_url_parse_relative(url.base, url.len, &parsed) != 0)
        goto None;

    /* return the URL found in Link header, if it is an absolute path-only URL */
    if (parsed.scheme == NULL && parsed.authority.base == NULL && url.len != 0 && url.base[0] == '/')
        return h2o_strdup(pool, url.base, url.len);

    /* check scheme and authority if given URL contains either of the two */
    h2o_url_t base = {base_scheme, *base_authority, {}, *base_path, 65535};
    h2o_url_resolve(pool, &base, &parsed, &resolved);
    if (base.scheme != resolved.scheme)
        goto None;
    if (parsed.authority.base != NULL &&
        !h2o_lcstris(base.authority.base, base.authority.len, resolved.authority.base, resolved.authority.len))
        goto None;
    return resolved.path;

None:
    return (h2o_iovec_t){};
}
Example #4
0
static void redirect_internally(h2o_redirect_handler_t *self, h2o_req_t *req, h2o_iovec_t dest)
{
    h2o_iovec_t method;
    h2o_url_t input, resolved;

    /* resolve the URL */
    if (h2o_url_parse_relative(dest.base, dest.len, &input) != 0) {
        h2o_req_log_error(req, MODULE_NAME, "invalid destination:%.*s", (int)dest.len, dest.base);
        goto SendInternalError;
    }
    if (input.scheme != NULL && input.authority.base != NULL) {
        resolved = input;
    } else {
        h2o_url_t base;
        /* we MUST to set authority to that of hostconf, or internal redirect might create a TCP connection */
        if (h2o_url_init(&base, req->scheme, req->hostconf->authority.hostport, req->path) != 0) {
            h2o_req_log_error(req, MODULE_NAME, "failed to parse current authority:%.*s", (int)req->authority.len,
                              req->authority.base);
            goto SendInternalError;
        }
        h2o_url_resolve(&req->pool, &base, &input, &resolved);
    }

    /* determine the method */
    switch (self->status) {
    case 307:
    case 308:
        method = req->method;
        break;
    default:
        method = h2o_iovec_init(H2O_STRLIT("GET"));
#ifndef _MSC_VER
        req->entity = (h2o_iovec_t){NULL};
#else
		req->entity = (h2o_iovec_t) { 0 };
#endif
        break;
    }

    h2o_reprocess_request_deferred(req, method, resolved.scheme, resolved.authority, resolved.path, NULL, 1);
    return;

SendInternalError:
    h2o_send_error_503(req, "Internal Server Error", "internal server error", 0);
}