Commit 0d2e65a1 authored by Ian Roddis's avatar Ian Roddis

Adding test case, moving max payload size to Tcp::Handler to try and help with cloning

parent 4e45bc59
...@@ -791,12 +791,6 @@ namespace Private { ...@@ -791,12 +791,6 @@ namespace Private {
class Handler : public Tcp::Handler { class Handler : public Tcp::Handler {
public: public:
Handler() : maxPayload_(Const::DefaultMaxPayload) {}
Handler(size_t maxPayload) : maxPayload_(maxPayload) { }
size_t getMaxPayload() { return maxPayload_; }
void setMaxPayload(size_t sz) { maxPayload_ = sz; }
void onInput(const char* buffer, size_t len, const std::shared_ptr<Tcp::Peer>& peer); void onInput(const char* buffer, size_t len, const std::shared_ptr<Tcp::Peer>& peer);
void onConnection(const std::shared_ptr<Tcp::Peer>& peer); void onConnection(const std::shared_ptr<Tcp::Peer>& peer);
...@@ -810,8 +804,6 @@ public: ...@@ -810,8 +804,6 @@ public:
private: private:
Private::Parser<Http::Request>& getParser(const std::shared_ptr<Tcp::Peer>& peer) const; Private::Parser<Http::Request>& getParser(const std::shared_ptr<Tcp::Peer>& peer) const;
protected:
size_t maxPayload_;
}; };
template<typename H, typename... Args> template<typename H, typename... Args>
......
...@@ -155,6 +155,9 @@ public: ...@@ -155,6 +155,9 @@ public:
void addCustomHandler(Route::Handler handler); void addCustomHandler(Route::Handler handler);
void setMaxPayload(size_t maxPayload);
size_t getMaxPayload() const;
void addNotFoundHandler(Route::Handler handler); void addNotFoundHandler(Route::Handler handler);
inline bool hasNotFoundHandler() { return notFoundHandler != nullptr; } inline bool hasNotFoundHandler() { return notFoundHandler != nullptr; }
void invokeNotFoundHandler(const Http::Request &req, Http::ResponseWriter resp) const; void invokeNotFoundHandler(const Http::Request &req, Http::ResponseWriter resp) const;
...@@ -166,6 +169,7 @@ private: ...@@ -166,6 +169,7 @@ private:
std::unordered_map<Http::Method, std::vector<Route>> routes; std::unordered_map<Http::Method, std::vector<Route>> routes;
std::vector<Route::Handler> customHandlers; std::vector<Route::Handler> customHandlers;
size_t maxPayload_;
Route::Handler notFoundHandler; Route::Handler notFoundHandler;
}; };
...@@ -182,7 +186,7 @@ namespace Private { ...@@ -182,7 +186,7 @@ namespace Private {
private: private:
std::shared_ptr<Tcp::Handler> clone() const { std::shared_ptr<Tcp::Handler> clone() const {
return std::make_shared<RouterHandler>(router); return std::make_shared<RouterHandler>(*this);
} }
Rest::Router router; Rest::Router router;
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include <pistache/flags.h> #include <pistache/flags.h>
#include <pistache/prototype.h> #include <pistache/prototype.h>
#include <pistache/common.h>
namespace Pistache { namespace Pistache {
namespace Tcp { namespace Tcp {
...@@ -36,23 +37,29 @@ public: ...@@ -36,23 +37,29 @@ public:
friend class Transport; friend class Transport;
Handler(); Handler();
Handler(const Handler & rhs);
~Handler(); ~Handler();
size_t getMaxPayload() { return maxPayload_; }
void setMaxPayload(size_t sz) { maxPayload_ = sz; }
virtual void onInput(const char *buffer, size_t len, const std::shared_ptr<Tcp::Peer>& peer) = 0; virtual void onInput(const char *buffer, size_t len, const std::shared_ptr<Tcp::Peer>& peer) = 0;
virtual void onConnection(const std::shared_ptr<Tcp::Peer>& peer); virtual void onConnection(const std::shared_ptr<Tcp::Peer>& peer);
virtual void onDisconnection(const std::shared_ptr<Tcp::Peer>& peer); virtual void onDisconnection(const std::shared_ptr<Tcp::Peer>& peer);
private:
void associateTransport(Transport* transport);
Transport *transport_;
protected: protected:
Transport *transport() { Transport *transport() {
if (!transport_) if (!transport_)
throw std::logic_error("Orphaned handler"); throw std::logic_error("Orphaned handler");
return transport_; return transport_;
} }
size_t maxPayload_;
private:
void associateTransport(Transport* transport);
Transport *transport_;
}; };
} // namespace Tcp } // namespace Tcp
......
...@@ -12,6 +12,13 @@ namespace Tcp { ...@@ -12,6 +12,13 @@ namespace Tcp {
Handler::Handler() Handler::Handler()
: transport_(nullptr) : transport_(nullptr)
, maxPayload_(Const::DefaultMaxPayload)
{
}
Handler::Handler(const Handler & rhs)
: transport_(nullptr)
, maxPayload_(rhs.maxPayload_)
{ } { }
Handler::~Handler() Handler::~Handler()
......
...@@ -244,7 +244,9 @@ Router::fromDescription(const Rest::Description& desc) { ...@@ -244,7 +244,9 @@ Router::fromDescription(const Rest::Description& desc) {
std::shared_ptr<Private::RouterHandler> std::shared_ptr<Private::RouterHandler>
Router::handler() const { Router::handler() const {
return std::make_shared<Private::RouterHandler>(*this); auto handler = std::make_shared<Private::RouterHandler>(*this);
handler->setMaxPayload(maxPayload_);
return std::move(handler);
} }
void void
...@@ -258,7 +260,6 @@ Router::initFromDescription(const Rest::Description& desc) { ...@@ -258,7 +260,6 @@ Router::initFromDescription(const Rest::Description& desc) {
oss << "Path '" << path.value << "' is not bound"; oss << "Path '" << path.value << "' is not bound";
throw std::runtime_error(oss.str()); throw std::runtime_error(oss.str());
} }
addRoute(path.method, std::move(path.value), std::move(path.handler)); addRoute(path.method, std::move(path.value), std::move(path.handler));
} }
} }
...@@ -299,6 +300,17 @@ Router::addCustomHandler(Route::Handler handler) { ...@@ -299,6 +300,17 @@ Router::addCustomHandler(Route::Handler handler) {
customHandlers.push_back(std::move(handler)); customHandlers.push_back(std::move(handler));
} }
void
Router::setMaxPayload(size_t maxPayload) {
maxPayload_ = maxPayload;
}
size_t
Router::getMaxPayload() const {
return maxPayload_;
}
void void
Router::addNotFoundHandler(Route::Handler handler) { Router::addNotFoundHandler(Route::Handler handler) {
notFoundHandler = std::move(handler); notFoundHandler = std::move(handler);
......
...@@ -17,4 +17,5 @@ pistache_test(cookie_test) ...@@ -17,4 +17,5 @@ pistache_test(cookie_test)
pistache_test(view_test) pistache_test(view_test)
pistache_test(http_parsing_test) pistache_test(http_parsing_test)
pistache_test(http_client_test) pistache_test(http_client_test)
pistache_test(net_test) pistache_test(net_test)
\ No newline at end of file pistache_test(payload_test)
#include "gtest/gtest.h"
#include <pistache/http.h>
#include <pistache/description.h>
#include <pistache/client.h>
#include <pistache/endpoint.h>
using namespace std;
using namespace Pistache;
struct TestParameter {
size_t payloadBytes;
Http::Code expectedResponseCode;
};
typedef std::vector<TestParameter> PayloadTestSizes;
void testPayloads(std::string url, PayloadTestSizes & testPayloads) {
// Client tests to make sure the payload is enforced
Http::Client client;
auto client_opts = Http::Client::options().threads(1).maxConnectionsPerHost(1);
client.init(client_opts);
std::vector<Async::Promise<Http::Response>> responses;
size_t tests_passed = 0;
for (auto & t : testPayloads) {
auto rb = client.post(url);
std::string payload(t.payloadBytes, 'A');
auto response = rb.body(payload).send();
response.then([t,&tests_passed](Http::Response rsp) {
if (rsp.code() == t.expectedResponseCode)
++tests_passed;
}, Async::IgnoreException);
responses.push_back(std::move(response));
}
auto sync = Async::whenAll(responses.begin(), responses.end());
Async::Barrier<std::vector<Http::Response>> barrier(sync);
barrier.wait_for(std::chrono::seconds(5));
client.shutdown();
ASSERT_TRUE(tests_passed == testPayloads.size());
}
void handleEcho(const Rest::Request&req, Http::ResponseWriter response) {
response.send(Http::Code::Ok, req.body(), MIME(Text, Plain));
}
TEST(payload_test, from_description)
{
Address addr(Ipv4::any(), 9084);
const size_t threads = 2;
const size_t max_payload = 1024; // very small
std::shared_ptr<Http::Endpoint> endpoint;
Rest::Description desc("Rest Description Test", "v1");
Rest::Router router;
desc
.route(desc.post("/echo"))
.bind(&handleEcho)
.response(Http::Code::Ok, "Response to the /ready call");
router.initFromDescription(desc);
router.setMaxPayload(max_payload);
auto flags = Tcp::Options::InstallSignalHandler | Tcp::Options::ReuseAddr;
auto opts = Http::Endpoint::options()
.threads(threads)
.flags(flags);
endpoint = std::make_shared<Pistache::Http::Endpoint>(addr);
endpoint->init(opts);
endpoint->setHandler(router.handler());
ASSERT_EQ(router.handler()->getMaxPayload(), max_payload);
endpoint->serveThreaded();
PayloadTestSizes payloads{
{1024, Http::Code::Ok}
,{2048, Http::Code::Request_Entity_Too_Large}
};
testPayloads("127.0.0.1:9084/echo", payloads);
endpoint->shutdown();
}
TEST(payload_test, manual_construction) {
class MyHandler : public Http::Handler {
HTTP_PROTOTYPE(MyHandler)
void onRequest(
const Http::Request& req,
Http::ResponseWriter response)
{
if (req.resource() == "/echo") {
if (req.method() == Http::Method::Post) {
response.send(Http::Code::Ok, req.body(), MIME(Text, Plain));
} else {
response.send(Http::Code::Method_Not_Allowed);
}
} else {
response.send(Http::Code::Not_Found);
}
}
private:
tag garbage;
};
Port port(9080);
int thr = 2;
Address addr(Ipv4::any(), port);
auto server = std::make_shared<Http::Endpoint>(addr);
size_t maxPayload = 2048;
auto opts = Http::Endpoint::options()
.threads(thr)
.flags(Tcp::Options::InstallSignalHandler)
.maxPayload(maxPayload);
server->init(opts);
server->setHandler(Http::make_handler<MyHandler>());
server->serveThreaded();
PayloadTestSizes payloads{
{1024, Http::Code::Ok}
, {1800, Http::Code::Ok}
, {2048, Http::Code::Request_Entity_Too_Large}
};
testPayloads("127.0.0.1:9080/echo", payloads);
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment