webserv/webserv/http/HttpResponse.cpp

111 lines
2.7 KiB
C++

#include <webserv/http/HttpConstants.hpp> // for getStatusCodeReason
#include <webserv/http/HttpResponse.hpp>
#include <string> // for basic_string, operator+, string, char_traits, to_string
#include <vector> // for vector
HttpResponse::HttpResponse() : headers_(std::make_unique<HttpHeaders>()) {}
void HttpResponse::addHeader(const std::string &key, const std::string &value)
{
headers_->add(key, value);
}
void HttpResponse::appendBody(const std::vector<uint8_t> &data)
{
if (complete_)
{
Log::warning("Attempt to set body on a completed HttpResponse");
return;
}
body_.insert(body_.end(), data.begin(), data.end());
}
void HttpResponse::appendBody(const std::string &body)
{
if (complete_)
{
Log::warning("Attempt to set body on a completed HttpResponse");
return;
}
body_.insert(body_.end(), body.begin(), body.end());
}
void HttpResponse::setBody(const std::vector<uint8_t> &data) // TODO: validate headers
{
if (complete_)
{
Log::warning("Attempt to set body on a completed HttpResponse");
return;
}
body_ = data;
setComplete();
}
void HttpResponse::setBody(const std::string &body)
{
body_.assign(body.begin(), body.end());
setComplete();
}
void HttpResponse::setStatus(uint16_t statusCode)
{
statusCode_ = statusCode;
}
void HttpResponse::setComplete()
{
complete_ = true;
}
void HttpResponse::setError(uint16_t statusCode)
{
statusCode_ = statusCode;
complete_ = true;
}
bool HttpResponse::isComplete() const noexcept
{
return complete_;
}
const HttpHeaders &HttpResponse::getHeaders() const noexcept
{
return *headers_;
}
std::string HttpResponse::getContentLengthHeader() const
{
return "Content-Length: " + std::to_string(body_.size()) + "\r\n";
}
std::string HttpResponse::getDateHeader() const
{
time_t now = time(nullptr);
struct tm *gmt = gmtime(&now);
char buffer[100];
strftime(buffer, sizeof(buffer), "%a, %d %b %Y %H:%M:%S GMT", gmt);
return "Date: " + std::string(buffer) + "\r\n";
}
std::vector<uint8_t> HttpResponse::toBytes(long offset) const
{
std::string headerStr;
std::string reason;
reason = Http::getStatusCodeReason(statusCode_);
headerStr = "HTTP/1.1 " + std::to_string(statusCode_) + " " + reason + "\r\n"; // todo: status line
headerStr += getContentLengthHeader();
headerStr += getDateHeader();
headerStr += "Connection: close\r\n";
headerStr += "Server: Webserv/1.0\r\n";
headerStr += headers_->toString();
std::vector<uint8_t> responseData(headerStr.begin(), headerStr.end());
responseData.insert(responseData.end(), body_.begin(), body_.end());
return {responseData.begin() + offset, responseData.end()};
}