rcpp_framework/libs/brynet/net/http/HttpParser.hpp

328 lines
7.6 KiB
C++
Raw Normal View History

2020-11-24 15:41:18 +01:00
#pragma once
2021-04-30 16:10:14 +02:00
#include <brynet/net/http/WebSocketFormat.hpp>
#include <cassert>
2020-11-24 15:41:18 +01:00
#include <map>
#include <memory>
2021-04-30 16:10:14 +02:00
#include <string>
2020-11-24 15:41:18 +01:00
#include "http_parser.h"
namespace brynet { namespace net { namespace http {
2021-04-30 16:10:14 +02:00
class HttpService;
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
class HTTPParser
{
public:
using Ptr = std::shared_ptr<HTTPParser>;
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
explicit HTTPParser(http_parser_type parserType)
: mParserType(parserType)
{
mLastWasValue = true;
mIsUpgrade = false;
mIsWebSocket = false;
mIsKeepAlive = false;
mISCompleted = false;
mStatusCode = 0;
mWSFrameType = WebSocketFormat::WebSocketFrameType::ERROR_FRAME;
mSettings.on_status = sStatusHandle;
mSettings.on_body = sBodyHandle;
mSettings.on_url = sUrlHandle;
mSettings.on_header_field = sHeadField;
mSettings.on_header_value = sHeadValue;
mSettings.on_headers_complete = sHeadComplete;
mSettings.on_message_begin = sMessageBegin;
mSettings.on_message_complete = sMessageEnd;
mSettings.on_chunk_header = sChunkHeader;
mSettings.on_chunk_complete = sChunkComplete;
mParser.data = this;
http_parser_init(&mParser, mParserType);
}
virtual ~HTTPParser() = default;
bool isUpgrade() const
{
return mIsUpgrade;
}
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
bool isWebSocket() const
{
return mIsWebSocket;
}
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
bool isKeepAlive() const
{
return mIsKeepAlive;
}
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
bool isCompleted() const
{
return mISCompleted;
}
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
int method() const
{
// mMethod's value defined in http_method, such as HTTP_GET、HTTP_POST.
// if mMethod is -1, it's invalid.
return mMethod;
}
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
const std::string& getPath() const
{
return mPath;
}
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
const std::string& getQuery() const
{
return mQuery;
}
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
const std::string& getStatus() const
{
return mStatus;
}
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
int getStatusCode() const
{
return mStatusCode;
}
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
bool hasEntry(const std::string& key,
const std::string& value) const
{
const auto it = mHeadValues.find(key);
return it != mHeadValues.end() && value == it->second;
}
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
bool hasKey(const std::string& key) const
{
return mHeadValues.find(key) != mHeadValues.end();
}
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
const std::string& getValue(const std::string& key) const
{
const static std::string emptystr("");
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
auto it = mHeadValues.find(key);
if (it != mHeadValues.end())
2020-11-24 15:41:18 +01:00
{
2021-04-30 16:10:14 +02:00
return (*it).second;
2020-11-24 15:41:18 +01:00
}
2021-04-30 16:10:14 +02:00
else
2020-11-24 15:41:18 +01:00
{
2021-04-30 16:10:14 +02:00
return emptystr;
2020-11-24 15:41:18 +01:00
}
2021-04-30 16:10:14 +02:00
}
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
const std::string& getBody() const
{
return mBody;
}
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
std::string& getWSCacheFrame()
{
return mWSCacheFrame;
}
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
std::string& getWSParseString()
{
return mWSParsePayload;
}
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
WebSocketFormat::WebSocketFrameType getWSFrameType() const
{
return mWSFrameType;
}
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
void cacheWSFrameType(WebSocketFormat::WebSocketFrameType frameType)
{
mWSFrameType = frameType;
}
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
private:
void clearParse()
{
mMethod = -1;
mIsUpgrade = false;
mIsWebSocket = false;
mISCompleted = false;
mLastWasValue = true;
mUrl.clear();
mQuery.clear();
mBody.clear();
mStatus.clear();
mCurrentField.clear();
mCurrentValue.clear();
mHeadValues.clear();
mPath.clear();
}
size_t tryParse(const char* buffer, size_t len)
{
const size_t nparsed = http_parser_execute(&mParser, &mSettings, buffer, len);
if (mISCompleted)
2020-11-24 15:41:18 +01:00
{
2021-04-30 16:10:14 +02:00
mIsUpgrade = mParser.upgrade;
mIsWebSocket = mIsUpgrade && hasEntry("Upgrade", "websocket");
mIsKeepAlive = hasEntry("Connection", "Keep-Alive");
mMethod = mParser.method;
http_parser_init(&mParser, mParserType);
2020-11-24 15:41:18 +01:00
}
2021-04-30 16:10:14 +02:00
return nparsed;
}
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
private:
static int sChunkHeader(http_parser* hp)
{
(void) hp;
return 0;
}
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
static int sChunkComplete(http_parser* hp)
{
(void) hp;
return 0;
}
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
static int sMessageBegin(http_parser* hp)
{
HTTPParser* httpParser = (HTTPParser*) hp->data;
httpParser->clearParse();
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
return 0;
}
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
static int sMessageEnd(http_parser* hp)
{
HTTPParser* httpParser = (HTTPParser*) hp->data;
httpParser->mISCompleted = true;
return 0;
}
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
static int sHeadComplete(http_parser* hp)
{
HTTPParser* httpParser = (HTTPParser*) hp->data;
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
if (httpParser->mUrl.empty())
2020-11-24 15:41:18 +01:00
{
return 0;
}
2021-04-30 16:10:14 +02:00
struct http_parser_url u;
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
const int result = http_parser_parse_url(httpParser->mUrl.data(),
httpParser->mUrl.size(),
0,
&u);
if (result != 0)
2020-11-24 15:41:18 +01:00
{
2021-04-30 16:10:14 +02:00
return -1;
2020-11-24 15:41:18 +01:00
}
2021-04-30 16:10:14 +02:00
if (!(u.field_set & (1 << UF_PATH)))
2020-11-24 15:41:18 +01:00
{
2021-04-30 16:10:14 +02:00
fprintf(stderr,
"\n\n*** failed to parse PATH in URL %s ***\n\n",
httpParser->mUrl.c_str());
return -1;
2020-11-24 15:41:18 +01:00
}
2021-04-30 16:10:14 +02:00
httpParser->mPath = std::string(
httpParser->mUrl.data() + u.field_data[UF_PATH].off,
u.field_data[UF_PATH].len);
if (u.field_set & (1 << UF_QUERY))
2020-11-24 15:41:18 +01:00
{
2021-04-30 16:10:14 +02:00
httpParser->mQuery = std::string(
httpParser->mUrl.data() + u.field_data[UF_QUERY].off,
u.field_data[UF_QUERY].len);
2020-11-24 15:41:18 +01:00
}
2021-04-30 16:10:14 +02:00
return 0;
}
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
static int sUrlHandle(http_parser* hp, const char* url, size_t length)
{
HTTPParser* httpParser = (HTTPParser*) hp->data;
httpParser->mUrl.append(url, length);
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
return 0;
}
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
static int sHeadValue(http_parser* hp, const char* at, size_t length)
{
HTTPParser* httpParser = (HTTPParser*) hp->data;
auto& value = httpParser->mHeadValues[httpParser->mCurrentField];
value.append(at, length);
httpParser->mLastWasValue = true;
return 0;
}
static int sHeadField(http_parser* hp, const char* at, size_t length)
{
HTTPParser* httpParser = (HTTPParser*) hp->data;
if (httpParser->mLastWasValue)
{
httpParser->mCurrentField.clear();
}
httpParser->mCurrentField.append(at, length);
httpParser->mLastWasValue = false;
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
return 0;
}
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
static int sStatusHandle(http_parser* hp, const char* at, size_t length)
{
HTTPParser* httpParser = (HTTPParser*) hp->data;
httpParser->mStatus.append(at, length);
httpParser->mStatusCode = hp->status_code;
return 0;
}
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
static int sBodyHandle(http_parser* hp, const char* at, size_t length)
{
HTTPParser* httpParser = (HTTPParser*) hp->data;
httpParser->mBody.append(at, length);
return 0;
}
private:
const http_parser_type mParserType;
http_parser mParser;
http_parser_settings mSettings;
int mMethod = -1;
bool mIsUpgrade = false;
bool mIsWebSocket = false;
bool mIsKeepAlive;
bool mISCompleted;
bool mLastWasValue;
std::string mCurrentField;
std::string mCurrentValue;
std::string mPath;
std::string mQuery;
std::string mStatus;
std::map<std::string, std::string> mHeadValues;
int mStatusCode;
std::string mUrl;
std::string mBody;
std::string mWSCacheFrame;
std::string mWSParsePayload;
WebSocketFormat::WebSocketFrameType mWSFrameType;
private:
friend class HttpService;
};
}}}// namespace brynet::net::http