nicer error reporting

This commit is contained in:
Christian Grothoff 2015-07-08 09:40:13 +02:00
parent 296e27b92a
commit ea5c1233f1
4 changed files with 70 additions and 193 deletions

View File

@ -234,7 +234,11 @@ TMH_DEPOSIT_handler_deposit (struct TMH_RequestHandler *rh,
json_t *wire; json_t *wire;
int res; int res;
struct TALER_Amount amount; struct TALER_Amount amount;
json_t *f; struct TMH_PARSE_FieldSpecification spec[] = {
TMH_PARSE_member_object ("wire", &wire),
TMH_PARSE_member_amount ("f", &amount),
TMH_PARSE_MEMBER_END
};
res = TMH_PARSE_post_json (connection, res = TMH_PARSE_post_json (connection,
connection_cls, connection_cls,
@ -245,39 +249,19 @@ TMH_DEPOSIT_handler_deposit (struct TMH_RequestHandler *rh,
return MHD_NO; return MHD_NO;
if ( (GNUNET_NO == res) || (NULL == json) ) if ( (GNUNET_NO == res) || (NULL == json) )
return MHD_YES; return MHD_YES;
if (-1 == json_unpack (json, res = TMH_PARSE_json_data (connection,
"{s:o, s:o}", json,
"wire", &wire, spec);
"f", &f)) if (GNUNET_OK != res)
{ {
GNUNET_break_op (0);
json_decref (json); json_decref (json);
return TMH_RESPONSE_reply_json_pack (connection, return (GNUNET_NO == res) ? MHD_YES : MHD_NO;
MHD_HTTP_BAD_REQUEST,
"{s:s}",
"error", "Bad format");
}
res = TMH_PARSE_amount_json (connection,
f,
&amount);
json_decref (f);
if (GNUNET_SYSERR == res)
{
json_decref (wire);
json_decref (json);
return MHD_NO;
}
if (GNUNET_NO == res)
{
json_decref (wire);
json_decref (json);
return MHD_YES;
} }
res = parse_and_handle_deposit_request (connection, res = parse_and_handle_deposit_request (connection,
json, json,
&amount, &amount,
wire); wire);
json_decref (wire); TMH_PARSE_release_data (spec);
json_decref (json); json_decref (json);
return res; return res;
} }

View File

@ -771,9 +771,37 @@ TMH_PARSE_navigate_json (struct MHD_Connection *connection,
{ {
struct TALER_Amount *where = va_arg (argp, void *); struct TALER_Amount *where = va_arg (argp, void *);
ret = TMH_PARSE_amount_json (connection, if (GNUNET_OK !=
(json_t *) root, TALER_json_to_amount ((json_t *) root,
where); where))
{
if (MHD_YES !=
TMH_RESPONSE_reply_json_pack (connection,
MHD_HTTP_BAD_REQUEST,
"{s:s, s:o}",
"error", "Bad format",
"path", path))
return GNUNET_SYSERR;
return GNUNET_NO;
}
if (0 != strcmp (where->currency,
TMH_mint_currency_string))
{
if (MHD_YES !=
TMH_RESPONSE_reply_json_pack (connection,
MHD_HTTP_BAD_REQUEST,
"{s:s, s:o, s:s}",
"error", "Currency not supported",
"path", path,
"currency", where->currency))
{
memset (where, 0, sizeof (struct TALER_Amount));
return GNUNET_SYSERR;
}
memset (where, 0, sizeof (struct TALER_Amount));
return GNUNET_NO;
}
ret = GNUNET_OK;
break; break;
} }
@ -781,9 +809,21 @@ TMH_PARSE_navigate_json (struct MHD_Connection *connection,
{ {
struct GNUNET_TIME_Absolute *where = va_arg (argp, void *); struct GNUNET_TIME_Absolute *where = va_arg (argp, void *);
ret = TMH_PARSE_time_abs_json (connection, if (GNUNET_OK !=
(json_t *) root, TALER_json_to_abs ((json_t *) root,
where); where))
{
if (MHD_YES !=
TMH_RESPONSE_reply_json_pack (connection,
MHD_HTTP_BAD_REQUEST,
"{s:s, s:s, s:o}",
"error", "Bad format",
"hint", "expected absolute time",
"path", path))
return GNUNET_SYSERR;
return GNUNET_NO;
}
ret = GNUNET_OK;
break; break;
} }
@ -940,129 +980,6 @@ TMH_PARSE_release_data (struct TMH_PARSE_FieldSpecification *spec)
} }
/**
* Parse absolute time specified in JSON format. The JSON format is
* "/Date(TIMEVAL)/" where TIMEVAL is in seconds after the Unix Epoch.
* Additionally, we support "/forever/" and "/never/" to represent the
* end of time.
*
* @param connection the MHD connection (to report errors)
* @param f json specification of the amount
* @param[out] time set to the time specified in @a f
* @return
* #GNUNET_YES if parsing was successful
* #GNUNET_NO if json is malformed, error response was generated
* #GNUNET_SYSERR on internal error, error response was not generated
*/
int
TMH_PARSE_time_abs_json (struct MHD_Connection *connection,
json_t *f,
struct GNUNET_TIME_Absolute *time)
{
const char *val;
unsigned long long tval;
val = json_string_value (f);
if (NULL == val)
{
if (MHD_YES !=
TMH_RESPONSE_reply_json_pack (connection,
MHD_HTTP_BAD_REQUEST,
"{s:s}",
"error", "string expected"))
return GNUNET_SYSERR;
return GNUNET_NO;
}
if ( (0 == strcasecmp (val,
"/forever/")) ||
(0 == strcasecmp (val,
"/never/")) )
{
*time = GNUNET_TIME_UNIT_FOREVER_ABS;
return GNUNET_OK;
}
if (1 != sscanf (val,
"/Date(%llu)/",
&tval))
{
if (MHD_YES !=
TMH_RESPONSE_reply_json_pack (connection,
MHD_HTTP_BAD_REQUEST,
"{s:s, s:s}",
"error", "timestamp expected",
"value", val))
return GNUNET_SYSERR;
return GNUNET_NO;
}
/* Time is in seconds in JSON, but in microseconds in GNUNET_TIME_Absolute */
time->abs_value_us = tval * 1000LL * 1000LL;
if ( (time->abs_value_us) / 1000LL / 1000LL != tval)
{
/* Integer overflow */
if (MHD_YES !=
TMH_RESPONSE_reply_json_pack (connection,
MHD_HTTP_BAD_REQUEST,
"{s:s, s:s}",
"error", "timestamp outside of legal range",
"value", val))
return GNUNET_SYSERR;
return GNUNET_NO;
}
return GNUNET_OK;
}
/**
* Parse amount specified in JSON format.
*
* @param connection the MHD connection (to report errors)
* @param f json specification of the amount
* @param[out] amount set to the amount specified in @a f
* @return
* #GNUNET_YES if parsing was successful
* #GNUNET_NO if json is malformed, error response was generated
* #GNUNET_SYSERR on internal error, error response was not generated
*/
int
TMH_PARSE_amount_json (struct MHD_Connection *connection,
json_t *f,
struct TALER_Amount *amount)
{
if (GNUNET_OK !=
TALER_json_to_amount (f,
amount))
{
TALER_LOG_WARNING ("Failed to parse JSON amount specification\n");
if (MHD_YES !=
TMH_RESPONSE_reply_json_pack (connection,
MHD_HTTP_BAD_REQUEST,
"{s:s}",
"error", "Bad format"))
return GNUNET_SYSERR;
return GNUNET_NO;
}
if (0 != strcmp (amount->currency,
TMH_mint_currency_string))
{
TALER_LOG_WARNING ("Currency specified not supported by this mint\n");
if (MHD_YES !=
TMH_RESPONSE_reply_json_pack (connection,
MHD_HTTP_BAD_REQUEST,
"{s:s, s:s}",
"error", "Currency not supported",
"currency", amount->currency))
{
memset (amount, 0, sizeof (struct TALER_Amount));
return GNUNET_SYSERR;
}
memset (amount, 0, sizeof (struct TALER_Amount));
return GNUNET_NO;
}
return GNUNET_OK;
}
/** /**
* Generate line in parser specification for 64-bit integer * Generate line in parser specification for 64-bit integer
* given as an integer in JSON. * given as an integer in JSON.

View File

@ -352,42 +352,6 @@ TMH_PARSE_member_time_abs (const char *field,
#define TMH_PARSE_MEMBER_END { NULL, NULL, 0, 0, TMH_PARSE_JNC_FIELD, 0 } #define TMH_PARSE_MEMBER_END { NULL, NULL, 0, 0, TMH_PARSE_JNC_FIELD, 0 }
/**
* Parse amount specified in JSON format.
*
* @param connection the MHD connection (to report errors)
* @param f json specification of the amount
* @param[out] amount set to the amount specified in @a f
* @return
* #GNUNET_YES if parsing was successful
* #GNUNET_NO if json is malformed, error response was generated
* #GNUNET_SYSERR on internal error, error response was not generated
*/
int
TMH_PARSE_amount_json (struct MHD_Connection *connection,
json_t *f,
struct TALER_Amount *amount);
/**
* Parse absolute time specified in JSON format. The JSON format is
* "/TIMEVAL/" where TIMEVAL is in seconds. Additionally, we
* support "/forever/" and "/never/" to represent the end of time.
*
* @param connection the MHD connection (to report errors)
* @param f json specification of the amount
* @param[out] time set to the time specified in @a f
* @return
* #GNUNET_YES if parsing was successful
* #GNUNET_NO if json is malformed, error response was generated
* #GNUNET_SYSERR on internal error, error response was not generated
*/
int
TMH_PARSE_time_abs_json (struct MHD_Connection *connection,
json_t *f,
struct GNUNET_TIME_Absolute *time);
/** /**
* Extraxt fixed-size base32crockford encoded data from request. * Extraxt fixed-size base32crockford encoded data from request.
* *

View File

@ -297,7 +297,19 @@ TALER_json_to_amount (json_t *json,
"fraction", &fraction, "fraction", &fraction,
"currency", &currency)) "currency", &currency))
{ {
char *json_enc;
GNUNET_break_op (0); GNUNET_break_op (0);
if (NULL == (json_enc = json_dumps (json,
JSON_COMPACT | JSON_SORT_KEYS | JSON_ENCODE_ANY)))
{
GNUNET_break (0);
return GNUNET_SYSERR;
}
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Malformed JSON amount: %s\n",
json_enc);
free (json_enc);
return GNUNET_SYSERR; return GNUNET_SYSERR;
} }
if ( (value < 0) || if ( (value < 0) ||
@ -415,7 +427,7 @@ TALER_hash_json (json_t *json,
GNUNET_CRYPTO_hash (wire_enc, GNUNET_CRYPTO_hash (wire_enc,
len, len,
hc); hc);
GNUNET_free (wire_enc); free (wire_enc);
return GNUNET_OK; return GNUNET_OK;
} }