Merge pull request #34 from an-tao/dev

Support gzip on the client side
This commit is contained in:
An Tao 2019-01-21 13:52:00 +08:00 committed by GitHub
commit 5780042f8f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 506 additions and 107 deletions

View File

@ -312,7 +312,7 @@ void doTest(const HttpClientPtr &client)
client->sendRequest(req, [=](ReqResult result, const HttpResponsePtr &resp) {
if (result == ReqResult::Ok)
{
if (resp->getBody().length() == 1754)
if (resp->getBody().length() == 5123)
{
outputGood(req);
}
@ -468,12 +468,16 @@ int main()
trantor::EventLoopThread loop[2];
loop[0].run();
loop[1].run();
auto client = HttpClient::newHttpClient("http://127.0.0.1:8848", loop[0].getLoop());
doTest(client);
// for (int i = 0; i < 100;i++)
{
auto client = HttpClient::newHttpClient("http://127.0.0.1:8848", loop[0].getLoop());
doTest(client);
#ifdef USE_OPENSSL
auto sslClient = HttpClient::newHttpClient("https://127.0.0.1:8849", loop[1].getLoop());
doTest(sslClient);
auto sslClient = HttpClient::newHttpClient("https://127.0.0.1:8849", loop[1].getLoop());
doTest(sslClient);
#endif
}
getchar();
loop[0].getLoop()->quit();
loop[1].getLoop()->quit();

View File

@ -18,6 +18,7 @@
#include <trantor/utils/Date.h>
#include <string>
#include <vector>
#include <memory>
namespace drogon
{
@ -64,6 +65,7 @@ int gzipCompress(const char *data, const size_t ndata,
char *zdata, size_t *nzdata);
int gzipDecompress(const char *zdata, const size_t nzdata,
char *data, size_t *ndata);
std::shared_ptr<std::string> gzipDecompress(const std::shared_ptr<std::string> &compressedData);
/// Get the http full date string
/**

View File

@ -609,24 +609,24 @@ void HttpAppFrameworkImpl::onAsyncRequest(const HttpRequestImplPtr &req, std::fu
LOG_TRACE << "http path=" << req->path();
// LOG_TRACE << "query: " << req->query() ;
std::string session_id = req->getCookie("JSESSIONID");
std::string sessionId = req->getCookie("JSESSIONID");
bool needSetJsessionid = false;
if (_useSession)
{
if (session_id == "")
if (sessionId == "")
{
session_id = getuuid().c_str();
sessionId = getuuid().c_str();
needSetJsessionid = true;
_sessionMapPtr->insert(session_id, std::make_shared<Session>(), _sessionTimeout);
_sessionMapPtr->insert(sessionId, std::make_shared<Session>(), _sessionTimeout);
}
else
{
if (_sessionMapPtr->find(session_id) == false)
if (_sessionMapPtr->find(sessionId) == false)
{
_sessionMapPtr->insert(session_id, std::make_shared<Session>(), _sessionTimeout);
_sessionMapPtr->insert(sessionId, std::make_shared<Session>(), _sessionTimeout);
}
}
(std::dynamic_pointer_cast<HttpRequestImpl>(req))->setSession((*_sessionMapPtr)[session_id]);
(std::dynamic_pointer_cast<HttpRequestImpl>(req))->setSession((*_sessionMapPtr)[sessionId]);
}
const std::string &path = req->path();
@ -674,7 +674,7 @@ void HttpAppFrameworkImpl::onAsyncRequest(const HttpRequestImplPtr &req, std::fu
resp->setStatusCode(HttpResponse::k304NotModified);
if (needSetJsessionid)
{
resp->addCookie("JSESSIONID", session_id);
resp->addCookie("JSESSIONID", sessionId);
}
callback(resp);
return;
@ -700,7 +700,7 @@ void HttpAppFrameworkImpl::onAsyncRequest(const HttpRequestImplPtr &req, std::fu
resp->setStatusCode(HttpResponse::k304NotModified);
if (needSetJsessionid)
{
resp->addCookie("JSESSIONID", session_id);
resp->addCookie("JSESSIONID", sessionId);
}
callback(resp);
return;
@ -717,7 +717,7 @@ void HttpAppFrameworkImpl::onAsyncRequest(const HttpRequestImplPtr &req, std::fu
{
//make a copy
auto newCachedResp = std::make_shared<HttpResponseImpl>(*std::dynamic_pointer_cast<HttpResponseImpl>(cachedResp));
newCachedResp->addCookie("JSESSIONID", session_id);
newCachedResp->addCookie("JSESSIONID", sessionId);
newCachedResp->setExpiredTime(-1);
callback(newCachedResp);
return;
@ -779,7 +779,7 @@ void HttpAppFrameworkImpl::onAsyncRequest(const HttpRequestImplPtr &req, std::fu
newCachedResp = std::make_shared<HttpResponseImpl>(*std::dynamic_pointer_cast<HttpResponseImpl>(resp));
newCachedResp->setExpiredTime(-1);
}
newCachedResp->addCookie("JSESSIONID", session_id);
newCachedResp->addCookie("JSESSIONID", sessionId);
callback(newCachedResp);
return;
}
@ -789,7 +789,7 @@ void HttpAppFrameworkImpl::onAsyncRequest(const HttpRequestImplPtr &req, std::fu
}
//Route to controller
_httpSimpleCtrlsRouter.route(req, std::move(callback), needSetJsessionid, std::move(session_id));
_httpSimpleCtrlsRouter.route(req, std::move(callback), needSetJsessionid, std::move(sessionId));
}
void HttpAppFrameworkImpl::readSendFile(const std::string &filePath, const HttpRequestImplPtr &req, const HttpResponsePtr &resp)

View File

@ -14,7 +14,7 @@
#include "HttpClientImpl.h"
#include "HttpRequestImpl.h"
#include "HttpClientParser.h"
#include "HttpResponseParser.h"
#include "HttpAppFrameworkImpl.h"
#include <stdlib.h>
#include <algorithm>
@ -131,7 +131,7 @@ void HttpClientImpl::sendRequestInLoop(const drogon::HttpRequestPtr &req,
_tcpClient->setConnectionCallback([=](const trantor::TcpConnectionPtr &connPtr) {
if (connPtr->connected())
{
connPtr->setContext(HttpClientParser(connPtr));
connPtr->setContext(HttpResponseParser(connPtr));
//send request;
LOG_TRACE << "Connection established!";
auto req = thisPtr->_reqAndCallbacks.front().first;
@ -197,10 +197,10 @@ void HttpClientImpl::sendReq(const trantor::TcpConnectionPtr &connPtr, const Htt
void HttpClientImpl::onRecvMessage(const trantor::TcpConnectionPtr &connPtr, trantor::MsgBuffer *msg)
{
HttpClientParser *context = any_cast<HttpClientParser>(connPtr->getMutableContext());
HttpResponseParser *responseParser = any_cast<HttpResponseParser>(connPtr->getMutableContext());
//LOG_TRACE << "###:" << msg->readableBytes();
if (!context->parseResponse(msg))
if (!responseParser->parseResponse(msg))
{
assert(!_reqAndCallbacks.empty());
auto cb = _reqAndCallbacks.front().second;
@ -211,10 +211,10 @@ void HttpClientImpl::onRecvMessage(const trantor::TcpConnectionPtr &connPtr, tra
return;
}
if (context->gotAll())
if (responseParser->gotAll())
{
auto resp = context->responseImpl();
context->reset();
auto resp = responseParser->responseImpl();
responseParser->reset();
assert(!_reqAndCallbacks.empty());
@ -223,6 +223,11 @@ void HttpClientImpl::onRecvMessage(const trantor::TcpConnectionPtr &connPtr, tra
{
resp->parseJson();
}
if (resp->getHeaderBy("content-encoding")=="gzip")
{
resp->gunzip();
}
auto &cb = _reqAndCallbacks.front().second;
cb(ReqResult::Ok, resp);
_reqAndCallbacks.pop();

View File

@ -140,7 +140,7 @@ void HttpControllersRouter::addHttpPath(const std::string &path,
void HttpControllersRouter::route(const HttpRequestImplPtr &req,
std::function<void(const HttpResponsePtr &)> &&callback,
bool needSetJsessionid,
std::string &&session_id)
std::string &&sessionId)
{
//find http controller
if (_ctrlRegex.mark_count() > 0)
@ -172,7 +172,7 @@ void HttpControllersRouter::route(const HttpRequestImplPtr &req,
auto &filters = binder->filtersName;
if (!filters.empty())
{
auto sessionIdPtr = std::make_shared<std::string>(std::move(session_id));
auto sessionIdPtr = std::make_shared<std::string>(std::move(sessionId));
auto callbackPtr = std::make_shared<std::function<void(const HttpResponsePtr &)>>(std::move(callback));
_appImpl.doFilters(filters, req, callbackPtr, needSetJsessionid, sessionIdPtr, [=]() {
doControllerHandler(binder, routerItem, req, std::move(*callbackPtr), needSetJsessionid, std::move(*sessionIdPtr));
@ -180,7 +180,7 @@ void HttpControllersRouter::route(const HttpRequestImplPtr &req,
}
else
{
doControllerHandler(binder, routerItem, req, std::move(callback), needSetJsessionid, std::move(session_id));
doControllerHandler(binder, routerItem, req, std::move(callback), needSetJsessionid, std::move(sessionId));
}
}
}
@ -190,7 +190,7 @@ void HttpControllersRouter::route(const HttpRequestImplPtr &req,
//No controller found
auto res = drogon::HttpResponse::newNotFoundResponse();
if (needSetJsessionid)
res->addCookie("JSESSIONID", session_id);
res->addCookie("JSESSIONID", sessionId);
callback(res);
}
}
@ -199,7 +199,7 @@ void HttpControllersRouter::route(const HttpRequestImplPtr &req,
//No controller found
auto res = drogon::HttpResponse::newNotFoundResponse();
if (needSetJsessionid)
res->addCookie("JSESSIONID", session_id);
res->addCookie("JSESSIONID", sessionId);
callback(res);
}
}
@ -209,7 +209,7 @@ void HttpControllersRouter::doControllerHandler(const CtrlBinderPtr &ctrlBinderP
const HttpRequestImplPtr &req,
std::function<void(const HttpResponsePtr &)> &&callback,
bool needSetJsessionid,
std::string &&session_id)
std::string &&sessionId)
{
HttpResponsePtr responsePtr;
{
@ -229,7 +229,7 @@ void HttpControllersRouter::doControllerHandler(const CtrlBinderPtr &ctrlBinderP
//make a copy response;
auto newResp = std::make_shared<HttpResponseImpl>(*std::dynamic_pointer_cast<HttpResponseImpl>(responsePtr));
newResp->setExpiredTime(-1); //make it temporary
newResp->addCookie("JSESSIONID", session_id);
newResp->addCookie("JSESSIONID", sessionId);
callback(newResp);
}
return;
@ -270,8 +270,8 @@ void HttpControllersRouter::doControllerHandler(const CtrlBinderPtr &ctrlBinderP
paraList.push_back(std::move(p));
}
ctrlBinderPtr->binderPtr->handleHttpRequest(paraList, req, [=, callback = std::move(callback), session_id = std::move(session_id)](const HttpResponsePtr &resp) {
LOG_TRACE << "http resp:needSetJsessionid=" << needSetJsessionid << ";JSESSIONID=" << session_id;
ctrlBinderPtr->binderPtr->handleHttpRequest(paraList, req, [=, callback = std::move(callback), sessionId = std::move(sessionId)](const HttpResponsePtr &resp) {
LOG_TRACE << "http resp:needSetJsessionid=" << needSetJsessionid << ";JSESSIONID=" << sessionId;
auto newResp = resp;
if (resp->expiredTime() >= 0)
{
@ -290,7 +290,7 @@ void HttpControllersRouter::doControllerHandler(const CtrlBinderPtr &ctrlBinderP
newResp = std::make_shared<HttpResponseImpl>(*std::dynamic_pointer_cast<HttpResponseImpl>(resp));
newResp->setExpiredTime(-1); //make it temporary
}
newResp->addCookie("JSESSIONID", session_id);
newResp->addCookie("JSESSIONID", sessionId);
}
callback(newResp);
});

View File

@ -38,7 +38,7 @@ class HttpControllersRouter : public trantor::NonCopyable
void route(const HttpRequestImplPtr &req,
std::function<void(const HttpResponsePtr &)> &&callback,
bool needSetJsessionid,
std::string &&session_id);
std::string &&sessionId);
private:
struct CtrlBinder
@ -67,6 +67,6 @@ class HttpControllersRouter : public trantor::NonCopyable
const HttpRequestImplPtr &req,
std::function<void(const HttpResponsePtr &)> &&callback,
bool needSetJsessionid,
std::string &&session_id);
std::string &&sessionId);
};
} // namespace drogon

View File

@ -33,7 +33,7 @@ namespace drogon
class HttpRequestImpl : public HttpRequest
{
public:
friend class HttpServerParser;
friend class HttpRequestParser;
HttpRequestImpl()
: _method(Invalid),
_version(kUnknown),

View File

@ -1,6 +1,6 @@
/**
*
* HttpServerParser.cc
* HttpRequestParser.cc
* An Tao
*
* Copyright 2018, An Tao. All rights reserved.
@ -14,18 +14,18 @@
#include <trantor/utils/MsgBuffer.h>
#include <trantor/utils/Logger.h>
#include "HttpServerParser.h"
#include "HttpRequestParser.h"
#include "HttpResponseImpl.h"
#include <iostream>
using namespace trantor;
using namespace drogon;
HttpServerParser::HttpServerParser(const trantor::TcpConnectionPtr &connPtr)
HttpRequestParser::HttpRequestParser(const trantor::TcpConnectionPtr &connPtr)
: _state(kExpectRequestLine),
_request(new HttpRequestImpl),
_conn(connPtr)
{
}
bool HttpServerParser::processRequestLine(const char *begin, const char *end)
bool HttpRequestParser::processRequestLine(const char *begin, const char *end)
{
bool succeed = false;
const char *start = begin;
@ -69,7 +69,7 @@ bool HttpServerParser::processRequestLine(const char *begin, const char *end)
}
// return false if any error
bool HttpServerParser::parseRequest(MsgBuffer *buf)
bool HttpRequestParser::parseRequest(MsgBuffer *buf)
{
bool ok = true;
bool hasMore = true;
@ -196,7 +196,7 @@ bool HttpServerParser::parseRequest(MsgBuffer *buf)
return ok;
}
void HttpServerParser::pushRquestToPipeLine(const HttpRequestPtr &req)
void HttpRequestParser::pushRquestToPipeLine(const HttpRequestPtr &req)
{
#ifndef NDEBUG
auto conn = _conn.lock();
@ -209,7 +209,7 @@ void HttpServerParser::pushRquestToPipeLine(const HttpRequestPtr &req)
_requestPipeLine.push_back(std::move(reqPair));
}
HttpRequestPtr HttpServerParser::getFirstRequest() const
HttpRequestPtr HttpRequestParser::getFirstRequest() const
{
#ifndef NDEBUG
auto conn = _conn.lock();
@ -224,7 +224,7 @@ HttpRequestPtr HttpServerParser::getFirstRequest() const
}
return HttpRequestImplPtr();
}
HttpResponsePtr HttpServerParser::getFirstResponse() const
HttpResponsePtr HttpRequestParser::getFirstResponse() const
{
#ifndef NDEBUG
auto conn = _conn.lock();
@ -239,7 +239,7 @@ HttpResponsePtr HttpServerParser::getFirstResponse() const
}
return HttpResponseImplPtr();
}
void HttpServerParser::popFirstRequest()
void HttpRequestParser::popFirstRequest()
{
#ifndef NDEBUG
auto conn = _conn.lock();
@ -250,7 +250,7 @@ void HttpServerParser::popFirstRequest()
#endif
_requestPipeLine.pop_front();
}
void HttpServerParser::pushResponseToPipeLine(const HttpRequestPtr &req,
void HttpRequestParser::pushResponseToPipeLine(const HttpRequestPtr &req,
const HttpResponsePtr &resp)
{
#ifndef NDEBUG
@ -270,7 +270,7 @@ void HttpServerParser::pushResponseToPipeLine(const HttpRequestPtr &req,
}
}
// std::mutex &HttpServerParser::getPipeLineMutex()
// std::mutex &HttpRequestParser::getPipeLineMutex()
// {
// return *_pipeLineMutex;
// }

View File

@ -1,6 +1,6 @@
/**
*
* HttpServerParser.h
* HttpRequestParser.h
* An Tao
*
* Copyright 2018, An Tao. All rights reserved.
@ -25,7 +25,7 @@
using namespace trantor;
namespace drogon
{
class HttpServerParser
class HttpRequestParser
{
public:
enum HttpRequestParseState
@ -36,7 +36,7 @@ class HttpServerParser
kGotAll,
};
HttpServerParser(const trantor::TcpConnectionPtr &connPtr);
HttpRequestParser(const trantor::TcpConnectionPtr &connPtr);
// return false if any error
bool parseRequest(MsgBuffer *buf);

View File

@ -29,7 +29,7 @@ namespace drogon
{
class HttpResponseImpl : public HttpResponse
{
friend class HttpClientParser;
friend class HttpResponseParser;
public:
explicit HttpResponseImpl()
@ -352,6 +352,13 @@ class HttpResponseImpl : public HttpResponse
makeHeaderString(_fullHeaderString);
}
void gunzip()
{
auto gunzipBody = gzipDecompress(_bodyPtr);
if(gunzipBody)
_bodyPtr = gunzipBody;
}
protected:
static std::string web_content_type_to_string(uint8_t contenttype);
static const std::string web_content_type_and_charset_to_string(uint8_t contenttype,

View File

@ -1,6 +1,6 @@
/**
*
* HttpClientParser.cc
* HttpResponseParser.cc
* An Tao
*
* Copyright 2018, An Tao. All rights reserved.
@ -14,17 +14,17 @@
#include <trantor/utils/MsgBuffer.h>
#include <trantor/utils/Logger.h>
#include "HttpClientParser.h"
#include "HttpResponseParser.h"
#include <iostream>
using namespace trantor;
using namespace drogon;
HttpClientParser::HttpClientParser(const trantor::TcpConnectionPtr &connPtr)
HttpResponseParser::HttpResponseParser(const trantor::TcpConnectionPtr &connPtr)
: _state(HttpResponseParseState::kExpectResponseLine),
_response(new HttpResponseImpl)
{
}
bool HttpClientParser::processResponseLine(const char *begin, const char *end)
bool HttpResponseParser::processResponseLine(const char *begin, const char *end)
{
const char *start = begin;
const char *space = std::find(start, end, ' ');
@ -61,7 +61,7 @@ bool HttpClientParser::processResponseLine(const char *begin, const char *end)
}
// return false if any error
bool HttpClientParser::parseResponse(MsgBuffer *buf)
bool HttpResponseParser::parseResponse(MsgBuffer *buf)
{
bool ok = true;
bool hasMore = true;

View File

@ -1,6 +1,6 @@
/**
*
* HttpClientParser.h
* HttpResponseParser.h
* An Tao
*
* Copyright 2018, An Tao. All rights reserved.
@ -24,7 +24,7 @@
using namespace trantor;
namespace drogon
{
class HttpClientParser
class HttpResponseParser
{
public:
enum class HttpResponseParseState
@ -39,7 +39,7 @@ class HttpClientParser
kGotAll,
};
explicit HttpClientParser(const trantor::TcpConnectionPtr &connPtr);
explicit HttpResponseParser(const trantor::TcpConnectionPtr &connPtr);
// default copy-ctor, dtor and assignment are fine

View File

@ -15,7 +15,7 @@
#include "HttpServer.h"
#include <trantor/utils/Logger.h>
#include "HttpServerParser.h"
#include "HttpRequestParser.h"
#include "HttpResponseImpl.h"
#include <drogon/HttpRequest.h>
#include <drogon/HttpResponse.h>
@ -76,17 +76,17 @@ void HttpServer::onConnection(const TcpConnectionPtr &conn)
{
if (conn->connected())
{
conn->setContext(HttpServerParser(conn));
conn->setContext(HttpRequestParser(conn));
}
else if (conn->disconnected())
{
LOG_TRACE << "conn disconnected!";
HttpServerParser *context = any_cast<HttpServerParser>(conn->getMutableContext());
HttpRequestParser *requestParser = any_cast<HttpRequestParser>(conn->getMutableContext());
// LOG_INFO << "###:" << string(buf->peek(), buf->readableBytes());
if (context->webSocketConn())
if (requestParser->webSocketConn())
{
_disconnectWebsocketCallback(context->webSocketConn());
_disconnectWebsocketCallback(requestParser->webSocketConn());
}
conn->getMutableContext()->reset();
}
@ -96,35 +96,35 @@ void HttpServer::onConnection(const TcpConnectionPtr &conn)
void HttpServer::onMessage(const TcpConnectionPtr &conn,
MsgBuffer *buf)
{
HttpServerParser *context = any_cast<HttpServerParser>(conn->getMutableContext());
HttpRequestParser *requestParser = any_cast<HttpRequestParser>(conn->getMutableContext());
// LOG_INFO << "###:" << string(buf->peek(), buf->readableBytes());
if (context->webSocketConn())
if (requestParser->webSocketConn())
{
//websocket payload,we shouldn't parse it
_webSocketMessageCallback(context->webSocketConn(), buf);
_webSocketMessageCallback(requestParser->webSocketConn(), buf);
return;
}
if (!context->parseRequest(buf))
if (!requestParser->parseRequest(buf))
{
conn->send("HTTP/1.1 400 Bad Request\r\n\r\n");
//conn->shutdown();
}
if (context->gotAll())
if (requestParser->gotAll())
{
context->requestImpl()->parseParameter();
context->requestImpl()->setPeerAddr(conn->peerAddr());
context->requestImpl()->setLocalAddr(conn->localAddr());
context->requestImpl()->setReceiveDate(trantor::Date::date());
if (context->firstReq() && isWebSocket(conn, context->request()))
requestParser->requestImpl()->parseParameter();
requestParser->requestImpl()->setPeerAddr(conn->peerAddr());
requestParser->requestImpl()->setLocalAddr(conn->localAddr());
requestParser->requestImpl()->setReceiveDate(trantor::Date::date());
if (requestParser->firstReq() && isWebSocket(conn, requestParser->request()))
{
auto wsConn = std::make_shared<WebSocketConnectionImpl>(conn);
_newWebsocketCallback(context->request(),
_newWebsocketCallback(requestParser->request(),
[=](const HttpResponsePtr &resp) mutable {
if (resp->statusCode() == HttpResponse::k101SwitchingProtocols)
{
context->setWebsockConnection(wsConn);
requestParser->setWebsockConnection(wsConn);
}
auto httpString = std::dynamic_pointer_cast<HttpResponseImpl>(resp)->renderToString();
conn->send(httpString);
@ -132,8 +132,8 @@ void HttpServer::onMessage(const TcpConnectionPtr &conn,
wsConn);
}
else
onRequest(conn, context->request());
context->reset();
onRequest(conn, requestParser->request());
requestParser->reset();
}
}
bool HttpServer::isWebSocket(const TcpConnectionPtr &conn, const HttpRequestImplPtr &req)
@ -158,10 +158,10 @@ void HttpServer::onRequest(const TcpConnectionPtr &conn, const HttpRequestImplPt
{
req->setMethod(Get);
}
HttpServerParser *context = any_cast<HttpServerParser>(conn->getMutableContext());
HttpRequestParser *requestParser = any_cast<HttpRequestParser>(conn->getMutableContext());
{
//std::lock_guard<std::mutex> guard(context->getPipeLineMutex());
context->pushRquestToPipeLine(req);
//std::lock_guard<std::mutex> guard(requestParser->getPipeLineMutex());
requestParser->pushRquestToPipeLine(req);
}
_httpAsyncCallback(req, [=](const HttpResponsePtr &response) {
if (!response)
@ -224,17 +224,17 @@ void HttpServer::onRequest(const TcpConnectionPtr &conn, const HttpRequestImplPt
* requests in the same order that the requests were received.
* rfc2616-8.1.1.2
*/
//std::lock_guard<std::mutex> guard(context->getPipeLineMutex());
if (context->getFirstRequest() == req)
//std::lock_guard<std::mutex> guard(requestParser->getPipeLineMutex());
if (requestParser->getFirstRequest() == req)
{
context->popFirstRequest();
requestParser->popFirstRequest();
sendResponse(conn, newResp);
while (1)
{
auto resp = context->getFirstResponse();
auto resp = requestParser->getFirstResponse();
if (resp)
{
context->popFirstRequest();
requestParser->popFirstRequest();
sendResponse(conn, resp);
}
else
@ -244,25 +244,25 @@ void HttpServer::onRequest(const TcpConnectionPtr &conn, const HttpRequestImplPt
else
{
//some earlier requests are waiting for responses;
context->pushResponseToPipeLine(req, newResp);
requestParser->pushResponseToPipeLine(req, newResp);
}
}
else
{
conn->getLoop()->queueInLoop([conn, req, newResp, this]() {
HttpServerParser *context = any_cast<HttpServerParser>(conn->getMutableContext());
if (context)
HttpRequestParser *requestParser = any_cast<HttpRequestParser>(conn->getMutableContext());
if (requestParser)
{
if (context->getFirstRequest() == req)
if (requestParser->getFirstRequest() == req)
{
context->popFirstRequest();
requestParser->popFirstRequest();
sendResponse(conn, newResp);
while (1)
{
auto resp = context->getFirstResponse();
auto resp = requestParser->getFirstResponse();
if (resp)
{
context->popFirstRequest();
requestParser->popFirstRequest();
sendResponse(conn, resp);
}
else
@ -272,7 +272,7 @@ void HttpServer::onRequest(const TcpConnectionPtr &conn, const HttpRequestImplPt
else
{
//some earlier requests are waiting for responses;
context->pushResponseToPipeLine(req, newResp);
requestParser->pushResponseToPipeLine(req, newResp);
}
}
});

View File

@ -67,7 +67,7 @@ void HttpSimpleControllersRouter::registerHttpSimpleController(const std::string
void HttpSimpleControllersRouter::route(const HttpRequestImplPtr &req,
std::function<void(const HttpResponsePtr &)> &&callback,
bool needSetJsessionid,
std::string &&session_id)
std::string &&sessionId)
{
std::string pathLower(req->path().length(), 0);
std::transform(req->path().begin(), req->path().end(), pathLower.begin(), tolower);
@ -90,7 +90,7 @@ void HttpSimpleControllersRouter::route(const HttpRequestImplPtr &req,
auto &filters = ctrlInfo.filtersName;
if (!filters.empty())
{
auto sessionIdPtr = std::make_shared<std::string>(std::move(session_id));
auto sessionIdPtr = std::make_shared<std::string>(std::move(sessionId));
auto callbackPtr = std::make_shared<std::function<void(const HttpResponsePtr &)>>(std::move(callback));
_appImpl.doFilters(filters, req, callbackPtr, needSetJsessionid, sessionIdPtr, [=, pathLower = std::move(pathLower)]() mutable {
doControllerHandler(std::move(pathLower), req, std::move(*callbackPtr), needSetJsessionid, std::move(*sessionIdPtr));
@ -98,18 +98,18 @@ void HttpSimpleControllersRouter::route(const HttpRequestImplPtr &req,
}
else
{
doControllerHandler(std::move(pathLower), req, std::move(callback), needSetJsessionid, std::move(session_id));
doControllerHandler(std::move(pathLower), req, std::move(callback), needSetJsessionid, std::move(sessionId));
}
return;
}
_httpCtrlsRouter.route(req, std::move(callback), needSetJsessionid, std::move(session_id));
_httpCtrlsRouter.route(req, std::move(callback), needSetJsessionid, std::move(sessionId));
}
void HttpSimpleControllersRouter::doControllerHandler(std::string &&pathLower,
const HttpRequestImplPtr &req,
std::function<void(const HttpResponsePtr &)> &&callback,
bool needSetJsessionid,
std::string &&session_id)
std::string &&sessionId)
{
auto &ctrlItem = _simpCtrlMap[pathLower];
const std::string &ctrlName = ctrlItem.controllerName;
@ -141,14 +141,14 @@ void HttpSimpleControllersRouter::doControllerHandler(std::string &&pathLower,
//make a copy response;
auto newResp = std::make_shared<HttpResponseImpl>(*std::dynamic_pointer_cast<HttpResponseImpl>(responsePtr));
newResp->setExpiredTime(-1); //make it temporary
newResp->addCookie("JSESSIONID", session_id);
newResp->addCookie("JSESSIONID", sessionId);
callback(newResp);
}
return;
}
else
{
controller->asyncHandleHttpRequest(req, [=, callback = std::move(callback), pathLower = std::move(pathLower), session_id = std::move(session_id)](const HttpResponsePtr &resp) {
controller->asyncHandleHttpRequest(req, [=, callback = std::move(callback), pathLower = std::move(pathLower), sessionId = std::move(sessionId)](const HttpResponsePtr &resp) {
auto newResp = resp;
if (resp->expiredTime() >= 0)
{
@ -168,7 +168,7 @@ void HttpSimpleControllersRouter::doControllerHandler(std::string &&pathLower,
newResp = std::make_shared<HttpResponseImpl>(*std::dynamic_pointer_cast<HttpResponseImpl>(resp));
newResp->setExpiredTime(-1); //make it temporary
}
newResp->addCookie("JSESSIONID", session_id);
newResp->addCookie("JSESSIONID", sessionId);
}
callback(newResp);
});
@ -181,7 +181,7 @@ void HttpSimpleControllersRouter::doControllerHandler(std::string &&pathLower,
LOG_ERROR << "can't find controller " << ctrlName;
auto res = drogon::HttpResponse::newNotFoundResponse();
if (needSetJsessionid)
res->addCookie("JSESSIONID", session_id);
res->addCookie("JSESSIONID", sessionId);
callback(res);
}

View File

@ -40,7 +40,7 @@ class HttpSimpleControllersRouter : public trantor::NonCopyable
void route(const HttpRequestImplPtr &req,
std::function<void(const HttpResponsePtr &)> &&callback,
bool needSetJsessionid,
std::string &&session_id);
std::string &&sessionId);
private:
HttpAppFrameworkImpl &_appImpl;
@ -61,6 +61,6 @@ class HttpSimpleControllersRouter : public trantor::NonCopyable
const HttpRequestImplPtr &req,
std::function<void(const HttpResponsePtr &)> &&callback,
bool needSetJsessionid,
std::string &&session_id);
std::string &&sessionId);
};
} // namespace drogon

View File

@ -442,6 +442,61 @@ int gzipDecompress(const char *zdata, const size_t nzdata,
*ndata = d_stream.total_out;
return 0;
}
std::shared_ptr<std::string> gzipDecompress(const std::shared_ptr<std::string> &compressedData)
{
if (compressedData->length() == 0)
return compressedData;
auto full_length = compressedData->length();
auto decompressed = std::make_shared<std::string>(full_length * 2, 0);
bool done = false;
int status;
z_stream strm = {0};
strm.next_in = (Bytef *)compressedData->data();
strm.avail_in = compressedData->length();
strm.total_out = 0;
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
if (inflateInit2(&strm, (15 + 32)) != Z_OK)
return nullptr;
while (!done)
{
// Make sure we have enough room and reset the lengths.
if (strm.total_out >= decompressed->length())
{
decompressed->resize(decompressed->length() * 2);
}
// chadeltu 加了(Bytef *)
strm.next_out = (Bytef *)decompressed->data() + strm.total_out;
strm.avail_out = decompressed->length() - strm.total_out;
// Inflate another chunk.
status = inflate(&strm, Z_SYNC_FLUSH);
if (status == Z_STREAM_END)
{
done = true;
}
else if (status != Z_OK)
{
break;
}
}
if (inflateEnd(&strm) != Z_OK)
return nullptr;
// Set real length.
if (done)
{
decompressed->resize(strm.total_out);
return decompressed;
}
else
{
return nullptr;
}
}
char *getHttpFullDate(const trantor::Date &date)
{
static __thread int64_t lastSecond = 0;

View File

@ -7,4 +7,5 @@ add_executable(class_name_test ClassNameTest.cc)
add_executable(sha1_test Sha1Test.cc)
add_executable(view_data_test HttpViewDataTest.cc)
add_executable(md5_test Md5Test.cc ../src/ssl_funcs/Md5.cc)
add_executable(http_full_date_test HttpFullDateTest.cc)
add_executable(http_full_date_test HttpFullDateTest.cc)
add_executable(gzip_test GzipTest.cc)

325
lib/tests/GzipTest.cc Normal file
View File

@ -0,0 +1,325 @@
#include <drogon/utils/Utilities.h>
#include <iostream>
using namespace drogon;
int main()
{
const std::string inStr = "Applications\n"
"Developer\n"
"Library\n"
"Network\n"
"System\n"
"Users\n"
"Volumes\n"
"bin\n"
"cores\n"
"dev\n"
"etc\n"
"home\n"
"installer.failurerequests\n"
"net\n"
"opt\n"
"private\n"
"sbin\n"
"tmp\n"
"usb\n"
"usr\n"
"var\n"
"vm\n"
"用户信息\n"
"\n"
"/Applications:\n"
"Adobe\n"
"Adobe Creative Cloud\n"
"Adobe Photoshop CC\n"
"AirPlayer Pro.app\n"
"Android Studio.app\n"
"App Store.app\n"
"Autodesk\n"
"Automator.app\n"
"Axure RP Pro 7.0.app\n"
"BaiduNetdisk_mac.app\n"
"CLion.app\n"
"Calculator.app\n"
"Calendar.app\n"
"Chess.app\n"
"CleanApp.app\n"
"Contacts.app\n"
"DVD Player.app\n"
"Dashboard.app\n"
"Dictionary.app\n"
"Docs for Xcode.app\n"
"FaceTime.app\n"
"FinalShell\n"
"Firefox.app\n"
"Folx.app\n"
"Font Book.app\n"
"GitHub.app\n"
"Google Chrome.app\n"
"Grammarly.app\n"
"Image Capture.app\n"
"Lantern.app\n"
"Launchpad.app\n"
"License.rtf\n"
"MacPorts\n"
"Mail.app\n"
"Maps.app\n"
"Messages.app\n"
"Microsoft Excel.app\n"
"Microsoft Office 2011\n"
"Microsoft OneNote.app\n"
"Microsoft Outlook.app\n"
"Microsoft PowerPoint.app\n"
"Microsoft Word.app\n"
"Mindjet MindManager.app\n"
"Mission Control.app\n"
"Mockplus.app\n"
"MyEclipse 2015\n"
"Notes.app\n"
"OmniGraffle.app\n"
"PP助手.app\n"
"Pages.app\n"
"Photo Booth.app\n"
"Photos.app\n"
"Preview.app\n"
"QJVPN.app\n"
"QQ.app\n"
"QuickTime Player.app\n"
"RAR Extractor Lite.app\n"
"Reminders.app\n"
"Remote Desktop Connection.app\n"
"Renee Undeleter.app\n"
"Sabaki.app\n"
"Safari.app\n"
"ShadowsocksX.app\n"
"Siri.app\n"
"SogouInputPad.app\n"
"Stickies.app\n"
"System Preferences.app\n"
"TeX\n"
"Telegram.app\n"
"Termius.app\n"
"Tesumego - How to Make a Professional Go Player.app\n"
"TextEdit.app\n"
"Thunder.app\n"
"Time Machine.app\n"
"Tunnelblick.app\n"
"Utilities\n"
"VPN Shield.appdownload\n"
"VirtualBox.app\n"
"WeChat.app\n"
"WinOnX2.app\n"
"Wireshark.app\n"
"Xcode.app\n"
"Yose.app\n"
"YoudaoNote.localized\n"
"finalshelldata\n"
"iBooks.app\n"
"iPhoto.app\n"
"iTools.app\n"
"iTunes.app\n"
"pgAdmin 4.app\n"
"wechatwebdevtools.app\n"
"搜狐影音.appdownload\n"
"网易有道词典.app\n"
"万能数据恢复大师.app\n"
"\n"
"/Applications/Adobe:\n"
"Flash Player\n"
"\n"
"/Applications/Adobe/Flash Player:\n"
"AddIns\n"
"\n"
"/Applications/Adobe/Flash Player/AddIns:\n"
"airappinstaller\n"
"\n"
"/Applications/Adobe/Flash Player/AddIns/airappinstaller:\n"
"airappinstaller\n"
"digest.s\n"
"\n"
"/Applications/Adobe Creative Cloud:\n"
"Adobe Creative Cloud\n"
"Icon\n"
"Uninstall Adobe Creative Cloud\n"
"\n"
"/Applications/Adobe Photoshop CC:\n"
"Adobe Photoshop CC.app\n"
"Configuration\n"
"Icon\n"
"Legal\n"
"LegalNotices.pdf\n"
"Locales\n"
"Plug-ins\n"
"Presets\n"
"卸载 Adobe Photoshop CC\n"
"\n"
"/Applications/Adobe Photoshop CC/Adobe Photoshop CC.app:\n"
"Contents\n"
"Linguistics\n"
"\n"
"/Applications/Adobe Photoshop CC/Adobe Photoshop CC.app/Contents:\n"
"Application Data\n"
"Frameworks\n"
"Info.plist\n"
"MacOS\n"
"PkgInfo\n"
"Required\n"
"Resources\n"
"_CodeSignature\n"
"\n"
"/Applications/Adobe Photoshop CC/Adobe Photoshop CC.app/Contents/Application Data:\n"
"Custom File Info Panels\n"
"\n"
"/Applications/Adobe Photoshop CC/Adobe Photoshop CC.app/Contents/Application Data/Custom File Info Panels:\n"
"4.0\n"
"\n"
"/Applications/Adobe Photoshop CC/Adobe Photoshop CC.app/Contents/Application Data/Custom File Info Panels/4.0:\n"
"bin\n"
"custom\n"
"panels\n"
"\n"
"/Applications/Adobe Photoshop CC/Adobe Photoshop CC.app/Contents/Application Data/Custom File Info Panels/4.0/bin:\n"
"FileInfoFoundation.swf\n"
"FileInfoUI.swf\n"
"framework.swf\n"
"loc\n"
"\n"
"/Applications/Adobe Photoshop CC/Adobe Photoshop CC.app/Contents/Application Data/Custom File Info Panels/4.0/bin/loc:\n"
"FileInfo_ar_AE.dat\n"
"FileInfo_bg_BG.dat\n"
"FileInfo_cs_CZ.dat\n"
"FileInfo_da_DK.dat\n"
"FileInfo_de_DE.dat\n"
"FileInfo_el_GR.dat\n"
"FileInfo_en_US.dat\n"
"FileInfo_es_ES.dat\n"
"FileInfo_et_EE.dat\n"
"FileInfo_fi_FI.dat\n"
"FileInfo_fr_FR.dat\n"
"FileInfo_he_IL.dat\n"
"FileInfo_hr_HR.dat\n"
"FileInfo_hu_HU.dat\n"
"FileInfo_it_IT.dat\n"
"FileInfo_ja_JP.dat\n"
"FileInfo_ko_KR.dat\n"
"FileInfo_lt_LT.dat\n"
"FileInfo_lv_LV.dat\n"
"FileInfo_nb_NO.dat\n"
"FileInfo_nl_NL.dat\n"
"FileInfo_pl_PL.dat\n"
"FileInfo_pt_BR.dat\n"
"FileInfo_ro_RO.dat\n"
"FileInfo_ru_RU.dat\n"
"FileInfo_sk_SK.dat\n"
"FileInfo_sl_SI.dat\n"
"FileInfo_sv_SE.dat\n"
"FileInfo_tr_TR.dat\n"
"FileInfo_uk_UA.dat\n"
"FileInfo_zh_CN.dat\n"
"FileInfo_zh_TW.dat\n"
"\n"
"/Applications/Adobe Photoshop CC/Adobe Photoshop CC.app/Contents/Application Data/Custom File Info Panels/4.0/custom:\n"
"DICOM.xml\n"
"Mobile.xml\n"
"loc\n"
"\n"
"/Applications/Adobe Photoshop CC/Adobe Photoshop CC.app/Contents/Application Data/Custom File Info Panels/4.0/custom/loc:\n"
"DICOM_ar_AE.dat\n"
"DICOM_bg_BG.dat\n"
"DICOM_cs_CZ.dat\n"
"DICOM_da_DK.dat\n"
"DICOM_de_DE.dat\n"
"DICOM_el_GR.dat\n"
"DICOM_en_US.dat\n"
"DICOM_es_ES.dat\n"
"DICOM_et_EE.dat\n"
"DICOM_fi_FI.dat\n"
"DICOM_fr_FR.dat\n"
"DICOM_he_IL.dat\n"
"DICOM_hr_HR.dat\n"
"DICOM_hu_HU.dat\n"
"DICOM_it_IT.dat\n"
"DICOM_ja_JP.dat\n"
"DICOM_ko_KR.dat\n"
"DICOM_lt_LT.dat\n"
"DICOM_lv_LV.dat\n"
"DICOM_nb_NO.dat\n"
"DICOM_nl_NL.dat\n"
"DICOM_pl_PL.dat\n"
"DICOM_pt_BR.dat\n"
"DICOM_ro_RO.dat\n"
"DICOM_ru_RU.dat\n"
"DICOM_sk_SK.dat\n"
"DICOM_sl_SI.dat\n"
"DICOM_sv_SE.dat\n"
"DICOM_tr_TR.dat\n"
"DICOM_uk_UA.dat\n"
"DICOM_zh_CN.dat\n"
"DICOM_zh_TW.dat\n"
"Mobile_ar_AE.dat\n"
"Mobile_bg_BG.dat\n"
"Mobile_cs_CZ.dat\n"
"Mobile_da_DK.dat\n"
"Mobile_de_DE.dat\n"
"Mobile_el_GR.dat\n"
"Mobile_en_US.dat\n"
"Mobile_es_ES.dat\n"
"Mobile_et_EE.dat\n"
"Mobile_fi_FI.dat\n"
"Mobile_fr_FR.dat\n"
"Mobile_he_IL.dat\n"
"Mobile_hr_HR.dat\n"
"Mobile_hu_HU.dat\n"
"Mobile_it_IT.dat\n"
"Mobile_ja_JP.dat\n"
"Mobile_ko_KR.dat\n"
"Mobile_lt_LT.dat\n"
"Mobile_lv_LV.dat\n"
"Mobile_nb_NO.dat\n"
"Mobile_nl_NL.dat\n"
"Mobile_pl_PL.dat\n"
"Mobile_pt_BR.dat\n"
"Mobile_ro_RO.dat\n"
"Mobile_ru_RU.dat\n"
"Mobile_sk_SK.dat\n"
"Mobile_sl_SI.dat\n"
"Mobile_sv_SE.dat\n"
"Mobile_tr_TR.dat\n"
"Mobile_uk_UA.dat\n"
"Mobile_zh_CN.dat\n"
"Mobile_zh_TW.dat\n"
"\n"
"/Applications/Adobe Photoshop CC/Adobe Photoshop CC.app/Contents/Application Data/Custom File Info Panels/4.0/panels:\n"
"IPTC\n"
"IPTCExt\n"
"advanced\n"
"audioData\n"
"camera\n"
"categories\n"
"description\n"
"dicom\n"
"gpsData\n"
"history\n"
"mobile\n"
"origin\n"
"rawpacket";
std::string out;
out.resize(inStr.length());
size_t len = out.length();
auto ret=gzipCompress(inStr.c_str(), inStr.length(), out.data(), &len);
if(ret==0)
{
out.resize(len);
std::cout << "origin length=" << inStr.length() << " compressing length=" << out.length() << std::endl;
auto decompressStr = gzipDecompress(std::make_shared<std::string>(out));
if (decompressStr)
{
std::cout << "decompressing length=" << decompressStr->length() << std::endl;
std::cout << *decompressStr;
}
}
return 0;
}