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(); }
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); }