Get down to a single write call
This commit is contained in:
@@ -1,12 +1,14 @@
|
||||
#include <sys/uio.h>
|
||||
|
||||
#include "fastcgi_conn.h"
|
||||
|
||||
#include "fastcgi_request.h"
|
||||
|
||||
#include "fastcgi_conn.h"
|
||||
#include "fastcgi_parse.h"
|
||||
|
||||
FastCGIRequest::FastCGIRequest(uint16_t request_id, FastCGIConn* conn)
|
||||
: request_id_(request_id),
|
||||
conn_(conn) {}
|
||||
conn_(conn),
|
||||
out_buf_(fastcgi_max_record_len) {}
|
||||
|
||||
void FastCGIRequest::AddParam(const std::string_view& key, const std::string_view& value) {
|
||||
params_.try_emplace(std::string(key), std::string(value));
|
||||
@@ -20,49 +22,57 @@ const std::string& FastCGIRequest::GetParam(const std::string& key) {
|
||||
return params_.at(key);
|
||||
}
|
||||
|
||||
void FastCGIRequest::Write(const std::vector<std::pair<std::string_view, std::string_view>>& headers, const std::vector<std::string_view>& body) {
|
||||
std::vector<iovec> vecs;
|
||||
vecs.reserve((headers.size() * 4) + 1 + body.size());
|
||||
void FastCGIRequest::WriteHeader(const std::string_view& name, const std::string_view& value) {
|
||||
CHECK(!body_sent_);
|
||||
CHECK(out_buf_.Write(name));
|
||||
CHECK(out_buf_.Write(": "));
|
||||
CHECK(out_buf_.Write(value));
|
||||
CHECK(out_buf_.Write("\n"));
|
||||
}
|
||||
|
||||
CHECK(headers.empty() || !body_sent_);
|
||||
|
||||
for (const auto& header : headers) {
|
||||
vecs.push_back(iovec{
|
||||
.iov_base = const_cast<char*>(header.first.data()),
|
||||
.iov_len = header.first.size(),
|
||||
});
|
||||
vecs.push_back(iovec{
|
||||
.iov_base = const_cast<char*>(": "),
|
||||
.iov_len = 2,
|
||||
});
|
||||
vecs.push_back(iovec{
|
||||
.iov_base = const_cast<char*>(header.second.data()),
|
||||
.iov_len = header.second.size(),
|
||||
});
|
||||
vecs.push_back(iovec{
|
||||
.iov_base = const_cast<char*>("\n"),
|
||||
.iov_len = 1,
|
||||
});
|
||||
}
|
||||
|
||||
if (!body.empty() && !body_sent_) {
|
||||
void FastCGIRequest::WriteBody(const std::string_view& body) {
|
||||
if (!body_sent_) {
|
||||
CHECK(out_buf_.Write("\n"));
|
||||
body_sent_ = true;
|
||||
vecs.push_back(iovec{
|
||||
.iov_base = const_cast<char*>("\n"),
|
||||
.iov_len = 1,
|
||||
});
|
||||
}
|
||||
|
||||
for (const auto& chunk : body) {
|
||||
vecs.push_back(iovec{
|
||||
.iov_base = const_cast<char*>(chunk.data()),
|
||||
.iov_len = chunk.size(),
|
||||
});
|
||||
}
|
||||
|
||||
conn_->WriteOutput(request_id_, vecs);
|
||||
// TODO: make this able to span multiple packets
|
||||
CHECK(out_buf_.Write(body));
|
||||
}
|
||||
|
||||
void FastCGIRequest::WriteEnd() {
|
||||
conn_->WriteEnd(request_id_);
|
||||
void FastCGIRequest::End() {
|
||||
FastCGIHeader output_header;
|
||||
FastCGIHeader end_header;
|
||||
FastCGIEndRequest end;
|
||||
|
||||
const auto output_len = out_buf_.ReadMaxLen();
|
||||
|
||||
output_header.version = 1;
|
||||
output_header.type = 6;
|
||||
output_header.SetRequestId(request_id_);
|
||||
output_header.SetContentLength(output_len);
|
||||
|
||||
end_header.version = 1;
|
||||
end_header.type = 3;
|
||||
end_header.SetRequestId(request_id_);
|
||||
end_header.SetContentLength(sizeof(end));
|
||||
|
||||
std::vector<iovec> vecs{
|
||||
iovec{
|
||||
.iov_base = &output_header,
|
||||
.iov_len = sizeof(output_header),
|
||||
},
|
||||
iovec{
|
||||
.iov_base = (void *)(CHECK_NOTNULL(out_buf_.Read(output_len))),
|
||||
.iov_len = output_len,
|
||||
},
|
||||
{
|
||||
.iov_base = &end_header,
|
||||
.iov_len = sizeof(end_header),
|
||||
},
|
||||
{
|
||||
.iov_base = &end,
|
||||
.iov_len = sizeof(end),
|
||||
},
|
||||
};
|
||||
conn_->Write(vecs);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user