static void do_send_file(struct st_h2o_sendfile_generator_t *self, h2o_req_t *req, int status, const char *reason, h2o_buf_t mime_type) { /* link the request */ self->req = req; /* setup response */ req->res.status = status; req->res.reason = reason; req->res.content_length = self->bytesleft; h2o_add_header(&req->pool, &req->res.headers, H2O_TOKEN_CONTENT_TYPE, mime_type.base, mime_type.len); h2o_add_header(&req->pool, &req->res.headers, H2O_TOKEN_LAST_MODIFIED, self->last_modified_buf, H2O_TIMESTR_RFC1123_LEN); h2o_add_header(&req->pool, &req->res.headers, H2O_TOKEN_ETAG, self->etag_buf, self->etag_len); /* send data */ h2o_start_response(req, &self->super); if (req->_ostr_top->start_pull != NULL) { req->_ostr_top->start_pull(req->_ostr_top, do_pull); } else { size_t bufsz = MAX_BUF_SIZE; if (self->bytesleft < bufsz) bufsz = self->bytesleft; self->buf = h2o_mempool_alloc(&req->pool, bufsz); do_proceed(&self->super, req); } }
static void do_send_file(struct st_h2o_sendfile_generator_t *self, h2o_req_t *req, int status, const char *reason, h2o_iovec_t mime_type, h2o_mime_attributes_t *mime_attr, int is_get) { /* link the request */ self->req = req; /* setup response */ req->res.status = status; req->res.reason = reason; req->res.content_length = self->bytesleft; req->res.mime_attr = mime_attr; if (self->ranged.range_count > 1) { mime_type.base = h2o_mem_alloc_pool(&req->pool, 52); mime_type.len = sprintf(mime_type.base, "multipart/byteranges; boundary=%s", self->ranged.boundary.base); } h2o_add_header(&req->pool, &req->res.headers, H2O_TOKEN_CONTENT_TYPE, mime_type.base, mime_type.len); h2o_filecache_get_last_modified(self->file.ref, self->header_bufs.last_modified); h2o_add_header(&req->pool, &req->res.headers, H2O_TOKEN_LAST_MODIFIED, self->header_bufs.last_modified, H2O_TIMESTR_RFC1123_LEN); add_headers_unconditional(self, req); if (self->content_encoding.base != NULL) h2o_add_header(&req->pool, &req->res.headers, H2O_TOKEN_CONTENT_ENCODING, self->content_encoding.base, self->content_encoding.len); if (self->ranged.range_count == 0) h2o_add_header(&req->pool, &req->res.headers, H2O_TOKEN_ACCEPT_RANGES, H2O_STRLIT("bytes")); else if (self->ranged.range_count == 1) { h2o_iovec_t content_range; content_range.base = h2o_mem_alloc_pool(&req->pool, 128); content_range.len = sprintf(content_range.base, "bytes %zd-%zd/%zd", self->ranged.range_infos[0], self->ranged.range_infos[0] + self->ranged.range_infos[1] - 1, self->ranged.filesize); h2o_add_header(&req->pool, &req->res.headers, H2O_TOKEN_CONTENT_RANGE, content_range.base, content_range.len); } /* special path for cases where we do not need to send any data */ if (!is_get || self->bytesleft == 0) { static h2o_generator_t generator = {NULL, NULL}; h2o_start_response(req, &generator); h2o_send(req, NULL, 0, 1); do_close(&self->super, req); return; } /* send data */ h2o_start_response(req, &self->super); if (self->ranged.range_count == 1) self->file.off = self->ranged.range_infos[0]; if (req->_ostr_top->start_pull != NULL && self->ranged.range_count < 2) { req->_ostr_top->start_pull(req->_ostr_top, do_pull); } else { size_t bufsz = MAX_BUF_SIZE; if (self->bytesleft < bufsz) bufsz = self->bytesleft; self->buf = h2o_mem_alloc_pool(&req->pool, bufsz); if (self->ranged.range_count < 2) do_proceed(&self->super, req); else { self->bytesleft = 0; self->super.proceed = do_multirange_proceed; do_multirange_proceed(&self->super, req); } } }