1
0
Fork 0
mirror of https://git.rwth-aachen.de/acs/public/villas/node/ synced 2025-03-09 00:00:00 +01:00

api: improve error responses

This commit is contained in:
Steffen Vogel 2020-09-30 16:11:13 +02:00
parent c7f96e1a97
commit e59cd8ac15
10 changed files with 64 additions and 55 deletions

View file

@ -51,19 +51,34 @@ class Request;
class Error : public RuntimeError {
public:
Error(int c = HTTP_STATUS_INTERNAL_SERVER_ERROR, const std::string &msg = "Invalid API request") :
template<typename... Args>
Error(int c = HTTP_STATUS_INTERNAL_SERVER_ERROR, const std::string &msg = "Invalid API request", Args&&... args) :
RuntimeError(msg, std::forward<Args>(args)...),
code(c),
json(nullptr)
{ }
template<typename... Args>
Error(int c = HTTP_STATUS_INTERNAL_SERVER_ERROR, const std::string &msg = "Invalid API request", const char *fmt = nullptr, Args&&... args) :
RuntimeError(msg),
code(c)
code(c),
json(fmt
? json_pack(fmt, std::forward<Args>(args)...)
: nullptr
)
{ }
int code;
json_t *json;
};
class BadRequest : public Error {
public:
BadRequest(const std::string &msg = "Bad API request") :
Error(HTTP_STATUS_BAD_REQUEST, msg)
template<typename... Args>
BadRequest(const std::string &msg = "Bad API request", Args&&... args) :
Error(HTTP_STATUS_BAD_REQUEST, msg, std::forward<Args>(args)...)
{ }
};

View file

@ -56,16 +56,20 @@ public:
if (ret) {
node = vlist_lookup_name<struct vnode>(nodes, matches[1].str());
if (!node)
throw BadRequest("Unknown node");
throw BadRequest("Unknown node", "{ s: s }",
"node", matches[1].str().c_str()
);
}
else {
node = vlist_lookup_uuid<struct vnode>(nodes, uuid);
if (!node)
throw BadRequest("No node found with with matching UUID");
throw BadRequest("No node found with with matching UUID", "{ s: s }",
"uuid", matches[1].str().c_str()
);
}
}
};
} /* namespace api */
} /* namespace node */
} /* namespace villas */
} /* namespace villas */

View file

@ -52,15 +52,19 @@ public:
ret = uuid_parse(matches[1].str().c_str(), uuid);
if (ret)
throw BadRequest("Invalid UUID");
throw BadRequest("Invalid UUID", "{ s: s }",
"uuid", matches[1].str().c_str()
);
auto *paths = session->getSuperNode()->getPaths();
path = vlist_lookup_uuid<struct vpath>(paths, uuid);
if (!path)
throw BadRequest("No path found with with matching UUID");
throw BadRequest("No path found with with matching UUID", "{ s: s }",
"uuid", matches[1].str().c_str()
);
}
};
} /* namespace api */
} /* namespace node */
} /* namespace villas */
} /* namespace villas */

View file

@ -70,18 +70,21 @@ class ErrorResponse : public Response {
protected:
std::string error;
json_t *json;
public:
ErrorResponse(Session *s, const RuntimeError &e) :
Response(s),
error(e.what())
error(e.what()),
json(nullptr)
{
code = 500;
}
ErrorResponse(Session *s, const Error &e) :
Response(s),
error(e.what())
error(e.what()),
json(e.json)
{
code = e.code;
}

View file

@ -45,5 +45,8 @@ Request * RequestFactory::make(Session *s, const std::string &uri, Request::Meth
return p;
}
throw BadRequest("Unknown API request");
throw BadRequest("Unknown API request", "{ s: s, s: i }",
"uri", uri.c_str(),
"method", meth
);
}

View file

@ -48,7 +48,9 @@ public:
struct vnode_type *vt = node_type_lookup("file");
if (node->_vt != vt)
throw BadRequest("This node is not a file node");
throw BadRequest("This node is not a file node", "{ s: s }",
"type", node->_vt
);
struct file *f = (struct file *) node->_vd;

View file

@ -29,17 +29,17 @@
#include <villas/utils.hpp>
#include <villas/api.hpp>
#include <villas/api/session.hpp>
#include <villas/api/request.hpp>
#include <villas/api/node_request.hpp>
#include <villas/api/response.hpp>
namespace villas {
namespace node {
namespace api {
class StatsRequest : public Request {
class StatsRequest : public NodeRequest {
public:
using Request::Request;
using NodeRequest::NodeRequest;
virtual Response * execute()
{
@ -49,15 +49,7 @@ public:
if (body != nullptr)
throw BadRequest("Stats endpoint does not accept any body data");
const auto &nodeName = matches[1].str();
struct vlist *nodes = session->getSuperNode()->getNodes();
struct vnode *node = vlist_lookup_name<struct vnode>(nodes, nodeName.c_str());
if (!node)
throw BadRequest("Unknown node");
if (!node->stats)
if (node->stats == nullptr)
throw BadRequest("The statistics collection for this node is not enabled");
return new Response(session, node->stats->toJson());

View file

@ -29,51 +29,30 @@
#include <villas/utils.hpp>
#include <villas/api.hpp>
#include <villas/api/session.hpp>
#include <villas/api/request.hpp>
#include <villas/api/node_request.hpp>
#include <villas/api/response.hpp>
namespace villas {
namespace node {
namespace api {
class StatsRequest : public Request {
class StatsRequest : public NodeRequest {
public:
using Request::Request;
using NodeRequest::NodeRequest;
virtual Response * execute()
{
int ret;
json_error_t err;
if (method != Method::POST)
throw InvalidMethod(this);
if (body != nullptr)
throw BadRequest("Stats endpoint does not accept any body data");
if (node->stats == nullptr)
throw BadRequest("The statistics collection for this node is not enabled");
char *node = nullptr;
ret = json_unpack_ex(body, &err, 0, "{ s?: s }",
"node", &node
);
if (ret < 0)
throw Error();
struct vlist *nodes = session->getSuperNode()->getNodes();
for (size_t i = 0; i < vlist_length(nodes); i++) {
struct vnode *n = (struct vnode *) vlist_at(nodes, i);
if (node && strcmp(node, node_name(n)))
continue;
if (n->stats) {
n->stats->reset();
info("Stats resetted for node %s", node_name(n));
}
}
node->stats->reset();
return new Response(session);
}

View file

@ -71,7 +71,7 @@ public:
if (body) {
ret = json_unpack_ex(body, &err, 0, "{ s?: s }", "config", &cfg);
if (ret < 0)
throw Error();
throw BadRequest("Failed to parse request body");
}
/* If no config is provided via request, we will use the previous one */

View file

@ -41,7 +41,14 @@ Response::~Response()
json_t * ErrorResponse::toJson()
{
return json_pack("{ s: s }",
json_t *ret;
ret = json_pack("{ s: s }",
"error", error.c_str()
);
if (json)
json_object_update(ret, json);
return ret;
}