commit 702b929080885825309044348d24559471cd46a9
parent 728c4fd49e63140895575fbb30f0fd9cbaacee65
Author: Christian Grothoff <christian@grothoff.org>
Date: Sat, 4 Apr 2026 23:24:14 +0200
de-duplicate 451 response parsing logic
Diffstat:
10 files changed, 108 insertions(+), 252 deletions(-)
diff --git a/src/include/taler/taler-exchange/common.h b/src/include/taler/taler-exchange/common.h
@@ -112,6 +112,19 @@ struct TALER_EXCHANGE_KycNeededRedirect
/**
+ * We received an #MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS response code.
+ * Parse the JSON response and initialize the @a uflr object.
+ *
+ * @param[out] uflr data structure to initialize
+ * @param j JSON response to parse
+ * @return #GNUNET_OK on success
+ */
+enum GNUNET_GenericReturnValue
+TALER_EXCHANGE_parse_451 (struct TALER_EXCHANGE_KycNeededRedirect *uflr,
+ const json_t *j);
+
+
+/**
* Information about a coin to be deposited into a purse or reserve.
*/
struct TALER_EXCHANGE_PurseDeposit
diff --git a/src/lib/exchange_api_common.c b/src/lib/exchange_api_common.c
@@ -707,4 +707,49 @@ TALER_EXCHANGE_keys_test_account_allowed (
}
+/**
+ * We received an #MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS response code.
+ * Parse the JSON response and initialize the @a uflr object.
+ *
+ * @param[out] uflr data structure to initialize
+ * @param j JSON response to parse
+ * @return #GNUNET_OK on success
+ */
+enum GNUNET_GenericReturnValue
+TALER_EXCHANGE_parse_451 (struct TALER_EXCHANGE_KycNeededRedirect *uflr,
+ const json_t *j)
+{
+ struct GNUNET_JSON_Specification spec[] = {
+ GNUNET_JSON_spec_fixed_auto (
+ "h_payto",
+ &uflr->h_payto),
+ GNUNET_JSON_spec_uint64 (
+ "requirement_row",
+ &uflr->requirement_row),
+ GNUNET_JSON_spec_mark_optional (
+ GNUNET_JSON_spec_fixed_auto (
+ "account_pub",
+ &uflr->account_pub),
+ NULL),
+ GNUNET_JSON_spec_mark_optional (
+ GNUNET_JSON_spec_bool (
+ "bad_kyc_auth",
+ &uflr->bad_kyc_auth),
+ NULL),
+ GNUNET_JSON_spec_end ()
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_JSON_parse (j,
+ spec,
+ NULL,
+ NULL))
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+ return GNUNET_OK;
+}
+
+
/* end of exchange_api_common.c */
diff --git a/src/lib/exchange_api_post-batch-deposit.c b/src/lib/exchange_api_post-batch-deposit.c
@@ -560,37 +560,16 @@ handle_deposit_finished (void *cls,
dr->hr.hint = TALER_JSON_get_error_hint (j);
break;
case MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS:
+ dr->hr.ec = TALER_JSON_get_error_code (j);
+ dr->hr.hint = TALER_JSON_get_error_hint (j);
+ if (GNUNET_OK !=
+ TALER_EXCHANGE_parse_451 (&dr->details.unavailable_for_legal_reasons,
+ j))
{
- struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_fixed_auto (
- "h_payto",
- &dr->details.unavailable_for_legal_reasons.h_payto),
- GNUNET_JSON_spec_uint64 (
- "requirement_row",
- &dr->details.unavailable_for_legal_reasons.requirement_row),
- GNUNET_JSON_spec_mark_optional (
- GNUNET_JSON_spec_fixed_auto (
- "account_pub",
- &dr->details.unavailable_for_legal_reasons.account_pub),
- NULL),
- GNUNET_JSON_spec_mark_optional (
- GNUNET_JSON_spec_bool (
- "bad_kyc_auth",
- &dr->details.unavailable_for_legal_reasons.bad_kyc_auth),
- NULL),
- GNUNET_JSON_spec_end ()
- };
-
- if (GNUNET_OK !=
- GNUNET_JSON_parse (j,
- spec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- dr->hr.http_status = 0;
- dr->hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
- break;
- }
+ GNUNET_break_op (0);
+ dr->hr.http_status = 0;
+ dr->hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
+ break;
}
break;
case MHD_HTTP_INTERNAL_SERVER_ERROR:
diff --git a/src/lib/exchange_api_post-kyc-wallet.c b/src/lib/exchange_api_post-kyc-wallet.c
@@ -149,39 +149,18 @@ handle_kyc_wallet_finished (void *cls,
ks.hr.ec = TALER_JSON_get_error_code (j);
break;
case MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS:
+ ks.hr.ec = TALER_JSON_get_error_code (j);
+ ks.hr.hint = TALER_JSON_get_error_hint (j);
+ if (GNUNET_OK !=
+ TALER_EXCHANGE_parse_451 (&ks.details.unavailable_for_legal_reasons,
+ j))
{
- struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_fixed_auto (
- "h_payto",
- &ks.details.unavailable_for_legal_reasons.h_payto),
- GNUNET_JSON_spec_uint64 (
- "requirement_row",
- &ks.details.unavailable_for_legal_reasons.requirement_row),
- GNUNET_JSON_spec_mark_optional (
- GNUNET_JSON_spec_fixed_auto (
- "account_pub",
- &ks.details.unavailable_for_legal_reasons.account_pub),
- NULL),
- GNUNET_JSON_spec_mark_optional (
- GNUNET_JSON_spec_bool (
- "bad_kyc_auth",
- &ks.details.unavailable_for_legal_reasons.bad_kyc_auth),
- NULL),
- GNUNET_JSON_spec_end ()
- };
-
- if (GNUNET_OK !=
- GNUNET_JSON_parse (j,
- spec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- ks.hr.http_status = 0;
- ks.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
- break;
- }
+ GNUNET_break_op (0);
+ ks.hr.http_status = 0;
+ ks.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
break;
}
+ break;
case MHD_HTTP_INTERNAL_SERVER_ERROR:
ks.hr.ec = TALER_JSON_get_error_code (j);
/* Server had an internal issue; we should retry, but this API
diff --git a/src/lib/exchange_api_post-purses-PURSE_PUB-merge.c b/src/lib/exchange_api_post-purses-PURSE_PUB-merge.c
@@ -269,37 +269,16 @@ handle_purse_merge_finished (void *cls,
dr.hr.hint = TALER_JSON_get_error_hint (j);
break;
case MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS:
+ dr.hr.ec = TALER_JSON_get_error_code (j);
+ dr.hr.hint = TALER_JSON_get_error_hint (j);
+ if (GNUNET_OK !=
+ TALER_EXCHANGE_parse_451 (&dr.details.unavailable_for_legal_reasons,
+ j))
{
- struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_fixed_auto (
- "h_payto",
- &dr.details.unavailable_for_legal_reasons.h_payto),
- GNUNET_JSON_spec_uint64 (
- "requirement_row",
- &dr.details.unavailable_for_legal_reasons.requirement_row),
- GNUNET_JSON_spec_mark_optional (
- GNUNET_JSON_spec_fixed_auto (
- "account_pub",
- &dr.details.unavailable_for_legal_reasons.account_pub),
- NULL),
- GNUNET_JSON_spec_mark_optional (
- GNUNET_JSON_spec_bool (
- "bad_kyc_auth",
- &dr.details.unavailable_for_legal_reasons.bad_kyc_auth),
- NULL),
- GNUNET_JSON_spec_end ()
- };
-
- if (GNUNET_OK !=
- GNUNET_JSON_parse (j,
- spec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- dr.hr.http_status = 0;
- dr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
- break;
- }
+ GNUNET_break_op (0);
+ dr.hr.http_status = 0;
+ dr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
+ break;
}
break;
case MHD_HTTP_INTERNAL_SERVER_ERROR:
diff --git a/src/lib/exchange_api_post-reserves-RESERVE_PUB-close.c b/src/lib/exchange_api_post-reserves-RESERVE_PUB-close.c
@@ -137,49 +137,6 @@ handle_reserves_close_ok (struct TALER_EXCHANGE_PostReservesCloseHandle *prch,
/**
- * We received an #MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS close code. Handle the JSON
- * response.
- *
- * @param prch handle of the request
- * @param j JSON response
- * @return #GNUNET_OK on success
- */
-static enum GNUNET_GenericReturnValue
-handle_reserves_close_kyc (struct TALER_EXCHANGE_PostReservesCloseHandle *prch,
- const json_t *j)
-{
- struct TALER_EXCHANGE_PostReservesCloseResponse rs = {
- .hr.reply = j,
- .hr.http_status = MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS,
- };
- struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_fixed_auto (
- "h_payto",
- &rs.details.unavailable_for_legal_reasons.h_payto),
- GNUNET_JSON_spec_uint64 (
- "requirement_row",
- &rs.details.unavailable_for_legal_reasons.requirement_row),
- GNUNET_JSON_spec_end ()
- };
-
- if (GNUNET_OK !=
- GNUNET_JSON_parse (j,
- spec,
- NULL,
- NULL))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- prch->cb (prch->cb_cls,
- &rs);
- prch->cb = NULL;
- GNUNET_JSON_parse_free (spec);
- return GNUNET_OK;
-}
-
-
-/**
* Function called when we're done processing the
* HTTP /reserves/$RID/close request.
*
@@ -241,9 +198,11 @@ handle_reserves_close_finished (void *cls,
rs.hr.hint = TALER_JSON_get_error_hint (j);
break;
case MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS:
+ rs.hr.ec = TALER_JSON_get_error_code (j);
+ rs.hr.hint = TALER_JSON_get_error_hint (j);
if (GNUNET_OK !=
- handle_reserves_close_kyc (prch,
- j))
+ TALER_EXCHANGE_parse_451 (&rs.details.unavailable_for_legal_reasons,
+ j))
{
GNUNET_break_op (0);
rs.hr.http_status = 0;
diff --git a/src/lib/exchange_api_post-reserves-RESERVE_PUB-open.c b/src/lib/exchange_api_post-reserves-RESERVE_PUB-open.c
@@ -213,49 +213,6 @@ handle_reserves_open_pr (struct TALER_EXCHANGE_PostReservesOpenHandle *proh,
/**
- * We received an #MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS open code. Handle the JSON
- * response.
- *
- * @param proh handle of the request
- * @param j JSON response
- * @return #GNUNET_OK on success
- */
-static enum GNUNET_GenericReturnValue
-handle_reserves_open_kyc (struct TALER_EXCHANGE_PostReservesOpenHandle *proh,
- const json_t *j)
-{
- struct TALER_EXCHANGE_PostReservesOpenResponse rs = {
- .hr.reply = j,
- .hr.http_status = MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS,
- };
- struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_fixed_auto (
- "h_payto",
- &rs.details.unavailable_for_legal_reasons.h_payto),
- GNUNET_JSON_spec_uint64 (
- "requirement_row",
- &rs.details.unavailable_for_legal_reasons.requirement_row),
- GNUNET_JSON_spec_end ()
- };
-
- if (GNUNET_OK !=
- GNUNET_JSON_parse (j,
- spec,
- NULL,
- NULL))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- proh->cb (proh->cb_cls,
- &rs);
- proh->cb = NULL;
- GNUNET_JSON_parse_free (spec);
- return GNUNET_OK;
-}
-
-
-/**
* Function called when we're done processing the
* HTTP /reserves/$RID/open request.
*
@@ -366,16 +323,6 @@ handle_reserves_open_finished (void *cls,
rs.hr.hint = TALER_JSON_get_error_hint (j);
break;
}
- case MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS:
- if (GNUNET_OK !=
- handle_reserves_open_kyc (proh,
- j))
- {
- GNUNET_break_op (0);
- rs.hr.http_status = 0;
- rs.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
- }
- break;
case MHD_HTTP_INTERNAL_SERVER_ERROR:
/* Server had an internal issue; we should retry, but this API
leaves this to the application */
diff --git a/src/lib/exchange_api_post-reserves-RESERVE_PUB-purse.c b/src/lib/exchange_api_post-reserves-RESERVE_PUB-purse.c
@@ -344,37 +344,16 @@ handle_purse_create_with_merge_finished (void *cls,
dr.hr.hint = TALER_JSON_get_error_hint (j);
break;
case MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS:
+ dr.hr.ec = TALER_JSON_get_error_code (j);
+ dr.hr.hint = TALER_JSON_get_error_hint (j);
+ if (GNUNET_OK !=
+ TALER_EXCHANGE_parse_451 (&dr.details.unavailable_for_legal_reasons,
+ j))
{
- struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_fixed_auto (
- "h_payto",
- &dr.details.unavailable_for_legal_reasons.h_payto),
- GNUNET_JSON_spec_uint64 (
- "requirement_row",
- &dr.details.unavailable_for_legal_reasons.requirement_row),
- GNUNET_JSON_spec_mark_optional (
- GNUNET_JSON_spec_fixed_auto (
- "account_pub",
- &dr.details.unavailable_for_legal_reasons.account_pub),
- NULL),
- GNUNET_JSON_spec_mark_optional (
- GNUNET_JSON_spec_bool (
- "bad_kyc_auth",
- &dr.details.unavailable_for_legal_reasons.bad_kyc_auth),
- NULL),
- GNUNET_JSON_spec_end ()
- };
-
- if (GNUNET_OK !=
- GNUNET_JSON_parse (j,
- spec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- dr.hr.http_status = 0;
- dr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
- break;
- }
+ GNUNET_break_op (0);
+ dr.hr.http_status = 0;
+ dr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
+ break;
}
break;
case MHD_HTTP_INTERNAL_SERVER_ERROR:
diff --git a/src/lib/exchange_api_post-withdraw.c b/src/lib/exchange_api_post-withdraw.c
@@ -385,7 +385,7 @@ copy_results (
break;
}
case MHD_HTTP_CREATED:
- resp.details.created = wbr->details.created;
+ resp.details.created = wbr->details.created;
break;
case MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS:
resp.details.unavailable_for_legal_reasons =
diff --git a/src/lib/exchange_api_post-withdraw_blinded.c b/src/lib/exchange_api_post-withdraw_blinded.c
@@ -441,42 +441,18 @@ handle_withdraw_blinded_finished (
wbr.hr.hint = TALER_JSON_get_error_hint (j_response);
break;
case MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS:
- /* only validate reply is well-formed */
+ wbr.hr.ec = TALER_JSON_get_error_code (j_response);
+ wbr.hr.hint = TALER_JSON_get_error_hint (j_response);
+ if (GNUNET_OK !=
+ TALER_EXCHANGE_parse_451 (&wbr.details.unavailable_for_legal_reasons,
+ j_response))
{
- struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_fixed_auto (
- "h_payto",
- &wbr.details.unavailable_for_legal_reasons.h_payto),
- GNUNET_JSON_spec_uint64 (
- "requirement_row",
- &wbr.details.unavailable_for_legal_reasons.requirement_row),
- GNUNET_JSON_spec_mark_optional (
- GNUNET_JSON_spec_fixed_auto (
- "account_pub",
- &wbr.details.unavailable_for_legal_reasons.account_pub),
- NULL),
- GNUNET_JSON_spec_mark_optional (
- GNUNET_JSON_spec_bool (
- "bad_kyc_auth",
- &wbr.details.unavailable_for_legal_reasons.bad_kyc_auth),
- NULL),
- GNUNET_JSON_spec_end ()
- };
-
- wbr.hr.ec = TALER_JSON_get_error_code (j_response);
- wbr.hr.hint = TALER_JSON_get_error_hint (j_response);
- if (GNUNET_OK !=
- GNUNET_JSON_parse (j_response,
- spec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- wbr.hr.http_status = 0;
- wbr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
- break;
- }
+ GNUNET_break_op (0);
+ wbr.hr.http_status = 0;
+ wbr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
break;
}
+ break;
case MHD_HTTP_INTERNAL_SERVER_ERROR:
/* Server had an internal issue; we should retry, but this API
leaves this to the application */