mirror of
https://github.com/openappsec/openappsec.git
synced 2025-09-29 19:24:26 +03:00
sync code
This commit is contained in:
@@ -25,6 +25,9 @@ public:
|
||||
virtual Maybe<std::string> getSchema(const std::string &uri) const = 0;
|
||||
virtual Maybe<std::string> invokeRest(const std::string &uri, std::istream &in) const = 0;
|
||||
|
||||
virtual bool isGetCall(const std::string &uri) const = 0;
|
||||
virtual std::string invokeGet(const std::string &uri) const = 0;
|
||||
|
||||
protected:
|
||||
~I_RestInvoke() {}
|
||||
};
|
||||
|
@@ -97,6 +97,10 @@ RestConn::parseConn() const
|
||||
stop();
|
||||
}
|
||||
|
||||
if (method=="GET" && invoke->isGetCall(identifier)) {
|
||||
return sendResponse("200 OK", invoke->invokeGet(identifier), false);
|
||||
}
|
||||
|
||||
stringstream body;
|
||||
body.str(readSize(len));
|
||||
|
||||
@@ -152,15 +156,16 @@ RestConn::readSize(int len) const
|
||||
}
|
||||
|
||||
void
|
||||
RestConn::sendResponse(const string &status, const string &body) const
|
||||
RestConn::sendResponse(const string &status, const string &body, bool add_newline) const
|
||||
{
|
||||
stringstream stream;
|
||||
stream <<
|
||||
"HTTP/1.1 " << status << "\r\n" <<
|
||||
"Content-Type: application/json\r\n" <<
|
||||
"Content-Length: " << (body.size() + 2) << "\r\n" <<
|
||||
"Content-Length: " << (body.size() + (add_newline ? 2 : 0)) << "\r\n" <<
|
||||
"\r\n" <<
|
||||
body << "\r\n";
|
||||
body;
|
||||
if (add_newline) stream << "\r\n";
|
||||
|
||||
|
||||
string res = stream.str();
|
||||
|
@@ -30,7 +30,7 @@ private:
|
||||
void stop() const;
|
||||
std::string readLine() const;
|
||||
std::string readSize(int len) const;
|
||||
void sendResponse(const std::string &status, const std::string &body) const;
|
||||
void sendResponse(const std::string &status, const std::string &body, bool add_newline = true) const;
|
||||
|
||||
int fd;
|
||||
I_MainLoop *mainloop;
|
||||
|
@@ -31,6 +31,7 @@ USE_DEBUG_FLAG(D_API);
|
||||
|
||||
static const int listen_limit = 100;
|
||||
static const chrono::milliseconds bind_retry_interval_msec = chrono::milliseconds(500);
|
||||
static const AlertInfo alert(AlertTeam::CORE, "rest i/s");
|
||||
|
||||
#include <iostream>
|
||||
|
||||
@@ -47,9 +48,12 @@ public:
|
||||
|
||||
bool bindRestServerSocket(struct sockaddr_in &addr, vector<uint16_t> port_range);
|
||||
bool addRestCall(RestAction oper, const string &uri, unique_ptr<RestInit> &&init) override;
|
||||
bool addGetCall(const string &uri, const function<string()> &cb) override;
|
||||
uint16_t getListeningPort() const override { return listening_port; }
|
||||
Maybe<std::string> getSchema(const std::string &uri) const override;
|
||||
Maybe<std::string> invokeRest(const std::string &uri, istream &in) const override;
|
||||
Maybe<string> getSchema(const string &uri) const override;
|
||||
Maybe<string> invokeRest(const string &uri, istream &in) const override;
|
||||
bool isGetCall(const string &uri) const override;
|
||||
string invokeGet(const string &uri) const override;
|
||||
|
||||
private:
|
||||
void prepareConfiguration();
|
||||
@@ -61,6 +65,7 @@ private:
|
||||
I_MainLoop::RoutineID id;
|
||||
I_MainLoop *mainloop;
|
||||
map<string, unique_ptr<RestInit>> rest_calls;
|
||||
map<string, function<string()>> get_calls;
|
||||
uint16_t listening_port = 0;
|
||||
vector<uint16_t> port_range;
|
||||
};
|
||||
@@ -96,8 +101,10 @@ RestServer::Impl::prepareConfiguration()
|
||||
} else {
|
||||
auto range_start = getPortConfig("Nano service API Port Range start");
|
||||
auto range_end = getPortConfig("Nano service API Port Range end");
|
||||
dbgAssert(range_start.ok() && range_end.ok()) << "Rest port configuration was not provided";
|
||||
dbgAssert(*range_start < *range_end) << "Rest port range corrupted (lower bound higher then upper bound)";
|
||||
dbgAssert(range_start.ok() && range_end.ok()) << alert << "Rest port configuration was not provided";
|
||||
dbgAssert(*range_start < *range_end)
|
||||
<< alert
|
||||
<< "Rest port range corrupted (lower bound higher then upper bound)";
|
||||
|
||||
port_range.resize(*range_end - *range_start);
|
||||
for (uint16_t i = 0, port = *range_start; i < port_range.size(); i++, port++) {
|
||||
@@ -113,7 +120,7 @@ RestServer::Impl::init()
|
||||
|
||||
auto init_connection = [this] () {
|
||||
fd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
dbgAssert(fd >= 0) << "Failed to open a socket";
|
||||
dbgAssert(fd >= 0) << alert << "Failed to open a socket";
|
||||
int socket_enable = 1;
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &socket_enable, sizeof(int)) < 0) {
|
||||
dbgWarning(D_API) << "Could not set the socket options";
|
||||
@@ -185,11 +192,19 @@ bool
|
||||
RestServer::Impl::addRestCall(RestAction oper, const string &uri, unique_ptr<RestInit> &&rest)
|
||||
{
|
||||
string full_uri = changeActionToString(oper) + uri;
|
||||
if (get_calls.find(full_uri) != get_calls.end()) return false;
|
||||
return rest_calls.emplace(make_pair(full_uri, move(rest))).second;
|
||||
}
|
||||
|
||||
Maybe<std::string>
|
||||
RestServer::Impl::getSchema(const std::string &uri) const
|
||||
bool
|
||||
RestServer::Impl::addGetCall(const string &uri, const function<string()> &callback)
|
||||
{
|
||||
if (rest_calls.find(uri) != rest_calls.end()) return false;
|
||||
return get_calls.emplace(uri, callback).second;
|
||||
}
|
||||
|
||||
Maybe<string>
|
||||
RestServer::Impl::getSchema(const string &uri) const
|
||||
{
|
||||
auto iter = rest_calls.find(uri);
|
||||
if (iter == rest_calls.end()) return genError("No matching REST call was found");
|
||||
@@ -200,8 +215,8 @@ RestServer::Impl::getSchema(const std::string &uri) const
|
||||
return out.str();
|
||||
}
|
||||
|
||||
Maybe<std::string>
|
||||
RestServer::Impl::invokeRest(const std::string &uri, istream &in) const
|
||||
Maybe<string>
|
||||
RestServer::Impl::invokeRest(const string &uri, istream &in) const
|
||||
{
|
||||
auto iter = rest_calls.find(uri);
|
||||
if (iter == rest_calls.end()) return genError("No matching REST call was found");
|
||||
@@ -209,6 +224,19 @@ RestServer::Impl::invokeRest(const std::string &uri, istream &in) const
|
||||
return instance->performRestCall(in);
|
||||
}
|
||||
|
||||
bool
|
||||
RestServer::Impl::isGetCall(const string &uri) const
|
||||
{
|
||||
return get_calls.find(uri) != get_calls.end();
|
||||
}
|
||||
|
||||
string
|
||||
RestServer::Impl::invokeGet(const string &uri) const
|
||||
{
|
||||
auto instance = get_calls.find(uri);
|
||||
return instance != get_calls.end() ? instance->second() : "";
|
||||
}
|
||||
|
||||
string
|
||||
RestServer::Impl::changeActionToString(RestAction oper)
|
||||
{
|
||||
@@ -226,7 +254,7 @@ RestServer::Impl::changeActionToString(RestAction oper)
|
||||
return "delete-";
|
||||
}
|
||||
default: {
|
||||
dbgAssert(false) << "Unknown REST action";
|
||||
dbgAssert(false) << alert << "Unknown REST action";
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
@@ -1,6 +1,7 @@
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <poll.h>
|
||||
|
||||
#include "cptest.h"
|
||||
#include "environment.h"
|
||||
@@ -143,9 +144,12 @@ TEST_F(RestConfigTest, basic_flow)
|
||||
|
||||
auto i_rest = Singleton::Consume<I_RestApi>::from(rest_server);
|
||||
ASSERT_TRUE(i_rest->addRestCall<TestServer>(RestAction::ADD, "test"));
|
||||
ASSERT_TRUE(i_rest->addGetCall("stuff", [] () { return string("blabla"); }));
|
||||
|
||||
int file_descriptor = socket(AF_INET, SOCK_STREAM, 0);
|
||||
EXPECT_NE(file_descriptor, -1);
|
||||
int file_descriptor1 = socket(AF_INET, SOCK_STREAM, 0);
|
||||
EXPECT_NE(file_descriptor1, -1);
|
||||
int file_descriptor2 = socket(AF_INET, SOCK_STREAM, 0);
|
||||
EXPECT_NE(file_descriptor2, -1);
|
||||
|
||||
auto primary_port = getConfiguration<uint>("connection", "Nano service API Port Alternative");
|
||||
struct sockaddr_in sa;
|
||||
@@ -153,20 +157,34 @@ TEST_F(RestConfigTest, basic_flow)
|
||||
sa.sin_port = htons(primary_port.unpack());
|
||||
sa.sin_addr.s_addr = inet_addr("127.0.0.1");
|
||||
int socket_enable = 1;
|
||||
EXPECT_EQ(setsockopt(file_descriptor, SOL_SOCKET, SO_REUSEADDR, &socket_enable, sizeof(int)), 0);
|
||||
EXPECT_EQ(setsockopt(file_descriptor1, SOL_SOCKET, SO_REUSEADDR, &socket_enable, sizeof(int)), 0);
|
||||
EXPECT_EQ(setsockopt(file_descriptor2, SOL_SOCKET, SO_REUSEADDR, &socket_enable, sizeof(int)), 0);
|
||||
|
||||
EXPECT_CALL(messaging, sendSyncMessage(_, _, _, _, _))
|
||||
.WillRepeatedly(Return(HTTPResponse(HTTPStatusCode::HTTP_OK, "")));
|
||||
|
||||
auto mainloop = Singleton::Consume<I_MainLoop>::from(mainloop_comp);
|
||||
I_MainLoop::Routine stop_routine = [&] () {
|
||||
EXPECT_EQ(connect(file_descriptor, (struct sockaddr*)&sa, sizeof(struct sockaddr)), 0);
|
||||
string msg = "POST /add-test HTTP/1.1\r\nContent-Length: 10\r\n\r\n{\"num\": 5}";
|
||||
EXPECT_EQ(write(file_descriptor, msg.data(), msg.size()), static_cast<int>(msg.size()));
|
||||
EXPECT_EQ(connect(file_descriptor1, (struct sockaddr*)&sa, sizeof(struct sockaddr)), 0);
|
||||
string msg1 = "GET /stuff HTTP/1.1\r\n\r\n";
|
||||
EXPECT_EQ(write(file_descriptor1, msg1.data(), msg1.size()), static_cast<int>(msg1.size()));
|
||||
|
||||
EXPECT_EQ(connect(file_descriptor2, (struct sockaddr*)&sa, sizeof(struct sockaddr)), 0);
|
||||
string msg2 = "POST /add-test HTTP/1.1\r\nContent-Length: 10\r\n\r\n{\"num\": 5}";
|
||||
EXPECT_EQ(write(file_descriptor2, msg2.data(), msg2.size()), static_cast<int>(msg2.size()));
|
||||
|
||||
while(!TestServer::g_num) {
|
||||
mainloop->yield(true);
|
||||
}
|
||||
|
||||
struct pollfd s_poll;
|
||||
s_poll.fd = file_descriptor1;
|
||||
s_poll.events = POLLIN;
|
||||
s_poll.revents = 0;
|
||||
while(poll(&s_poll, 1, 0) <= 0) {
|
||||
mainloop->yield(true);
|
||||
}
|
||||
|
||||
mainloop->stopAll();
|
||||
};
|
||||
mainloop->addOneTimeRoutine(
|
||||
@@ -178,4 +196,11 @@ TEST_F(RestConfigTest, basic_flow)
|
||||
mainloop->run();
|
||||
|
||||
EXPECT_EQ(TestServer::g_num, 5);
|
||||
|
||||
char respose[1000];
|
||||
EXPECT_EQ(read(file_descriptor1, respose, 1000), 76);
|
||||
EXPECT_EQ(
|
||||
string(respose, 76),
|
||||
"HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: 6\r\n\r\nblabla"
|
||||
);
|
||||
}
|
||||
|
Reference in New Issue
Block a user