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++
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_ = 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 Exception(kSchemaError, "Invalid request: 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
|