mirror of
https://github.com/drogonframework/drogon.git
synced 2025-09-22 00:00:33 -04:00
Add the setCustomStatusCode method
This commit is contained in:
parent
c6b65485e1
commit
b654e35e51
@ -105,6 +105,11 @@ class DROGON_EXPORT HttpResponse
|
||||
/// Set the status code of the response.
|
||||
virtual void setStatusCode(HttpStatusCode code) = 0;
|
||||
|
||||
void setCustomStatusCode(int code, string_view message = string_view{})
|
||||
{
|
||||
setCustomStatusCode(code, message.data(), message.length());
|
||||
}
|
||||
|
||||
/// Get the creation timestamp of the response.
|
||||
virtual const trantor::Date &creationDate() const = 0;
|
||||
const trantor::Date &getCreationDate() const
|
||||
@ -391,6 +396,9 @@ class DROGON_EXPORT HttpResponse
|
||||
virtual void setContentTypeCodeAndCustomString(ContentType type,
|
||||
const char *typeString,
|
||||
size_t typeStringLength) = 0;
|
||||
virtual void setCustomStatusCode(int code,
|
||||
const char *message,
|
||||
size_t messageLength) = 0;
|
||||
};
|
||||
template <>
|
||||
inline HttpResponsePtr toResponse<const Json::Value &>(const Json::Value &pJson)
|
||||
|
@ -19,10 +19,11 @@ namespace drogon
|
||||
{
|
||||
enum HttpStatusCode
|
||||
{
|
||||
// rfc2616-6.1.1
|
||||
kUnknown = 0,
|
||||
k100Continue = 100,
|
||||
k101SwitchingProtocols = 101,
|
||||
k102Processing = 102,
|
||||
k103EarlyHints = 103,
|
||||
k200OK = 200,
|
||||
k201Created = 201,
|
||||
k202Accepted = 202,
|
||||
@ -30,12 +31,16 @@ enum HttpStatusCode
|
||||
k204NoContent = 204,
|
||||
k205ResetContent = 205,
|
||||
k206PartialContent = 206,
|
||||
k207MultiStatus = 207,
|
||||
k208AlreadyReported = 208,
|
||||
k226IMUsed = 226,
|
||||
k300MultipleChoices = 300,
|
||||
k301MovedPermanently = 301,
|
||||
k302Found = 302,
|
||||
k303SeeOther = 303,
|
||||
k304NotModified = 304,
|
||||
k305UseProxy = 305,
|
||||
k306Unused = 306,
|
||||
k307TemporaryRedirect = 307,
|
||||
k308PermanentRedirect = 308,
|
||||
k400BadRequest = 400,
|
||||
@ -58,6 +63,9 @@ enum HttpStatusCode
|
||||
k417ExpectationFailed = 417,
|
||||
k418ImATeapot = 418,
|
||||
k421MisdirectedRequest = 421,
|
||||
k422UnprocessableEntity = 422,
|
||||
k423Locked = 423,
|
||||
k424FailedDependency = 424,
|
||||
k425TooEarly = 425,
|
||||
k426UpgradeRequired = 426,
|
||||
k428PreconditionRequired = 428,
|
||||
@ -70,7 +78,11 @@ enum HttpStatusCode
|
||||
k503ServiceUnavailable = 503,
|
||||
k504GatewayTimeout = 504,
|
||||
k505HTTPVersionNotSupported = 505,
|
||||
k506VariantAlsoNegotiates = 506,
|
||||
k507InsufficientStorage = 507,
|
||||
k508LoopDetected = 508,
|
||||
k510NotExtended = 510,
|
||||
k511NetworkAuthenticationRequired = 511
|
||||
};
|
||||
|
||||
enum class Version
|
||||
|
@ -19,7 +19,7 @@
|
||||
#include <drogon/IOThreadStorage.h>
|
||||
#include <fstream>
|
||||
#include <memory>
|
||||
#include <stdio.h>
|
||||
#include <cstdio>
|
||||
#include <sys/stat.h>
|
||||
#include <trantor/utils/Logger.h>
|
||||
#ifdef _WIN32
|
||||
@ -159,8 +159,7 @@ HttpResponsePtr HttpResponse::newNotFoundResponse()
|
||||
{
|
||||
if (HttpAppFrameworkImpl::instance().isUsingCustomErrorHandler())
|
||||
{
|
||||
auto resp = app().getCustomErrorHandler()(k404NotFound);
|
||||
return resp;
|
||||
return app().getCustomErrorHandler()(k404NotFound);
|
||||
}
|
||||
HttpViewData data;
|
||||
data.insert("version", drogon::getVersion());
|
||||
@ -245,8 +244,8 @@ HttpResponsePtr HttpResponse::newFileResponse(
|
||||
}
|
||||
auto resp = std::make_shared<HttpResponseImpl>();
|
||||
std::streambuf *pbuf = infile.rdbuf();
|
||||
std::streamsize filesize = pbuf->pubseekoff(0, infile.end);
|
||||
pbuf->pubseekoff(0, infile.beg); // rewind
|
||||
std::streamsize filesize = pbuf->pubseekoff(0, std::ifstream::end);
|
||||
pbuf->pubseekoff(0, std::ifstream::beg); // rewind
|
||||
if (HttpAppFrameworkImpl::instance().useSendfile() && filesize > 1024 * 200)
|
||||
// TODO : Is 200k an appropriate value? Or set it to be configurable
|
||||
{
|
||||
@ -295,17 +294,37 @@ void HttpResponseImpl::makeHeaderString(trantor::MsgBuffer &buffer)
|
||||
int len{0};
|
||||
if (version_ == Version::kHttp11)
|
||||
{
|
||||
len = snprintf(buffer.beginWrite(),
|
||||
buffer.writableBytes(),
|
||||
"HTTP/1.1 %d ",
|
||||
statusCode_);
|
||||
if (customStatusCode_ >= 0)
|
||||
{
|
||||
len = snprintf(buffer.beginWrite(),
|
||||
buffer.writableBytes(),
|
||||
"HTTP/1.1 %d ",
|
||||
customStatusCode_);
|
||||
}
|
||||
else
|
||||
{
|
||||
len = snprintf(buffer.beginWrite(),
|
||||
buffer.writableBytes(),
|
||||
"HTTP/1.1 %d ",
|
||||
statusCode_);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
len = snprintf(buffer.beginWrite(),
|
||||
buffer.writableBytes(),
|
||||
"HTTP/1.0 %d ",
|
||||
statusCode_);
|
||||
if (customStatusCode_ >= 0)
|
||||
{
|
||||
len = snprintf(buffer.beginWrite(),
|
||||
buffer.writableBytes(),
|
||||
"HTTP/1.0 %d ",
|
||||
customStatusCode_);
|
||||
}
|
||||
else
|
||||
{
|
||||
len = snprintf(buffer.beginWrite(),
|
||||
buffer.writableBytes(),
|
||||
"HTTP/1.0 %d ",
|
||||
statusCode_);
|
||||
}
|
||||
}
|
||||
buffer.hasWritten(len);
|
||||
|
||||
@ -326,7 +345,9 @@ void HttpResponseImpl::makeHeaderString(trantor::MsgBuffer &buffer)
|
||||
}
|
||||
else
|
||||
{
|
||||
struct stat filestat;
|
||||
struct stat filestat
|
||||
{
|
||||
};
|
||||
if (stat(sendfileName_.data(), &filestat) < 0)
|
||||
{
|
||||
LOG_SYSERR << sendfileName_ << " stat error";
|
||||
@ -385,7 +406,7 @@ void HttpResponseImpl::renderToBuffer(trantor::MsgBuffer &buffer)
|
||||
}
|
||||
|
||||
// output cookies
|
||||
if (cookies_.size() > 0)
|
||||
if (!cookies_.empty())
|
||||
{
|
||||
for (auto it = cookies_.begin(); it != cookies_.end(); ++it)
|
||||
{
|
||||
@ -457,7 +478,7 @@ std::shared_ptr<trantor::MsgBuffer> HttpResponseImpl::renderToBuffer()
|
||||
}
|
||||
|
||||
// output cookies
|
||||
if (cookies_.size() > 0)
|
||||
if (!cookies_.empty())
|
||||
{
|
||||
for (auto it = cookies_.begin(); it != cookies_.end(); ++it)
|
||||
{
|
||||
@ -506,7 +527,7 @@ std::shared_ptr<trantor::MsgBuffer> HttpResponseImpl::
|
||||
}
|
||||
|
||||
// output cookies
|
||||
if (cookies_.size() > 0)
|
||||
if (!cookies_.empty())
|
||||
{
|
||||
for (auto it = cookies_.begin(); it != cookies_.end(); ++it)
|
||||
{
|
||||
@ -698,10 +719,6 @@ void HttpResponseImpl::parseJson() const
|
||||
}
|
||||
}
|
||||
|
||||
HttpResponseImpl::~HttpResponseImpl()
|
||||
{
|
||||
}
|
||||
|
||||
bool HttpResponseImpl::shouldBeCompressed() const
|
||||
{
|
||||
if (!sendfileName_.empty() ||
|
||||
|
@ -47,27 +47,27 @@ class DROGON_EXPORT HttpResponseImpl : public HttpResponse
|
||||
contentTypeString_(webContentTypeToString(type))
|
||||
{
|
||||
}
|
||||
virtual void setPassThrough(bool flag) override
|
||||
void setPassThrough(bool flag) override
|
||||
{
|
||||
passThrough_ = flag;
|
||||
}
|
||||
virtual HttpStatusCode statusCode() const override
|
||||
HttpStatusCode statusCode() const override
|
||||
{
|
||||
return statusCode_;
|
||||
}
|
||||
|
||||
virtual const trantor::Date &creationDate() const override
|
||||
const trantor::Date &creationDate() const override
|
||||
{
|
||||
return creationDate_;
|
||||
}
|
||||
|
||||
virtual void setStatusCode(HttpStatusCode code) override
|
||||
void setStatusCode(HttpStatusCode code) override
|
||||
{
|
||||
statusCode_ = code;
|
||||
setStatusMessage(statusCodeToString(code));
|
||||
}
|
||||
|
||||
virtual void setVersion(const Version v) override
|
||||
void setVersion(const Version v) override
|
||||
{
|
||||
version_ = v;
|
||||
if (version_ == Version::kHttp10)
|
||||
@ -76,42 +76,42 @@ class DROGON_EXPORT HttpResponseImpl : public HttpResponse
|
||||
}
|
||||
}
|
||||
|
||||
virtual Version version() const override
|
||||
Version version() const override
|
||||
{
|
||||
return version_;
|
||||
}
|
||||
|
||||
virtual void setCloseConnection(bool on) override
|
||||
void setCloseConnection(bool on) override
|
||||
{
|
||||
closeConnection_ = on;
|
||||
}
|
||||
|
||||
virtual bool ifCloseConnection() const override
|
||||
bool ifCloseConnection() const override
|
||||
{
|
||||
return closeConnection_;
|
||||
}
|
||||
|
||||
virtual void setContentTypeCode(ContentType type) override
|
||||
void setContentTypeCode(ContentType type) override
|
||||
{
|
||||
contentType_ = type;
|
||||
setContentType(webContentTypeToString(type));
|
||||
flagForParsingContentType_ = true;
|
||||
}
|
||||
|
||||
// virtual void setContentTypeCodeAndCharacterSet(ContentType type, const
|
||||
// void setContentTypeCodeAndCharacterSet(ContentType type, const
|
||||
// std::string &charSet = "utf-8") override
|
||||
// {
|
||||
// contentType_ = type;
|
||||
// setContentType(webContentTypeAndCharsetToString(type, charSet));
|
||||
// }
|
||||
|
||||
virtual ContentType contentType() const override
|
||||
ContentType contentType() const override
|
||||
{
|
||||
if (!flagForParsingContentType_)
|
||||
{
|
||||
flagForParsingContentType_ = true;
|
||||
auto &contentTypeString = getHeaderBy("content-type");
|
||||
if (contentTypeString == "")
|
||||
if (contentTypeString.empty())
|
||||
{
|
||||
contentType_ = CT_NONE;
|
||||
}
|
||||
@ -133,20 +133,19 @@ class DROGON_EXPORT HttpResponseImpl : public HttpResponse
|
||||
return contentType_;
|
||||
}
|
||||
|
||||
virtual const std::string &getHeader(std::string key) const override
|
||||
const std::string &getHeader(std::string key) const override
|
||||
{
|
||||
transform(key.begin(), key.end(), key.begin(), ::tolower);
|
||||
return getHeaderBy(key);
|
||||
}
|
||||
|
||||
virtual void removeHeader(std::string key) override
|
||||
void removeHeader(std::string key) override
|
||||
{
|
||||
transform(key.begin(), key.end(), key.begin(), ::tolower);
|
||||
removeHeaderBy(key);
|
||||
}
|
||||
|
||||
virtual const std::unordered_map<std::string, std::string> &headers()
|
||||
const override
|
||||
const std::unordered_map<std::string, std::string> &headers() const override
|
||||
{
|
||||
return headers_;
|
||||
}
|
||||
@ -168,14 +167,14 @@ class DROGON_EXPORT HttpResponseImpl : public HttpResponse
|
||||
headers_.erase(lowerKey);
|
||||
}
|
||||
|
||||
virtual void addHeader(std::string field, const std::string &value) override
|
||||
void addHeader(std::string field, const std::string &value) override
|
||||
{
|
||||
fullHeaderString_.reset();
|
||||
transform(field.begin(), field.end(), field.begin(), ::tolower);
|
||||
headers_[std::move(field)] = value;
|
||||
}
|
||||
|
||||
virtual void addHeader(std::string field, std::string &&value) override
|
||||
void addHeader(std::string field, std::string &&value) override
|
||||
{
|
||||
fullHeaderString_.reset();
|
||||
transform(field.begin(), field.end(), field.begin(), ::tolower);
|
||||
@ -184,23 +183,22 @@ class DROGON_EXPORT HttpResponseImpl : public HttpResponse
|
||||
|
||||
void addHeader(const char *start, const char *colon, const char *end);
|
||||
|
||||
virtual void addCookie(const std::string &key,
|
||||
const std::string &value) override
|
||||
void addCookie(const std::string &key, const std::string &value) override
|
||||
{
|
||||
cookies_[key] = Cookie(key, value);
|
||||
}
|
||||
|
||||
virtual void addCookie(const Cookie &cookie) override
|
||||
void addCookie(const Cookie &cookie) override
|
||||
{
|
||||
cookies_[cookie.key()] = cookie;
|
||||
}
|
||||
|
||||
virtual void addCookie(Cookie &&cookie) override
|
||||
void addCookie(Cookie &&cookie) override
|
||||
{
|
||||
cookies_[cookie.key()] = std::move(cookie);
|
||||
}
|
||||
|
||||
virtual const Cookie &getCookie(const std::string &key) const override
|
||||
const Cookie &getCookie(const std::string &key) const override
|
||||
{
|
||||
static const Cookie defaultCookie;
|
||||
auto it = cookies_.find(key);
|
||||
@ -211,18 +209,17 @@ class DROGON_EXPORT HttpResponseImpl : public HttpResponse
|
||||
return defaultCookie;
|
||||
}
|
||||
|
||||
virtual const std::unordered_map<std::string, Cookie> &cookies()
|
||||
const override
|
||||
const std::unordered_map<std::string, Cookie> &cookies() const override
|
||||
{
|
||||
return cookies_;
|
||||
}
|
||||
|
||||
virtual void removeCookie(const std::string &key) override
|
||||
void removeCookie(const std::string &key) override
|
||||
{
|
||||
cookies_.erase(key);
|
||||
}
|
||||
|
||||
virtual void setBody(const std::string &body) override
|
||||
void setBody(const std::string &body) override
|
||||
{
|
||||
bodyPtr_ = std::make_shared<HttpMessageStringBody>(body);
|
||||
if (passThrough_)
|
||||
@ -230,7 +227,7 @@ class DROGON_EXPORT HttpResponseImpl : public HttpResponse
|
||||
addHeader("content-length", std::to_string(bodyPtr_->length()));
|
||||
}
|
||||
}
|
||||
virtual void setBody(std::string &&body) override
|
||||
void setBody(std::string &&body) override
|
||||
{
|
||||
bodyPtr_ = std::make_shared<HttpMessageStringBody>(std::move(body));
|
||||
if (passThrough_)
|
||||
@ -246,9 +243,9 @@ class DROGON_EXPORT HttpResponseImpl : public HttpResponse
|
||||
std::shared_ptr<trantor::MsgBuffer> renderToBuffer();
|
||||
void renderToBuffer(trantor::MsgBuffer &buffer);
|
||||
std::shared_ptr<trantor::MsgBuffer> renderHeaderForHeadMethod();
|
||||
virtual void clear() override;
|
||||
void clear() override;
|
||||
|
||||
virtual void setExpiredTime(ssize_t expiredTime) override
|
||||
void setExpiredTime(ssize_t expiredTime) override
|
||||
{
|
||||
expriedTime_ = expiredTime;
|
||||
datePos_ = std::string::npos;
|
||||
@ -258,12 +255,12 @@ class DROGON_EXPORT HttpResponseImpl : public HttpResponse
|
||||
}
|
||||
}
|
||||
|
||||
virtual ssize_t expiredTime() const override
|
||||
ssize_t expiredTime() const override
|
||||
{
|
||||
return expriedTime_;
|
||||
}
|
||||
|
||||
virtual const char *getBodyData() const override
|
||||
const char *getBodyData() const override
|
||||
{
|
||||
if (!flagForSerializingJson_ && jsonPtr_)
|
||||
{
|
||||
@ -275,7 +272,7 @@ class DROGON_EXPORT HttpResponseImpl : public HttpResponse
|
||||
}
|
||||
return bodyPtr_->data();
|
||||
}
|
||||
virtual size_t getBodyLength() const override
|
||||
size_t getBodyLength() const override
|
||||
{
|
||||
if (bodyPtr_)
|
||||
return bodyPtr_->length();
|
||||
@ -284,7 +281,7 @@ class DROGON_EXPORT HttpResponseImpl : public HttpResponse
|
||||
|
||||
void swap(HttpResponseImpl &that) noexcept;
|
||||
void parseJson() const;
|
||||
virtual const std::shared_ptr<Json::Value> &jsonObject() const override
|
||||
const std::shared_ptr<Json::Value> &jsonObject() const override
|
||||
{
|
||||
// Not multi-thread safe but good, because we basically call this
|
||||
// function in a single thread
|
||||
@ -295,9 +292,9 @@ class DROGON_EXPORT HttpResponseImpl : public HttpResponse
|
||||
}
|
||||
return jsonPtr_;
|
||||
}
|
||||
virtual const std::string &getJsonError() const override
|
||||
const std::string &getJsonError() const override
|
||||
{
|
||||
const static std::string none{""};
|
||||
const static std::string none;
|
||||
if (jsonParsingErrorPtr_)
|
||||
return *jsonParsingErrorPtr_;
|
||||
return none;
|
||||
@ -356,13 +353,13 @@ class DROGON_EXPORT HttpResponseImpl : public HttpResponse
|
||||
}
|
||||
}
|
||||
#endif
|
||||
~HttpResponseImpl();
|
||||
~HttpResponseImpl() override = default;
|
||||
|
||||
protected:
|
||||
void makeHeaderString(trantor::MsgBuffer &headerString);
|
||||
|
||||
private:
|
||||
virtual void setBody(const char *body, size_t len) override
|
||||
void setBody(const char *body, size_t len) override
|
||||
{
|
||||
bodyPtr_ = std::make_shared<HttpMessageStringViewBody>(body, len);
|
||||
if (passThrough_)
|
||||
@ -370,19 +367,28 @@ class DROGON_EXPORT HttpResponseImpl : public HttpResponse
|
||||
addHeader("content-length", std::to_string(bodyPtr_->length()));
|
||||
}
|
||||
}
|
||||
virtual void setContentTypeCodeAndCustomString(
|
||||
ContentType type,
|
||||
const char *typeString,
|
||||
size_t typeStringLength) override
|
||||
void setContentTypeCodeAndCustomString(ContentType type,
|
||||
const char *typeString,
|
||||
size_t typeStringLength) override
|
||||
{
|
||||
contentType_ = type;
|
||||
flagForParsingContentType_ = true;
|
||||
setContentType(string_view{typeString, typeStringLength});
|
||||
}
|
||||
|
||||
void setCustomStatusCode(int code,
|
||||
const char *message,
|
||||
size_t messageLength) override
|
||||
{
|
||||
assert(code >= 0);
|
||||
customStatusCode_ = code;
|
||||
statusMessage_ = string_view{message, messageLength};
|
||||
}
|
||||
|
||||
std::unordered_map<std::string, std::string> headers_;
|
||||
std::unordered_map<std::string, Cookie> cookies_;
|
||||
|
||||
int customStatusCode_{-1};
|
||||
HttpStatusCode statusCode_{kUnknown};
|
||||
string_view statusMessage_;
|
||||
|
||||
|
@ -186,6 +186,16 @@ const string_view &statusCodeToString(int code)
|
||||
static string_view sv = "Switching Protocols";
|
||||
return sv;
|
||||
}
|
||||
case 102:
|
||||
{
|
||||
static string_view sv = "Processing";
|
||||
return sv;
|
||||
}
|
||||
case 103:
|
||||
{
|
||||
static string_view sv = "Early Hints";
|
||||
return sv;
|
||||
}
|
||||
case 200:
|
||||
{
|
||||
static string_view sv = "OK";
|
||||
@ -221,6 +231,21 @@ const string_view &statusCodeToString(int code)
|
||||
static string_view sv = "Partial Content";
|
||||
return sv;
|
||||
}
|
||||
case 207:
|
||||
{
|
||||
static string_view sv = "Multi-Status";
|
||||
return sv;
|
||||
}
|
||||
case 208:
|
||||
{
|
||||
static string_view sv = "Already Reported";
|
||||
return sv;
|
||||
}
|
||||
case 226:
|
||||
{
|
||||
static string_view sv = "IM Used";
|
||||
return sv;
|
||||
}
|
||||
case 300:
|
||||
{
|
||||
static string_view sv = "Multiple Choices";
|
||||
@ -251,6 +276,11 @@ const string_view &statusCodeToString(int code)
|
||||
static string_view sv = "Use Proxy";
|
||||
return sv;
|
||||
}
|
||||
case 306:
|
||||
{
|
||||
static string_view sv = "(Unused)";
|
||||
return sv;
|
||||
}
|
||||
case 307:
|
||||
{
|
||||
static string_view sv = "Temporary Redirect";
|
||||
@ -361,6 +391,21 @@ const string_view &statusCodeToString(int code)
|
||||
static string_view sv = "Misdirected Request";
|
||||
return sv;
|
||||
}
|
||||
case 422:
|
||||
{
|
||||
static string_view sv = "Unprocessable Entity";
|
||||
return sv;
|
||||
}
|
||||
case 423:
|
||||
{
|
||||
static string_view sv = "Locked";
|
||||
return sv;
|
||||
}
|
||||
case 424:
|
||||
{
|
||||
static string_view sv = "Failed Dependency";
|
||||
return sv;
|
||||
}
|
||||
case 425:
|
||||
{
|
||||
static string_view sv = "Too Early";
|
||||
@ -421,11 +466,31 @@ const string_view &statusCodeToString(int code)
|
||||
static string_view sv = "HTTP Version Not Supported";
|
||||
return sv;
|
||||
}
|
||||
case 506:
|
||||
{
|
||||
static string_view sv = "Variant Also Negotiates";
|
||||
return sv;
|
||||
}
|
||||
case 507:
|
||||
{
|
||||
static string_view sv = "Insufficient Storage";
|
||||
return sv;
|
||||
}
|
||||
case 508:
|
||||
{
|
||||
static string_view sv = "Loop Detected";
|
||||
return sv;
|
||||
}
|
||||
case 510:
|
||||
{
|
||||
static string_view sv = "Not Extended";
|
||||
return sv;
|
||||
}
|
||||
case 511:
|
||||
{
|
||||
static string_view sv = "Network Authentication Required";
|
||||
return sv;
|
||||
}
|
||||
default:
|
||||
if (code >= 100 && code < 200)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user