static void on_setup_ostream(h2o_filter_t *self, h2o_req_t *req, h2o_ostream_t **slot) { h2o_iovec_t dest, method; ssize_t xru_index; /* obtain x-reproxy-url header, or skip to next ostream */ if ((xru_index = h2o_find_header(&req->res.headers, H2O_TOKEN_X_REPROXY_URL, -1)) == -1) { h2o_setup_next_ostream(req, slot); return; } dest = req->res.headers.entries[xru_index].value; h2o_delete_header(&req->res.headers, xru_index); /* setup params */ switch (req->res.status) { case 307: case 308: method = req->method; break; default: method = h2o_iovec_init(H2O_STRLIT("GET")); req->entity = (h2o_iovec_t){NULL}; break; } /* request internal redirect (is deferred) */ h2o_send_redirect_internal(req, method, dest.base, dest.len, 0); /* setup filter (that swallows the response until the timeout gets fired) */ h2o_ostream_t *ostream = h2o_add_ostream(req, H2O_ALIGNOF(*ostream), sizeof(*ostream), slot); ostream->do_send = on_send; }
static void on_setup_ostream(h2o_filter_t *self, h2o_req_t *req, h2o_ostream_t **slot) { struct rproxy_t *rproxy; ssize_t reproxy_header_index; h2o_buf_t reproxy_url; /* do nothing unless 200 */ if (req->res.status != 200) goto SkipMe; if ((reproxy_header_index = h2o_find_header(&req->res.headers, H2O_TOKEN_X_REPROXY_URL, -1)) == -1) goto SkipMe; reproxy_url = req->res.headers.entries[reproxy_header_index].value; h2o_delete_header(&req->res.headers, reproxy_header_index); /* setup */ rproxy = (void*)h2o_add_ostream(req, sizeof(struct rproxy_t), slot); rproxy->filter = self; rproxy->super.do_send = send_chunk; rproxy->reproxy_url = h2o_strdup(&req->pool, reproxy_url.base, reproxy_url.len).base; /* next ostream is setup when send_chunk receives EOS */ return; SkipMe: h2o_setup_next_ostream(self, req, slot); }
static mrb_value h2o_mrb_req_send_file(mrb_state *mrb, mrb_value self) { h2o_mruby_internal_context_t *mruby_ctx = (h2o_mruby_internal_context_t *)mrb->ud; char *fn; int status; h2o_iovec_t content_type; int content_type_header_removed = 0; if (mruby_ctx->state != H2O_MRUBY_STATE_UNDETERMINED) mrb_raise(mrb, E_RUNTIME_ERROR, "response already sent"); mrb_get_args(mrb, "z", &fn); /* determine status and reason to be used */ if ((status = mruby_ctx->req->res.status) == 0) status = 200; { /* determine content-type (removing existing header, since it is added by h2o_file_send) */ ssize_t header_index; if ((header_index = h2o_find_header(&mruby_ctx->req->res.headers, H2O_TOKEN_CONTENT_TYPE, -1)) != -1) { content_type = mruby_ctx->req->res.headers.entries[header_index].value; h2o_delete_header(&mruby_ctx->req->res.headers, header_index); content_type_header_removed = 1; } else { const char *ext = h2o_get_filext(fn, strlen(fn)); h2o_mimemap_type_t *m = h2o_mimemap_get_type_by_extension(mruby_ctx->req->pathconf->mimemap, ext); if (m == NULL || m->type != H2O_MIMEMAP_TYPE_MIMETYPE) { m = h2o_mimemap_get_default_type(mruby_ctx->req->pathconf->mimemap); assert(m->type == H2O_MIMEMAP_TYPE_MIMETYPE); } content_type = m->data.mimetype; } } if (h2o_file_send(mruby_ctx->req, status, mruby_ctx->req->res.reason, fn, content_type, H2O_FILE_FLAG_SEND_GZIP) == 0) { /* succeeded, return true */ mruby_ctx->state = H2O_MRUBY_STATE_RESPONSE_SENT; return mrb_true_value(); } else { /* failed, restore content-type header and return false */ if (content_type_header_removed) h2o_add_header(&mruby_ctx->req->pool, &mruby_ctx->req->res.headers, H2O_TOKEN_CONTENT_TYPE, content_type.base, content_type.len); return mrb_false_value(); } }