rcpp_framework/core/http_request_parser.h

157 lines
4.0 KiB
C++

/**
*
* HttpRequestParser.h
* An Tao
*
* Copyright 2018, An Tao. All rights reserved.
* https://github.com/an-tao/drogon
* Use of this source code is governed by a MIT license
* that can be found in the License file.
*
* Drogon
*
*/
#pragma once
#include "core/http_server_callbacks.h"
#include <core/http_types.h>
#include <trantor/utils/NonCopyable.h>
#include <trantor/net/TcpConnection.h>
#include <trantor/utils/MsgBuffer.h>
#include <mutex>
#include <deque>
namespace drogon
{
class HttpRequestParser : public trantor::NonCopyable,
public std::enable_shared_from_this<HttpRequestParser>
{
public:
enum class HttpRequestParseStatus
{
kExpectMethod,
kExpectRequestLine,
kExpectHeaders,
kExpectBody,
kExpectChunkLen,
kExpectChunkBody,
kExpectLastEmptyChunk,
kGotAll,
};
explicit HttpRequestParser(const trantor::TcpConnectionPtr &connPtr);
// return false if any error
bool parseRequest(trantor::MsgBuffer *buf);
bool gotAll() const
{
return status_ == HttpRequestParseStatus::kGotAll;
}
void reset();
const HttpRequestPtr &requestImpl() const
{
return request_;
}
bool firstReq()
{
if (firstRequest_)
{
firstRequest_ = false;
return true;
}
return false;
}
const WebSocketConnectionPtr &webSocketConn() const
{
return websockConnPtr_;
}
void setWebsockConnection(const WebSocketConnectionPtr &conn)
{
websockConnPtr_ = conn;
}
// to support request pipelining(rfc2616-8.1.2.2)
void pushRequestToPipelining(const HttpRequestPtr &req);
HttpRequestPtr getFirstRequest() const;
std::pair<HttpResponsePtr, bool> getFirstResponse() const;
void popFirstRequest();
void pushResponseToPipelining(const HttpRequestPtr &req,
const HttpResponsePtr &resp,
bool isHeadMethod);
size_t numberOfRequestsInPipelining() const
{
return requestPipelining_.size();
}
bool emptyPipelining()
{
return requestPipelining_.empty();
}
bool isStop() const
{
return stopWorking_;
}
void stop()
{
stopWorking_ = true;
}
size_t numberOfRequestsParsed() const
{
return requestsCounter_;
}
trantor::MsgBuffer &getBuffer()
{
return sendBuffer_;
}
std::vector<std::pair<HttpResponsePtr, bool>> &getResponseBuffer()
{
assert(loop_->isInLoopThread());
if (!responseBuffer_)
{
responseBuffer_ =
std::unique_ptr<std::vector<std::pair<HttpResponsePtr, bool>>>(
new std::vector<std::pair<HttpResponsePtr, bool>>);
}
return *responseBuffer_;
}
std::vector<HttpRequestPtr> &getRequestBuffer()
{
assert(loop_->isInLoopThread());
if (!requestBuffer_)
{
requestBuffer_ = std::unique_ptr<std::vector<HttpRequestPtr>>(
new std::vector<HttpRequestPtr>);
}
return *requestBuffer_;
}
private:
HttpRequestPtr makeRequestForPool(HttpRequest *p);
void shutdownConnection(HttpStatusCode code);
bool processRequestLine(const char *begin, const char *end);
HttpRequestParseStatus status_;
trantor::EventLoop *loop_;
HttpRequestPtr request_;
bool firstRequest_{true};
WebSocketConnectionPtr websockConnPtr_;
std::deque<std::pair<HttpRequestPtr, std::pair<HttpResponsePtr, bool>>>
requestPipelining_;
size_t requestsCounter_{0};
std::weak_ptr<trantor::TcpConnection> conn_;
bool stopWorking_{false};
trantor::MsgBuffer sendBuffer_;
std::unique_ptr<std::vector<std::pair<HttpResponsePtr, bool>>>
responseBuffer_;
std::unique_ptr<std::vector<HttpRequestPtr>> requestBuffer_;
std::vector<HttpRequestPtr> requestsPool_;
size_t currentChunkLength_;
size_t currentContentLength_{0};
};
} // namespace drogon