Delay parsing parameters untils needed

This commit is contained in:
antao 2019-03-05 11:08:14 +08:00
parent bbd840bd3b
commit 7232536aee
3 changed files with 36 additions and 21 deletions

View File

@ -21,7 +21,7 @@
using namespace drogon; using namespace drogon;
void HttpRequestImpl::parseParameter() void HttpRequestImpl::parseParameters() const
{ {
const std::string &input = query(); const std::string &input = query();
if (input.empty()) if (input.empty())

View File

@ -30,6 +30,7 @@
#include <stdio.h> #include <stdio.h>
#include <algorithm> #include <algorithm>
#include <string> #include <string>
#include <thread>
using std::string; using std::string;
using namespace trantor; using namespace trantor;
@ -63,8 +64,6 @@ class HttpRequestImpl : public HttpRequest
return _version; return _version;
} }
void parseParameter();
bool setMethod(const char *start, const char *end) bool setMethod(const char *start, const char *end)
{ {
@ -159,11 +158,13 @@ class HttpRequestImpl : public HttpRequest
virtual const std::unordered_map<std::string, std::string> &getParameters() const override virtual const std::unordered_map<std::string, std::string> &getParameters() const override
{ {
parseParametersOnce();
return _parameters; return _parameters;
} }
virtual const std::string &getParameter(const std::string &key, const std::string &defaultVal = std::string()) const override virtual const std::string &getParameter(const std::string &key, const std::string &defaultVal = std::string()) const override
{ {
parseParametersOnce();
auto iter = _parameters.find(key); auto iter = _parameters.find(key);
if (iter != _parameters.end()) if (iter != _parameters.end())
return iter->second; return iter->second;
@ -280,6 +281,7 @@ class HttpRequestImpl : public HttpRequest
virtual void setParameter(const std::string &key, const std::string &value) override virtual void setParameter(const std::string &key, const std::string &value) override
{ {
_flagForParsingParameters = true;
_parameters[key] = value; _parameters[key] = value;
} }
@ -337,6 +339,7 @@ class HttpRequestImpl : public HttpRequest
virtual const std::shared_ptr<Json::Value> getJsonObject() const override virtual const std::shared_ptr<Json::Value> getJsonObject() const override
{ {
parseParametersOnce();
return _jsonPtr; return _jsonPtr;
} }
@ -370,14 +373,25 @@ class HttpRequestImpl : public HttpRequest
} }
private: private:
void parseParameters() const;
void parseParametersOnce() const
{
// Multi-thread is not safe but good enough
if(!_flagForParsingParameters)
{
_flagForParsingParameters = true;
parseParameters();
}
}
mutable bool _flagForParsingParameters=false;
HttpMethod _method; HttpMethod _method;
Version _version; Version _version;
std::string _path; std::string _path;
std::string _query; std::string _query;
std::unordered_map<std::string, std::string> _headers; std::unordered_map<std::string, std::string> _headers;
std::unordered_map<std::string, std::string> _cookies; std::unordered_map<std::string, std::string> _cookies;
std::unordered_map<std::string, std::string> _parameters; mutable std::unordered_map<std::string, std::string> _parameters;
std::shared_ptr<Json::Value> _jsonPtr; mutable std::shared_ptr<Json::Value> _jsonPtr;
SessionPtr _sessionPtr; SessionPtr _sessionPtr;
trantor::InetAddress _peer; trantor::InetAddress _peer;
trantor::InetAddress _local; trantor::InetAddress _local;

View File

@ -103,28 +103,26 @@ void HttpServer::onMessage(const TcpConnectionPtr &conn,
MsgBuffer *buf) MsgBuffer *buf)
{ {
HttpRequestParser *requestParser = any_cast<HttpRequestParser>(conn->getMutableContext()); HttpRequestParser *requestParser = any_cast<HttpRequestParser>(conn->getMutableContext());
int counter = 0;
// LOG_INFO << "###:" << string(buf->peek(), buf->readableBytes()); // With the pipelining feature or web socket, it is possible to receice multiple messages at once, so
if (requestParser->webSocketConn()) // the while loop is necessary
{
//websocket payload,we shouldn't parse it
_webSocketMessageCallback(requestParser->webSocketConn(), buf);
return;
}
int counter=0;
while (buf->readableBytes() > 0) while (buf->readableBytes() > 0)
{ {
if (requestParser->webSocketConn())
{
//Websocket payload,we shouldn't parse it
_webSocketMessageCallback(requestParser->webSocketConn(), buf);
return;
}
if (!requestParser->parseRequest(buf)) if (!requestParser->parseRequest(buf))
{ {
conn->send("HTTP/1.1 400 Bad Request\r\n\r\n"); conn->send("HTTP/1.1 400 Bad Request\r\n\r\n");
//conn->shutdown(); //conn->shutdown();
requestParser->reset(); requestParser->reset();
break; return;
} }
if (requestParser->gotAll()) if (requestParser->gotAll())
{ {
requestParser->requestImpl()->parseParameter();
requestParser->requestImpl()->setPeerAddr(conn->peerAddr()); requestParser->requestImpl()->setPeerAddr(conn->peerAddr());
requestParser->requestImpl()->setLocalAddr(conn->localAddr()); requestParser->requestImpl()->setLocalAddr(conn->localAddr());
requestParser->requestImpl()->setReceiveDate(trantor::Date::date()); requestParser->requestImpl()->setReceiveDate(trantor::Date::date());
@ -146,15 +144,16 @@ void HttpServer::onMessage(const TcpConnectionPtr &conn,
onRequest(conn, requestParser->requestImpl()); onRequest(conn, requestParser->requestImpl());
requestParser->reset(); requestParser->reset();
counter++; counter++;
if(counter>1) if (counter > 1)
LOG_WARN<<"HAHAHAHA, more than 1 req received!"<<counter; LOG_TRACE << "More than one requests are parsed (" << counter << ")";
} }
else else
{ {
break; return;
} }
} }
} }
bool HttpServer::isWebSocket(const TcpConnectionPtr &conn, const HttpRequestImplPtr &req) bool HttpServer::isWebSocket(const TcpConnectionPtr &conn, const HttpRequestImplPtr &req)
{ {
if (req->getHeaderBy("connection") == "Upgrade" && if (req->getHeaderBy("connection") == "Upgrade" &&
@ -166,6 +165,7 @@ bool HttpServer::isWebSocket(const TcpConnectionPtr &conn, const HttpRequestImpl
} }
return false; return false;
} }
void HttpServer::onRequest(const TcpConnectionPtr &conn, const HttpRequestImplPtr &req) void HttpServer::onRequest(const TcpConnectionPtr &conn, const HttpRequestImplPtr &req)
{ {
const std::string &connection = req->getHeaderBy("connection"); const std::string &connection = req->getHeaderBy("connection");
@ -299,6 +299,7 @@ void HttpServer::onRequest(const TcpConnectionPtr &conn, const HttpRequestImplPt
} }
}); });
} }
void HttpServer::sendResponse(const TcpConnectionPtr &conn, void HttpServer::sendResponse(const TcpConnectionPtr &conn,
const HttpResponsePtr &response, const HttpResponsePtr &response,
bool isHeadMethod) bool isHeadMethod)