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:
parent
c7f96e1a97
commit
e59cd8ac15
10 changed files with 64 additions and 55 deletions
|
@ -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)...)
|
||||
{ }
|
||||
};
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue