static int redirect_to_dir(h2o_req_t *req, const char *path, size_t path_len) { static h2o_generator_t generator = { NULL, NULL }; static const h2o_buf_t body_prefix = { H2O_STRLIT("<!DOCTYPE html><TITLE>301 Moved Permanently</TITLE><P>The document has moved <A HREF=\"") }; static const h2o_buf_t body_suffix = { H2O_STRLIT("\">here</A>") }; h2o_buf_t url; size_t alloc_size; h2o_buf_t bufs[3]; /* determine the size of the memory needed */ alloc_size = sizeof(":///") + req->scheme.len + req->authority.len + path_len; /* allocate and build url */ url.base = h2o_mempool_alloc(&req->pool, alloc_size); url.len = sprintf(url.base, "%.*s://%.*s%.*s/", (int)req->scheme.len, req->scheme.base, (int)req->authority.len, req->authority.base, (int)path_len, path); assert(url.len + 1 == alloc_size); /* build response header */ req->res.status = 301; req->res.reason = "Moved Permanently"; memset(&req->res.headers, 0, sizeof(req->res.headers)); h2o_add_header(&req->pool, &req->res.headers, H2O_TOKEN_LOCATION, url.base, url.len); h2o_add_header(&req->pool, &req->res.headers, H2O_TOKEN_CONTENT_TYPE, H2O_STRLIT("text/html; charset=utf-8")); /* build response */ bufs[0] = body_prefix; bufs[1] = h2o_htmlescape(&req->pool, url.base, url.len); bufs[2] = body_suffix; /* send */ h2o_start_response(req, &generator); h2o_send(req, bufs, 3, 1); return 0; }
static result_return_t on_fortune_result(db_query_param_t *param, PGresult *result) { fortune_ctx_t * const fortune_ctx = H2O_STRUCT_FROM_MEMBER(fortune_ctx_t, param, param); int ret = DONE; const ExecStatusType status = PQresultStatus(result); if (status == PGRES_TUPLES_OK) { const size_t num_rows = PQntuples(result); ret = SUCCESS; for (size_t i = 0; i < num_rows; i++) { fortune_t * const fortune = h2o_mem_alloc_pool(&fortune_ctx->req->pool, sizeof(*fortune)); if (fortune) { memset(fortune, 0, sizeof(*fortune)); fortune->id.base = PQgetvalue(result, i, 0); fortune->id.len = PQgetlength(result, i, 0); fortune->message = h2o_htmlescape(&fortune_ctx->req->pool, PQgetvalue(result, i, 1), PQgetlength(result, i, 1)); fortune->l.next = fortune_ctx->result; fortune_ctx->result = &fortune->l; fortune_ctx->num_result++; if (!i) fortune->data = result; } else { send_error(INTERNAL_SERVER_ERROR, REQ_ERROR, fortune_ctx->req); ret = DONE; if (!i) PQclear(result); break; } } } else if (result) { LIBRARY_ERROR("PQresultStatus", PQresultErrorMessage(result)); send_error(BAD_GATEWAY, DB_ERROR, fortune_ctx->req); PQclear(result); } else { mustache_api_t api = {.sectget = on_fortune_section, .varget = on_fortune_variable, .write = add_iovec}; thread_context_t * const ctx = H2O_STRUCT_FROM_MEMBER(thread_context_t, event_loop.h2o_ctx, fortune_ctx->req->conn->ctx); const size_t iovcnt = MIN(MAX_IOVEC, fortune_ctx->num_result * 5 + 2); const size_t sz = offsetof(iovec_list_t, iov) + iovcnt * sizeof(h2o_iovec_t); char _Alignas(iovec_list_t) mem[sz]; iovec_list_t * const restrict iovec_list = (iovec_list_t *) mem; memset(iovec_list, 0, offsetof(iovec_list_t, iov)); iovec_list->max_iovcnt = iovcnt; fortune_ctx->iovec_list_iter = iovec_list; fortune_ctx->result = sort_fortunes(fortune_ctx->result); if (mustache_render(&api, fortune_ctx, ctx->global_data->fortunes_template)) { fortune_ctx->iovec_list = iovec_list->l.next; set_default_response_param(HTML, fortune_ctx->content_length, fortune_ctx->req); h2o_start_response(fortune_ctx->req, &fortune_ctx->generator); const h2o_send_state_t state = fortune_ctx->iovec_list ? H2O_SEND_STATE_IN_PROGRESS : H2O_SEND_STATE_FINAL; h2o_send(fortune_ctx->req, iovec_list->iov, iovec_list->iovcnt, state); } else send_error(INTERNAL_SERVER_ERROR, REQ_ERROR, fortune_ctx->req); } return ret; }