Improve debugabbility of JSON API

JSON API server uses standardized error handling based on
  std::error_condition for a few method, this improve debugabbility both
  from library size and from API client side
JSON API auth token are now more flexible, now the only proibition is using
  colon character ':' in user name
Implemented TO_JSON operation for std::error_condition
Avoid unkown serial job handling code duplication via fatalUnknownSerialJob
Usability improvement in t_RsLogger
Disable compilation of now unused is_alphanumeric
This commit is contained in:
Gioacchino Mazzurco 2020-01-27 21:22:49 +01:00
parent 9c65836503
commit 5dbbe1ffd7
No known key found for this signature in database
GPG key ID: A1FBCA3872E87051
9 changed files with 311 additions and 99 deletions

View file

@ -768,3 +768,37 @@ bool RsTypeSerializer::from_JSON( const std::string& memberName,
}
return ret;
}
void RsTypeSerializer::ErrConditionWrapper::serial_process(
RsGenericSerializer::SerializeJob j,
RsGenericSerializer::SerializeContext& ctx )
{
switch(j)
{
case RsGenericSerializer::SIZE_ESTIMATE: // fallthrough
case RsGenericSerializer::DESERIALIZE: // fallthrough
case RsGenericSerializer::SERIALIZE: // fallthrough
case RsGenericSerializer::FROM_JSON:
RsFatal() << __PRETTY_FUNCTION__ << " SerializeJob: " << j
<< "is not supported on std::error_condition " << std::endl;
print_stacktrace();
exit(-2);
case RsGenericSerializer::PRINT: // fallthrough
case RsGenericSerializer::TO_JSON:
{
constexpr RsGenericSerializer::SerializeJob rj =
RsGenericSerializer::TO_JSON;
int32_t tNum = mec.value();
RsTypeSerializer::serial_process(rj, ctx, tNum, "errorNumber");
std::string tStr = mec.category().name();
RsTypeSerializer::serial_process(rj, ctx, tStr, "errorCategory");
tStr = mec.message();
RsTypeSerializer::serial_process(rj, ctx, tStr, "errorMessage");
break;
}
default: RsTypeSerializer::fatalUnknownSerialJob(j);
}
}

View file

