Support HTTP1.0 clients (#320)

This commit is contained in:
An Tao 2019-12-22 13:15:56 +08:00 committed by GitHub
parent 4809cc9508
commit 27c687a0af
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 78 additions and 32 deletions

View File

@ -102,12 +102,6 @@ class HttpRequest
return fromRequest<T>(*this);
}
enum Version
{
kUnknown = 0,
kHttp10 = 1,
kHttp11 = 2
};
/// Return the method string of the request, such as GET, POST, etc.
virtual const char *methodString() const = 0;
const char *getMethodString() const

View File

@ -254,6 +254,19 @@ class HttpResponse
return body();
}
/// Return the enum type version of the response.
/**
* kHttp10 means Http version is 1.0
* kHttp11 means Http verison is 1.1
*/
virtual Version version() const = 0;
/// Return the enum type version of the response.
Version getVersion() const
{
return version();
}
/// Reset the reponse object to its initial state
virtual void clear() = 0;

View File

@ -63,8 +63,9 @@ enum HttpStatusCode
k505HTTPVersionnotsupported = 505,
};
enum Version
enum class Version
{
kUnknown = 0,
kHttp10,
kHttp11
};

View File

@ -581,6 +581,14 @@ void HttpAppFrameworkImpl::callCallback(
return;
}
}
else if (resp->version() != req->version())
{
auto newResp = std::make_shared<HttpResponseImpl>(
*static_cast<HttpResponseImpl *>(resp.get()));
newResp->setExpiredTime(-1); // make it temporary
callback(newResp);
return;
}
else
{
callback(resp);

View File

@ -25,7 +25,7 @@ HttpFileUploadRequest::HttpFileUploadRequest(
files_(files)
{
setMethod(drogon::Post);
setVersion(drogon::HttpRequest::kHttp11);
setVersion(drogon::Version::kHttp11);
setContentType("Content-Type: multipart/form-data; boundary=" + boundary_ +
"\r\n");
contentType_ = CT_MULTIPART_FORM_DATA;

View File

@ -231,11 +231,11 @@ void HttpRequestImpl::appendToBuffer(trantor::MsgBuffer *output) const
}
output->append(" ");
if (version_ == kHttp11)
if (version_ == Version::kHttp11)
{
output->append("HTTP/1.1");
}
else if (version_ == kHttp10)
else if (version_ == Version::kHttp10)
{
output->append("HTTP/1.0");
}
@ -410,7 +410,7 @@ void HttpRequestImpl::addHeader(const char *start,
{
if (field == "connection")
{
if (version_ == kHttp11)
if (version_ == Version::kHttp11)
{
if (value.length() == 5 && value == "close")
keepAlive_ = false;
@ -440,7 +440,7 @@ HttpRequestPtr HttpRequest::newHttpRequest()
{
auto req = std::make_shared<HttpRequestImpl>(nullptr);
req->setMethod(drogon::Get);
req->setVersion(drogon::HttpRequest::kHttp11);
req->setVersion(drogon::Version::kHttp11);
return req;
}
@ -448,7 +448,7 @@ HttpRequestPtr HttpRequest::newHttpFormPostRequest()
{
auto req = std::make_shared<HttpRequestImpl>(nullptr);
req->setMethod(drogon::Post);
req->setVersion(drogon::HttpRequest::kHttp11);
req->setVersion(drogon::Version::kHttp11);
req->contentType_ = CT_APPLICATION_X_FORM;
return req;
}
@ -463,7 +463,7 @@ HttpRequestPtr HttpRequest::newHttpJsonRequest(const Json::Value &data)
});
auto req = std::make_shared<HttpRequestImpl>(nullptr);
req->setMethod(drogon::Get);
req->setVersion(drogon::HttpRequest::kHttp11);
req->setVersion(drogon::Version::kHttp11);
req->contentType_ = CT_APPLICATION_JSON;
req->setContent(writeString(builder, data));
return req;

View File

@ -45,7 +45,7 @@ class HttpRequestImpl : public HttpRequest
void reset()
{
method_ = Invalid;
version_ = kUnknown;
version_ = Version::kUnknown;
contentLen_ = 0;
flagForParsingJson_ = false;
headers_.clear();
@ -73,7 +73,7 @@ class HttpRequestImpl : public HttpRequest
void setVersion(Version v)
{
version_ = v;
if (v == kHttp10)
if (version_ == Version::kHttp10)
{
keepAlive_ = false;
}
@ -453,7 +453,7 @@ class HttpRequestImpl : public HttpRequest
mutable bool flagForParsingParameters_{false};
mutable bool flagForParsingJson_{false};
HttpMethod method_{Invalid};
Version version_{kUnknown};
Version version_{Version::kUnknown};
std::string path_;
string_view matchedPathPattern_{""};
std::string query_;

View File

@ -68,11 +68,11 @@ bool HttpRequestParser::processRequestLine(const char *begin, const char *end)
{
if (*(end - 1) == '1')
{
request_->setVersion(HttpRequest::kHttp11);
request_->setVersion(Version::kHttp11);
}
else if (*(end - 1) == '0')
{
request_->setVersion(HttpRequest::kHttp10);
request_->setVersion(Version::kHttp10);
}
else
{
@ -223,7 +223,7 @@ bool HttpRequestParser::parseRequest(MsgBuffer *buf)
auto &expect = request_->expect();
if (expect == "100-continue" &&
request_->getVersion() >= HttpRequest::kHttp11)
request_->getVersion() >= Version::kHttp11)
{
if (request_->contentLen_ == 0)
{

View File

@ -108,7 +108,7 @@ HttpResponsePtr HttpResponse::newNotFoundResponse()
thread404Pages.init([](drogon::HttpResponsePtr &resp,
size_t index) {
HttpViewData data;
data.insert("version", getVersion());
data.insert("version", drogon::getVersion());
resp = HttpResponse::newHttpViewResponse("drogon::NotFound",
data);
resp->setStatusCode(k404NotFound);
@ -121,7 +121,7 @@ HttpResponsePtr HttpResponse::newNotFoundResponse()
else
{
HttpViewData data;
data.insert("version", getVersion());
data.insert("version", drogon::getVersion());
auto notFoundResp =
HttpResponse::newHttpViewResponse("drogon::NotFound", data);
notFoundResp->setStatusCode(k404NotFound);
@ -208,8 +208,17 @@ void HttpResponseImpl::makeHeaderString(
{
char buf[128];
assert(headerStringPtr);
auto len = snprintf(buf, sizeof buf, "HTTP/1.1 %d ", statusCode_);
int len{0};
if (version_ == Version::kHttp11)
{
len = snprintf(buf, sizeof buf, "HTTP/1.1 %d ", statusCode_);
}
else
{
len = snprintf(buf, sizeof buf, "HTTP/1.0 %d ", statusCode_);
}
headerStringPtr->append(buf, len);
if (!statusMessage_.empty())
headerStringPtr->append(statusMessage_.data(), statusMessage_.length());
headerStringPtr->append("\r\n");
@ -248,9 +257,9 @@ void HttpResponseImpl::makeHeaderString(
{
headerStringPtr->append("Connection: close\r\n");
}
else
else if (version_ == Version::kHttp10)
{
// output->append("Connection: Keep-Alive\r\n");
headerStringPtr->append("Connection: Keep-Alive\r\n");
}
}
headerStringPtr->append(contentTypeString_.data(),
@ -282,8 +291,17 @@ void HttpResponseImpl::renderToBuffer(trantor::MsgBuffer &buffer)
if (!fullHeaderString_)
{
char buf[128];
auto len = snprintf(buf, sizeof buf, "HTTP/1.1 %d ", statusCode_);
int len{0};
if (version_ == Version::kHttp11)
{
len = snprintf(buf, sizeof buf, "HTTP/1.1 %d ", statusCode_);
}
else
{
len = snprintf(buf, sizeof buf, "HTTP/1.0 %d ", statusCode_);
}
buffer.append(buf, len);
if (!statusMessage_.empty())
buffer.append(statusMessage_.data(), statusMessage_.length());
buffer.append("\r\n");
@ -322,9 +340,9 @@ void HttpResponseImpl::renderToBuffer(trantor::MsgBuffer &buffer)
{
buffer.append("Connection: close\r\n");
}
else
else if (version_ == Version::kHttp10)
{
// output->append("Connection: Keep-Alive\r\n");
buffer.append("Connection: Keep-Alive\r\n");
}
}
buffer.append(contentTypeString_.data(),
@ -616,7 +634,7 @@ void HttpResponseImpl::swap(HttpResponseImpl &that) noexcept
void HttpResponseImpl::clear()
{
statusCode_ = kUnknown;
version_ = kHttp11;
version_ = Version::kHttp11;
statusMessage_ = string_view{};
fullHeaderString_.reset();
headers_.clear();

View File

@ -67,6 +67,15 @@ class HttpResponseImpl : public HttpResponse
virtual void setVersion(const Version v) override
{
version_ = v;
if (version_ == Version::kHttp10)
{
closeConnection_ = true;
}
}
virtual Version version() const override
{
return version_;
}
virtual void setCloseConnection(bool on) override
@ -347,7 +356,7 @@ class HttpResponseImpl : public HttpResponse
string_view statusMessage_;
trantor::Date creationDate_;
Version version_;
Version version_{Version::kHttp11};
bool closeConnection_{false};
size_t leftBodyLength_{0};

View File

@ -42,11 +42,11 @@ bool HttpResponseParser::processResponseLine(const char *begin, const char *end)
LOG_TRACE << *(space - 1);
if (*(space - 1) == '1')
{
responsePtr_->setVersion(kHttp11);
responsePtr_->setVersion(Version::kHttp11);
}
else if (*(space - 1) == '0')
{
responsePtr_->setVersion(kHttp10);
responsePtr_->setVersion(Version::kHttp10);
}
else
{

View File

@ -294,6 +294,7 @@ void HttpServer::onRequests(
auto resp = advice(req);
if (resp)
{
resp->setVersion(req->getVersion());
if (!syncFlag)
{
requestParser->getResponseBuffer().emplace_back(
@ -329,6 +330,8 @@ void HttpServer::onRequests(
return;
if (!conn->connected())
return;
response->setVersion(req->getVersion());
response->setCloseConnection(close_);
auto newResp =
getCompressedResponse(req, response, isHeadMethod);