You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

100 lines
2.3 KiB
C++

#include "webcc/request.h"
#include "webcc/logger.h"
#include "webcc/utility.h"
namespace webcc {
// -----------------------------------------------------------------------------
namespace misc_strings {
// Literal strings can't be used because they have an extra '\0'.
const char CRLF[] = { '\r', '\n' };
const char DOUBLE_DASHES[] = { '-', '-' };
} // misc_strings
// -----------------------------------------------------------------------------
void Request::Prepare() {
CreateStartLine();
if (url_.port().empty()) {
SetHeader(headers::kHost, url_.host());
} else {
SetHeader(headers::kHost, url_.host() + ":" + url_.port());
}
if (form_parts_.empty()) {
Message::Prepare();
return;
}
// Multipart form data.
// Another choice to generate the boundary is like what Apache does.
// See: https://stackoverflow.com/a/5686863
if (boundary_.empty()) {
boundary_ = utility::RandomUuid();
}
SetContentType("multipart/form-data; boundary=" + boundary_);
Payload data_payload;
using boost::asio::buffer;
for (auto& part : form_parts_) {
// Boundary
data_payload.push_back(buffer(misc_strings::DOUBLE_DASHES));
data_payload.push_back(buffer(boundary_));
data_payload.push_back(buffer(misc_strings::CRLF));
part->Prepare(&data_payload);
}
// Boundary end
data_payload.push_back(buffer(misc_strings::DOUBLE_DASHES));
data_payload.push_back(buffer(boundary_));
data_payload.push_back(buffer(misc_strings::DOUBLE_DASHES));
data_payload.push_back(buffer(misc_strings::CRLF));
// Update Content-Length header.
std::size_t content_length = 0;
for (auto& buffer : data_payload) {
content_length += buffer.size();
}
SetContentLength(content_length);
// Prepare start line and headers.
Message::Prepare();
// Append payload of content data.
payload_.insert(payload_.end(), data_payload.begin(), data_payload.end());
}
void Request::CreateStartLine() {
if (!start_line_.empty()) {
return;
}
if (url_.host().empty()) {
throw Error{ Error::kSyntaxError, "Host is missing" };
}
std::string target = "/" + url_.path();
if (!url_.query().empty()) {
target += "?";
target += url_.query();
}
start_line_ = method_;
start_line_ += " ";
start_line_ += target;
start_line_ += " HTTP/1.1";
}
} // namespace webcc