@ -22,6 +22,12 @@
*******************************************************************************/
#pragma once
#include <typeinfo> // for typeid
#include <type_traits>
#include <errno.h>
#include <system_error>
#include "serialiser/rsserial.h"
#include "serialiser/rstlvbase.h"
#include "serialiser/rstlvlist.h"
@ -34,11 +40,6 @@
#include "util/rsjson.h"
#include "util/rsdebug.h"
#include <typeinfo> // for typeid
#include <type_traits>
#include <errno.h>
/* INTERNAL ONLY helper to avoid copy paste code for std::{vector,list,set}<T>
* Can't use a template function because T is needed for const_cast */
#define RsTypeSerializer_PRIVATE_TO_JSON_ARRAY() do \
@ -132,7 +133,12 @@ struct RsTypeSerializer
/// Generic types
template<typename T>
typename std::enable_if<std::is_same<RsTlvItem,T>::value || !(std::is_base_of<RsSerializable,T>::value || std::is_enum<T>::value || std::is_base_of<RsTlvItem,T>::value )>::type
typename
std::enable_if< std::is_same<RsTlvItem,T>::value || !(
std::is_base_of<RsSerializable,T>::value ||
std::is_enum<T>::value ||
std::is_base_of<RsTlvItem,T>::value ||
std::is_same<std::error_condition,T>::value ) >::type
static /*void*/ serial_process( RsGenericSerializer::SerializeJob j,
RsGenericSerializer::SerializeContext& ctx,
T& member, const std::string& member_name )
@ -160,11 +166,7 @@ struct RsTypeSerializer
ctx.mOk &= (ctx.mOk || ctx.mFlags & RsGenericSerializer::SERIALIZATION_FLAG_YIELDING)
&& from_JSON(member_name, member, ctx.mJson);
break;
default:
std::cerr << __PRETTY_FUNCTION__ << " Unknown serial job: "
<< static_cast<std::underlying_type<decltype(j)>::type>(j)
<< std::endl;
exit(EINVAL);
default: fatalUnknownSerialJob(j);
}
}
@ -200,11 +202,7 @@ struct RsTypeSerializer
(ctx.mOk || ctx.mFlags & RsGenericSerializer::SERIALIZATION_FLAG_YIELDING)
&& from_JSON(member_name, type_id, member, ctx.mJson);
break;
default:
std::cerr << __PRETTY_FUNCTION__ << " Unknown serial job: "
<< static_cast<std::underlying_type<decltype(j)>::type>(j)
<< std::endl;
exit(EINVAL);
default: fatalUnknownSerialJob(j);
}
}
@ -362,11 +360,7 @@ struct RsTypeSerializer
}
break;
}
default:
std::cerr << __PRETTY_FUNCTION__ << " Unknown serial job: "
<< static_cast<std::underlying_type<decltype(j)>::type>(j)
<< std::endl;
exit(EINVAL);
default: fatalUnknownSerialJob(j);
}
}
@ -441,12 +435,7 @@ struct RsTypeSerializer
break;
}
default:
std::cerr << __PRETTY_FUNCTION__ << " Unknown serial job: "
<< static_cast<std::underlying_type<decltype(j)>::type>(j)
<< std::endl;
exit(EINVAL);
break;
default: fatalUnknownSerialJob(j);
}
}
@ -505,7 +494,7 @@ struct RsTypeSerializer
case RsGenericSerializer::FROM_JSON:
RsTypeSerializer_PRIVATE_FROM_JSON_ARRAY(push_back);
break;
default: break;
default: fatalUnknownSerialJob(j);
}
}
@ -564,7 +553,7 @@ struct RsTypeSerializer
case RsGenericSerializer::FROM_JSON:
RsTypeSerializer_PRIVATE_FROM_JSON_ARRAY(insert);
break;
default: break;
default: fatalUnknownSerialJob(j);
}
}
@ -620,7 +609,7 @@ struct RsTypeSerializer
case RsGenericSerializer::FROM_JSON:
RsTypeSerializer_PRIVATE_FROM_JSON_ARRAY(push_back);
break;
default: break;
default: fatalUnknownSerialJob(j);
}
}
@ -663,7 +652,7 @@ struct RsTypeSerializer
&& (v = t_RsFlags32<N>(f), true);
break;
}
default: break;
default: fatalUnknownSerialJob(j);
}
}
@ -772,18 +761,15 @@ struct RsTypeSerializer
break;
}
default:
std::cerr << __PRETTY_FUNCTION__ << " Unknown serial job: "
<< static_cast<std::underlying_type<decltype(j)>::type>(j)
<< std::endl;
exit(EINVAL);
break;
default: fatalUnknownSerialJob(j);
}
}
/// RsTlvItem derivatives only
template<typename T>
typename std::enable_if<std::is_base_of<RsTlvItem,T>::value && !std::is_same<RsTlvItem,T>::value>::type
typename std::enable_if<
std::is_base_of<RsTlvItem,T>::value && !std::is_same<RsTlvItem,T>::value
>::type
static /*void*/ serial_process( RsGenericSerializer::SerializeJob j,
RsGenericSerializer::SerializeContext& ctx,
T& member,
@ -792,6 +778,21 @@ struct RsTypeSerializer
serial_process(j, ctx, static_cast<RsTlvItem&>(member), memberName);
}
/** std::error_condition
* supports only TO_JSON ErrConditionWrapper::serial_process will explode
* at runtime if a different SerializeJob is passed down */
template<typename T>
typename std::enable_if< std::is_base_of<std::error_condition,T>::value >::type
static /*void*/ serial_process(
RsGenericSerializer::SerializeJob j,
RsGenericSerializer::SerializeContext& ctx,
const T& cond,
const std::string& member_name )
{
ErrConditionWrapper ew(cond);
serial_process(j, ctx, ew, member_name);
}
protected:
//============================================================================//
@ -909,6 +910,27 @@ protected:
t_RsTlvList<TLV_CLASS,TLV_TYPE>& member,
RsJson& jDoc );
[[noreturn]] static void fatalUnknownSerialJob(int j)
{
RsFatal() << " Unknown serial job: " << j << std::endl;
print_stacktrace();
exit(EINVAL);
}
struct ErrConditionWrapper : RsSerializable
{
ErrConditionWrapper(const std::error_condition& ec): mec(ec) {}
/** supports only TO_JSON if a different SerializeJob is passed it will
* explode at runtime */
void serial_process(
RsGenericSerializer::SerializeJob j,
RsGenericSerializer::SerializeContext& ctx ) override;
private:
const std::error_condition& mec;
};
RS_SET_CONTEXT_DEBUG_LEVEL(1)
};