mirror of
https://github.com/drogonframework/drogon.git
synced 2025-07-23 00:01:23 -04:00
Compare commits
18 Commits
ab73516ae1
...
9d80aaa1e9
Author | SHA1 | Date | |
---|---|---|---|
|
9d80aaa1e9 | ||
|
75f197ecd4 | ||
|
8ce2b853d9 | ||
|
781ef3c194 | ||
|
3eddcafe73 | ||
|
09a8634838 | ||
|
3ea63787e7 | ||
|
7202330f10 | ||
|
e27b800b33 | ||
|
98678dd331 | ||
|
f2a7ac8b2f | ||
|
89786de0fe | ||
|
49cfea3b4a | ||
|
a3a6267577 | ||
|
69f592b726 | ||
|
a0a9f7a337 | ||
|
1a27e8bf1e | ||
|
05a18675fe |
@ -13,7 +13,7 @@ Drogon is a cross-platform framework, It supports Linux, macOS, FreeBSD, OpenBSD
|
|||||||
|
|
||||||
* Use a non-blocking I/O network lib based on epoll (kqueue under macOS/FreeBSD) to provide high-concurrency, high-performance network IO, please visit the [TFB Tests Results](https://www.techempower.com/benchmarks/#section=data-r19&hw=ph&test=composite) for more details;
|
* Use a non-blocking I/O network lib based on epoll (kqueue under macOS/FreeBSD) to provide high-concurrency, high-performance network IO, please visit the [TFB Tests Results](https://www.techempower.com/benchmarks/#section=data-r19&hw=ph&test=composite) for more details;
|
||||||
* Provide a completely asynchronous programming mode;
|
* Provide a completely asynchronous programming mode;
|
||||||
* Support Http1.0/1.1 (server side and client side);
|
* Support HTTP/2 (and 1.0/1.1) client and HTTP 1.1/1.0 server
|
||||||
* Based on template, a simple reflection mechanism is implemented to completely decouple the main program framework, controllers and views.
|
* Based on template, a simple reflection mechanism is implemented to completely decouple the main program framework, controllers and views.
|
||||||
* Support cookies and built-in sessions;
|
* Support cookies and built-in sessions;
|
||||||
* Support back-end rendering, the controller generates the data to the view to generate the Html page. Views are described by CSP template files, C++ codes are embedded into Html pages through CSP tags. And the drogon command-line tool automatically generates the C++ code files for compilation;
|
* Support back-end rendering, the controller generates the data to the view to generate the Html page. Views are described by CSP template files, C++ codes are embedded into Html pages through CSP tags. And the drogon command-line tool automatically generates the C++ code files for compilation;
|
||||||
|
@ -16,7 +16,7 @@ int main()
|
|||||||
{
|
{
|
||||||
trantor::Logger::setLogLevel(trantor::Logger::kTrace);
|
trantor::Logger::setLogLevel(trantor::Logger::kTrace);
|
||||||
{
|
{
|
||||||
auto client = HttpClient::newHttpClient("https://clehaxze.tw:8844",
|
auto client = HttpClient::newHttpClient("https://clehaxze.tw",
|
||||||
nullptr,
|
nullptr,
|
||||||
false,
|
false,
|
||||||
false);
|
false);
|
||||||
@ -48,7 +48,7 @@ int main()
|
|||||||
req->setParameter("wd", "wx");
|
req->setParameter("wd", "wx");
|
||||||
req->setParameter("oq", "wx");
|
req->setParameter("oq", "wx");
|
||||||
|
|
||||||
for (int i = 0; i < 1; ++i)
|
for (int i = 0; i < 2; ++i)
|
||||||
{
|
{
|
||||||
client->sendRequest(
|
client->sendRequest(
|
||||||
req, [](ReqResult result, const HttpResponsePtr &response) {
|
req, [](ReqResult result, const HttpResponsePtr &response) {
|
||||||
@ -76,7 +76,6 @@ int main()
|
|||||||
});
|
});
|
||||||
LOG_INFO << "send request";
|
LOG_INFO << "send request";
|
||||||
}
|
}
|
||||||
|
|
||||||
app().run();
|
|
||||||
}
|
}
|
||||||
|
app().run();
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -5,11 +5,93 @@
|
|||||||
// TOOD: Write our own HPACK implementation
|
// TOOD: Write our own HPACK implementation
|
||||||
#include "hpack/HPacker.h"
|
#include "hpack/HPacker.h"
|
||||||
|
|
||||||
|
#include <variant>
|
||||||
|
|
||||||
namespace drogon
|
namespace drogon
|
||||||
{
|
{
|
||||||
|
|
||||||
namespace internal
|
namespace internal
|
||||||
{
|
{
|
||||||
|
struct ByteStream;
|
||||||
|
struct OByteStream;
|
||||||
|
|
||||||
|
struct SettingsFrame
|
||||||
|
{
|
||||||
|
bool ack = false;
|
||||||
|
std::vector<std::pair<uint16_t, uint32_t>> settings;
|
||||||
|
|
||||||
|
static std::optional<SettingsFrame> parse(ByteStream &payload,
|
||||||
|
uint8_t flags);
|
||||||
|
bool serialize(OByteStream &stream, uint8_t &flags) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct WindowUpdateFrame
|
||||||
|
{
|
||||||
|
uint32_t windowSizeIncrement = 0;
|
||||||
|
|
||||||
|
static std::optional<WindowUpdateFrame> parse(ByteStream &payload,
|
||||||
|
uint8_t flags);
|
||||||
|
bool serialize(OByteStream &stream, uint8_t &flags) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct HeadersFrame
|
||||||
|
{
|
||||||
|
uint8_t padLength = 0;
|
||||||
|
bool exclusive = false;
|
||||||
|
uint32_t streamDependency = 0;
|
||||||
|
uint8_t weight = 0;
|
||||||
|
std::vector<uint8_t> headerBlockFragment;
|
||||||
|
bool endHeaders = false;
|
||||||
|
bool endStream = false;
|
||||||
|
|
||||||
|
static std::optional<HeadersFrame> parse(ByteStream &payload,
|
||||||
|
uint8_t flags);
|
||||||
|
bool serialize(OByteStream &stream, uint8_t &flags) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GoAwayFrame
|
||||||
|
{
|
||||||
|
uint32_t lastStreamId = 0;
|
||||||
|
uint32_t errorCode = 0;
|
||||||
|
std::vector<uint8_t> additionalDebugData;
|
||||||
|
|
||||||
|
static std::optional<GoAwayFrame> parse(ByteStream &payload, uint8_t flags);
|
||||||
|
bool serialize(OByteStream &stream, uint8_t &flags) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DataFrame
|
||||||
|
{
|
||||||
|
uint8_t padLength = 0;
|
||||||
|
std::vector<uint8_t> data;
|
||||||
|
bool endStream = false;
|
||||||
|
|
||||||
|
static std::optional<DataFrame> parse(ByteStream &payload, uint8_t flags);
|
||||||
|
bool serialize(OByteStream &stream, uint8_t &flags) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PingFrame
|
||||||
|
{
|
||||||
|
std::array<uint8_t, 8> opaqueData;
|
||||||
|
bool ack = false;
|
||||||
|
|
||||||
|
static std::optional<PingFrame> parse(ByteStream &payload, uint8_t flags);
|
||||||
|
bool serialize(OByteStream &stream, uint8_t &flags) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
using H2Frame = std::variant<SettingsFrame,
|
||||||
|
WindowUpdateFrame,
|
||||||
|
HeadersFrame,
|
||||||
|
GoAwayFrame,
|
||||||
|
DataFrame,
|
||||||
|
PingFrame>;
|
||||||
|
|
||||||
|
enum class StreamState
|
||||||
|
{
|
||||||
|
ExpectingHeaders,
|
||||||
|
ExpectingContinuation,
|
||||||
|
ExpectingData,
|
||||||
|
Finished,
|
||||||
|
};
|
||||||
|
|
||||||
// Virtual stream that holds properties for the HTTP/2 stream
|
// Virtual stream that holds properties for the HTTP/2 stream
|
||||||
// Defaults to stream 0 global properties
|
// Defaults to stream 0 global properties
|
||||||
@ -17,11 +99,32 @@ struct H2Stream
|
|||||||
{
|
{
|
||||||
HttpReqCallback callback;
|
HttpReqCallback callback;
|
||||||
HttpResponseImplPtr response;
|
HttpResponseImplPtr response;
|
||||||
|
HttpRequestPtr request;
|
||||||
trantor::MsgBuffer body;
|
trantor::MsgBuffer body;
|
||||||
|
std::optional<size_t> contentLength;
|
||||||
|
int32_t streamId = 0;
|
||||||
|
StreamState state = StreamState::ExpectingHeaders;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
|
|
||||||
|
enum class StreamCloseErrorCode
|
||||||
|
{
|
||||||
|
NoError = 0x0,
|
||||||
|
ProtocolError = 0x1,
|
||||||
|
InternalError = 0x2,
|
||||||
|
FlowControlError = 0x3,
|
||||||
|
SettingsTimeout = 0x4,
|
||||||
|
StreamClosed = 0x5,
|
||||||
|
FrameSizeError = 0x6,
|
||||||
|
RefusedStream = 0x7,
|
||||||
|
Cancel = 0x8,
|
||||||
|
CompressionError = 0x9,
|
||||||
|
ConnectError = 0xa,
|
||||||
|
EnhanceYourCalm = 0xb,
|
||||||
|
InadequateSecurity = 0xc,
|
||||||
|
Http11Required = 0xd,
|
||||||
|
};
|
||||||
|
|
||||||
class Http2Transport : public HttpTransport
|
class Http2Transport : public HttpTransport
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
@ -42,9 +145,21 @@ class Http2Transport : public HttpTransport
|
|||||||
size_t maxFrameSize = 16384;
|
size_t maxFrameSize = 16384;
|
||||||
size_t avaliableWindowSize = 0;
|
size_t avaliableWindowSize = 0;
|
||||||
|
|
||||||
|
// Configuration settings
|
||||||
|
const size_t windowIncreaseThreshold = 32768;
|
||||||
|
const size_t windowIncreaseSize = 10 * 1024 * 1024; // 10 MiB
|
||||||
|
|
||||||
// Set after server settings are received
|
// Set after server settings are received
|
||||||
bool serverSettingsReceived = false;
|
bool serverSettingsReceived = false;
|
||||||
std::vector<std::pair<HttpRequestPtr, HttpReqCallback>> bufferedRequests;
|
std::queue<std::pair<HttpRequestPtr, HttpReqCallback>> bufferedRequests;
|
||||||
|
size_t avaliableWindow = 10 * 1024 * 1024; // 10 MiB
|
||||||
|
|
||||||
|
internal::H2Stream &createStream(int32_t streamId);
|
||||||
|
void streamFinished(internal::H2Stream &stream);
|
||||||
|
void streamFinished(int32_t streamId,
|
||||||
|
ReqResult result,
|
||||||
|
StreamCloseErrorCode errorCode,
|
||||||
|
std::string errorMsg = "");
|
||||||
|
|
||||||
int32_t nextStreamId()
|
int32_t nextStreamId()
|
||||||
{
|
{
|
||||||
@ -78,6 +193,10 @@ class Http2Transport : public HttpTransport
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void handleFrameForStream(const internal::H2Frame &frame,
|
||||||
|
int32_t streamId,
|
||||||
|
uint8_t flags);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Http2Transport(trantor::TcpConnectionPtr connPtr,
|
Http2Transport(trantor::TcpConnectionPtr connPtr,
|
||||||
size_t *bytesSent,
|
size_t *bytesSent,
|
||||||
@ -99,10 +218,7 @@ class Http2Transport : public HttpTransport
|
|||||||
"HTTP/2 handleConnectionClose not implemented");
|
"HTTP/2 handleConnectionClose not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
void onError(ReqResult result) override
|
void onError(ReqResult result) override;
|
||||||
{
|
|
||||||
throw std::runtime_error("HTTP/2 onError not implemented");
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void onServerSettingsReceived(){};
|
void onServerSettingsReceived(){};
|
||||||
|
@ -109,6 +109,9 @@ const char *HttpResponseImpl::versionString() const
|
|||||||
case Version::kHttp11:
|
case Version::kHttp11:
|
||||||
result = "HTTP/1.1";
|
result = "HTTP/1.1";
|
||||||
break;
|
break;
|
||||||
|
case Version::kHttp2:
|
||||||
|
result = "HTTP/2";
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user